diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 84f2b753f..927d9498f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -161,6 +161,8 @@ public class Backend { public static boolean isFlywheelWorld(@Nullable LevelAccessor world) { if (world == null) return false; + if (!world.isClientSide()) return false; + if (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()) return true; return world == Minecraft.getInstance().level; diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index ced144d19..491ec3f06 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -91,7 +91,7 @@ public class Loader implements ResourceManagerReloadListener { ClientLevel world = Minecraft.getInstance().level; if (Backend.isFlywheelWorld(world)) { // TODO: looks like it might be good to have another event here - InstancedRenderDispatcher.loadAllInWorld(world); + InstancedRenderDispatcher.resetInstanceWorld(world); CrumblingRenderer.reset(); } } 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 cece70c00..2eee2f458 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -211,6 +211,10 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift } protected void processQueuedAdditions() { + if (queuedAdditions.isEmpty()) { + return; + } + ArrayList queued; synchronized (queuedAdditions) { @@ -218,7 +222,7 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift queuedAdditions.clear(); } - if (queued.size() > 0) { + if (!queued.isEmpty()) { queued.forEach(this::addInternal); } } @@ -304,4 +308,10 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift invalidate(); instancedTiles.forEach(this::add); } + + public void detachLightListeners() { + for (AbstractInstance value : instances.values()) { + LightUpdater.get(value.world).removeListener(value); + } + } } 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 cf6042576..f35437895 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -9,10 +9,8 @@ import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; -import com.jozufozu.flywheel.util.ChunkIter; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; @@ -60,17 +58,8 @@ public class InstanceWorld { */ public void delete() { engine.delete(); - } - - /** - * Instantiate all the necessary instances to render the given world. - */ - public void loadAll(ClientLevel world) { - ChunkIter.forEachChunk(world, chunk -> { - chunk.getBlockEntities().values().forEach(tileEntityInstanceManager::add); - }); - world.entitiesForRendering() - .forEach(entityInstanceManager::add); + entityInstanceManager.detachLightListeners(); + tileEntityInstanceManager.detachLightListeners(); } /** 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 f380bd2d0..8e59f6f15 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -88,13 +88,12 @@ public class InstancedRenderDispatcher { ClientLevel world = event.getWorld(); if (Backend.getInstance() .canUseInstancing() && world != null) { - loadAllInWorld(world); + resetInstanceWorld(world); } } - public static void loadAllInWorld(ClientLevel world) { - instanceWorlds.replace(world, InstanceWorld::delete) - .loadAll(world); + public static void resetInstanceWorld(ClientLevel world) { + instanceWorlds.replace(world, InstanceWorld::delete); } } diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 72900ab01..c91713235 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -3,14 +3,10 @@ package com.jozufozu.flywheel.event; import java.util.ArrayList; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.light.LightUpdater; -import com.jozufozu.flywheel.util.ChunkIter; import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.world.level.LevelAccessor; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.TickEvent; @@ -40,20 +36,9 @@ public class ForgeEvents { } } - @SubscribeEvent - public static void onLoadWorld(WorldEvent.Load event) { - LevelAccessor world = event.getWorld(); - - if (Backend.isFlywheelWorld(world)) { - InstancedRenderDispatcher.loadAllInWorld((ClientLevel) world); - } - } - @SubscribeEvent public static void unloadWorld(WorldEvent.Unload event) { - LevelAccessor world = event.getWorld(); - ChunkIter._unload(world); - WorldAttached.invalidateWorld(world); + WorldAttached.invalidateWorld(event.getWorld()); } @SubscribeEvent diff --git a/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java index e7f1dfaf6..e5a75fc54 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java @@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; @@ -20,11 +21,16 @@ import net.minecraftforge.api.distmarker.OnlyIn; public class ChunkRebuildHooksMixin { @Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true) - private void filterBlockEntity(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set set, E be, CallbackInfo ci) { + private void addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set set, E be, CallbackInfo ci) { - if (Backend.getInstance().canUseInstancing() && Backend.isFlywheelWorld(be.getLevel()) && InstancedRenderRegistry.getInstance() - .shouldSkipRender(be)) { - ci.cancel(); + if (Backend.getInstance().canUseInstancing() && Backend.isFlywheelWorld(be.getLevel())) { + + InstancedRenderRegistry registry = InstancedRenderRegistry.getInstance(); + if (registry.canInstance(be.getType())) + InstancedRenderDispatcher.getTiles(be.getLevel()).queueAdd(be); + + if (registry.shouldSkipRender(be)) + ci.cancel(); } } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LeakChunkStorageArrayMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LeakChunkStorageArrayMixin.java deleted file mode 100644 index 1a9bce762..000000000 --- a/src/main/java/com/jozufozu/flywheel/mixin/LeakChunkStorageArrayMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.jozufozu.flywheel.mixin; - -import java.util.concurrent.atomic.AtomicReferenceArray; - -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.jozufozu.flywheel.util.ChunkIter; - -import net.minecraft.client.multiplayer.ClientChunkCache; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -/** - * In order to iterate over all loaded chunks, we do something absolutely foul. - * - *

- * By stealing the reference to the backing array of the chunk storage when it is constructed, we gain 0 maintenance - * access to the full array of loaded chunks. - *

- */ -@OnlyIn(Dist.CLIENT) -@Mixin(targets = "net.minecraft.client.multiplayer.ClientChunkCache$Storage") -public class LeakChunkStorageArrayMixin { - - @Shadow - @Final - AtomicReferenceArray chunks; - - @Inject(method = "", at = @At("TAIL")) - private void leakBackingArray(ClientChunkCache outer, int chunkRadius, CallbackInfo ci) { - ChunkIter._putStorageReference(outer.getLevel(), chunks); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java b/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java deleted file mode 100644 index 3174368df..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/ChunkIter.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.jozufozu.flywheel.util; - -import java.util.WeakHashMap; -import java.util.concurrent.atomic.AtomicReferenceArray; -import java.util.function.Consumer; - -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -/** - * Helper class for iterating over all loaded chunks. - */ -@OnlyIn(Dist.CLIENT) -public class ChunkIter { - - private static final WeakHashMap> storages = new WeakHashMap<>(); - - /** - * Iterate over all loaded chunks in a level. - */ - public static void forEachChunk(BlockGetter level, Consumer consumer) { - AtomicReferenceArray storage = storages.get(level); - - if (storage == null) - return; - - for (int i = 0; i < storage.length(); i++) { - LevelChunk chunk = storage.get(i); - if (chunk != null) { - consumer.accept(chunk); - } - } - } - - // INTERNAL MAINTENANCE METHODS BELOW - - public static void _putStorageReference(BlockGetter level, AtomicReferenceArray storage) { - storages.put(level, storage); - } - - public static void _unload(BlockGetter world) { - storages.remove(world); - } -} diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 2d64420b7..537f77cd1 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.jozufozu.flywheel.mixin", - "compatibilityLevel": "JAVA_16", + "compatibilityLevel": "JAVA_17", "refmap": "flywheel.refmap.json", "client": [ "CancelEntityRenderMixin", @@ -10,7 +10,6 @@ "FixFabulousDepthMixin", "InstanceAddMixin", "InstanceRemoveMixin", - "LeakChunkStorageArrayMixin", "LevelRendererAccessor", "PausedPartialTickAccessor", "RenderHooksMixin",