From 5ff194cbc8b2da9d1a640c639c77419024c4fee5 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Wed, 29 Nov 2023 20:03:26 -0800 Subject: [PATCH] Re-reload - Rename ReloadRenderersEvent to ReloadLevelRendererEvent - Rename Engine#renderCrumblingInstances to #renderCrumbling - Make all mixin classes package-private and abstract - Make all event classes final and document which event bus they are posted on - Add EndClientResourceReloadEvent - Replace some usages of ReloadLevelRendererEvent with EndClientResourceReloadEvent, including ModelHolder and ModelCache - Always add all existing entities from world to VisualizationManagerImpl on construction if level is instanceof Level - Delete all VisualizationManagerImpls on resource reload - Improve MemoryBlock utility - Add MemoryBlock#copyTo(MemoryBlock) - Remove MemoryBlock#reallocTracked and make #realloc create a tracked block if and only if the existing block is tracked - Fix reallocating a debug memory block creating a regular memory block - Change BakedModelBufferer to only invoke the result consumer if the data is not empty - Improve BackendArgument - Fix classloading BackendArgument early causing it to return incomplete suggestions - Always allow specifying namespace, allow matching only by path, and always display suggested IDs with namespace --- .../java/com/jozufozu/flywheel/Flywheel.java | 26 ++++--- .../jozufozu/flywheel/api/backend/Engine.java | 6 +- .../flywheel/api/event/BeginFrameEvent.java | 5 +- .../event/EndClientResourceReloadEvent.java | 42 ++++++++++ ...ent.java => ReloadLevelRendererEvent.java} | 8 +- .../flywheel/api/event/RenderStageEvent.java | 5 +- .../com/jozufozu/flywheel/backend/Loader.java | 46 ----------- .../flywheel/backend/compile/FlwPrograms.java | 27 +++++++ .../backend/engine/AbstractInstancer.java | 7 +- .../backend/engine/InstancerStorage.java | 1 - .../backend/engine/UniformBuffer.java | 4 +- .../engine/batching/BatchingEngine.java | 2 +- .../backend/engine/batching/DrawBuffer.java | 4 +- .../engine/indirect/IndirectDrawManager.java | 52 +++++++------ .../engine/indirect/IndirectEngine.java | 2 +- .../instancing/InstancedDrawManager.java | 1 - .../engine/instancing/InstancedInstancer.java | 3 +- .../engine/instancing/InstancingEngine.java | 6 +- .../flywheel/config/BackendArgument.java | 56 ++++---------- .../jozufozu/flywheel/config/FlwConfig.java | 4 +- ...evelExtension.java => LevelExtension.java} | 14 ++-- .../jozufozu/flywheel/glsl/SourceFile.java | 2 +- .../flywheel/impl/BackendManagerImpl.java | 38 ++++++---- .../VisualizationManagerImpl.java | 30 ++++---- .../lib/memory/AbstractMemoryBlockImpl.java | 76 +++++++++++++++++++ .../lib/memory/DebugMemoryBlockImpl.java | 36 +++++++-- .../flywheel/lib/memory/FlwMemoryTracker.java | 3 - .../flywheel/lib/memory/MemoryBlock.java | 6 +- .../flywheel/lib/memory/MemoryBlockImpl.java | 72 +----------------- .../lib/memory/TrackedMemoryBlockImpl.java | 16 +++- .../flywheel/lib/model/ModelCache.java | 4 +- .../flywheel/lib/model/ModelHolder.java | 4 +- .../lib/model/baked/BakedModelBufferer.java | 48 +++++++----- .../lib/model/baked/BakedModelBuilder.java | 20 ++--- .../lib/model/baked/BlockModelBuilder.java | 20 ++--- .../model/baked/MultiBlockModelBuilder.java | 20 ++--- .../flywheel/lib/model/part/VertexWriter.java | 2 +- .../flywheel/lib/util/ResourceUtil.java | 37 ++++++++- .../flywheel/mixin/BlockEntityTypeMixin.java | 2 +- .../flywheel/mixin/BufferBuilderMixin.java | 2 +- .../flywheel/mixin/ClientLevelMixin.java | 13 +--- .../flywheel/mixin/EntityTypeMixin.java | 2 +- .../flywheel/mixin/FogUpdateMixin.java | 2 +- .../flywheel/mixin/GlStateManagerMixin.java | 2 +- .../jozufozu/flywheel/mixin/LevelMixin.java | 21 +++++ .../flywheel/mixin/LevelRendererMixin.java | 6 +- .../flywheel/mixin/LightUpdateMixin.java | 2 +- .../flywheel/mixin/MinecraftMixin.java | 37 +++++++++ .../flywheel/mixin/PoseStackMixin.java | 2 +- .../flywheel/mixin/RenderTypeMixin.java | 3 +- .../flywheel/mixin/VertexFormatMixin.java | 2 +- .../mixin/fix/FixFabulousDepthMixin.java | 2 +- .../mixin/fix/FixNormalScalingMixin.java | 2 +- .../sodium/ChunkBuilderMeshingTaskMixin.java | 4 +- .../visualmanage/ChunkRebuildHooksMixin.java | 2 +- .../mixin/visualmanage/VisualAddMixin.java | 2 +- .../mixin/visualmanage/VisualRemoveMixin.java | 2 +- .../mixin/visualmanage/VisualUpdateMixin.java | 2 +- .../vanilla/effect/ExampleEffect.java | 4 +- src/main/resources/flywheel.mixins.json | 2 + 60 files changed, 501 insertions(+), 372 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/api/event/EndClientResourceReloadEvent.java rename src/main/java/com/jozufozu/flywheel/api/event/{ReloadRenderersEvent.java => ReloadLevelRendererEvent.java} (62%) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/Loader.java rename src/main/java/com/jozufozu/flywheel/extension/{ClientLevelExtension.java => LevelExtension.java} (50%) create mode 100644 src/main/java/com/jozufozu/flywheel/lib/memory/AbstractMemoryBlockImpl.java create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/LevelMixin.java create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/MinecraftMixin.java diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 5314a2143..6d3d55d13 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -5,10 +5,10 @@ import java.util.ArrayList; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.slf4j.Logger; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent; import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.backend.Backends; -import com.jozufozu.flywheel.backend.Loader; +import com.jozufozu.flywheel.backend.compile.FlwPrograms; import com.jozufozu.flywheel.backend.compile.Pipelines; import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer; @@ -70,7 +70,7 @@ public class Flywheel { IEventBus forgeEventBus = MinecraftForge.EVENT_BUS; IEventBus modEventBus = FMLJavaModLoadingContext.get() .getModEventBus(); - modEventBus.addListener(Flywheel::setup); + modEventBus.addListener(Flywheel::onCommonSetup); FlwConfig.get().registerSpecs(modLoadingContext); @@ -85,7 +85,7 @@ public class Flywheel { private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) { forgeEventBus.addListener(Flywheel::addDebugInfo); - forgeEventBus.addListener(BackendManagerImpl::onReloadRenderers); + forgeEventBus.addListener(BackendManagerImpl::onReloadLevelRenderer); forgeEventBus.addListener(VisualizationEventHandler::onClientTick); forgeEventBus.addListener(VisualizationEventHandler::onBeginFrame); @@ -96,14 +96,17 @@ public class Flywheel { forgeEventBus.addListener(FlwCommands::registerClientCommands); forgeEventBus.addListener(DrawBuffer::onReloadRenderers); - forgeEventBus.addListener(UniformBuffer::onReloadRenderers); + forgeEventBus.addListener(UniformBuffer::onReloadLevelRenderer); forgeEventBus.addListener(LightUpdater::onClientTick); - forgeEventBus.addListener((ReloadRenderersEvent e) -> ModelCache.onReloadRenderers(e)); - forgeEventBus.addListener(ModelHolder::onReloadRenderers); forgeEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.onUnloadLevel(e)); - modEventBus.addListener(Flywheel::lateInit); + modEventBus.addListener(Flywheel::onClientSetup); + + modEventBus.addListener(BackendManagerImpl::onEndClientResourceReload); + + modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload(e)); + modEventBus.addListener(ModelHolder::onEndClientResourceReload); modEventBus.addListener(PartialModel::onModelRegistry); modEventBus.addListener(PartialModel::onModelBake); @@ -115,12 +118,12 @@ public class Flywheel { Pipelines.init(); Backends.init(); - Loader.init(); + FlwPrograms.ResourceReloadListener.register(); ShadersModHandler.init(); } - private static void lateInit(final FMLClientSetupEvent event) { + private static void onClientSetup(FMLClientSetupEvent event) { VertexTypes.init(); InstanceTypes.init(); Materials.init(); @@ -134,7 +137,8 @@ public class Flywheel { IdRegistryImpl.freezeAll(); } - private static void setup(final FMLCommonSetupEvent event) { + private static void onCommonSetup(FMLCommonSetupEvent event) { + // FIXME: argument types also need to be registered to BuiltInRegistries.COMMAND_ARGUMENT_TYPE ArgumentTypeInfos.registerByClass(BackendArgument.class, SingletonArgumentInfo.contextFree(() -> BackendArgument.INSTANCE)); } diff --git a/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java b/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java index 881cb060c..3e9b7bd59 100644 --- a/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java +++ b/src/main/java/com/jozufozu/flywheel/api/backend/Engine.java @@ -31,13 +31,13 @@ public interface Engine extends InstancerProvider { /** * Render the given instances as a crumbling overlay. *
- * This is guaranteed to be called between the first and last calls to {@link #renderStage}. + * This is guaranteed to be called between the first and last calls to {@link #renderStage} for the current frame. * * @param executor The task executor running the frame plan. * @param context The render context for this frame. - * @param crumblingBlocks The instances to render. + * @param crumblingBlocks The instances to render. This list is never empty. */ - void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List crumblingBlocks); + void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks); /** * Maintain the render origin to be within a certain distance from the camera in all directions, diff --git a/src/main/java/com/jozufozu/flywheel/api/event/BeginFrameEvent.java b/src/main/java/com/jozufozu/flywheel/api/event/BeginFrameEvent.java index 9a90f0fbd..dd1014bb8 100644 --- a/src/main/java/com/jozufozu/flywheel/api/event/BeginFrameEvent.java +++ b/src/main/java/com/jozufozu/flywheel/api/event/BeginFrameEvent.java @@ -2,7 +2,10 @@ package com.jozufozu.flywheel.api.event; import net.minecraftforge.eventbus.api.Event; -public class BeginFrameEvent extends Event { +/** + * This event is posted to the Forge event bus. + */ +public final class BeginFrameEvent extends Event { private final RenderContext context; public BeginFrameEvent(RenderContext context) { diff --git a/src/main/java/com/jozufozu/flywheel/api/event/EndClientResourceReloadEvent.java b/src/main/java/com/jozufozu/flywheel/api/event/EndClientResourceReloadEvent.java new file mode 100644 index 000000000..7ebabaa67 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/event/EndClientResourceReloadEvent.java @@ -0,0 +1,42 @@ +package com.jozufozu.flywheel.api.event; + +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; + +/** + * This event is posted to mod event buses. + */ +// TODO: This should not be a mod bus event. However, currently, it cannot be a Forge bus event since that bus is not started by the time this event needs to be posted. +public final class EndClientResourceReloadEvent extends Event implements IModBusEvent { + private final Minecraft minecraft; + private final ResourceManager resourceManager; + private final boolean initialReload; + private final Optional error; + + public EndClientResourceReloadEvent(Minecraft minecraft, ResourceManager resourceManager, boolean initialReload, Optional error) { + this.minecraft = minecraft; + this.resourceManager = resourceManager; + this.initialReload = initialReload; + this.error = error; + } + + public Minecraft getMinecraft() { + return minecraft; + } + + public ResourceManager getResourceManager() { + return resourceManager; + } + + public boolean isInitialReload() { + return initialReload; + } + + public Optional getError() { + return error; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/api/event/ReloadRenderersEvent.java b/src/main/java/com/jozufozu/flywheel/api/event/ReloadLevelRendererEvent.java similarity index 62% rename from src/main/java/com/jozufozu/flywheel/api/event/ReloadRenderersEvent.java rename to src/main/java/com/jozufozu/flywheel/api/event/ReloadLevelRendererEvent.java index 0206ed3ce..dd6c55d55 100644 --- a/src/main/java/com/jozufozu/flywheel/api/event/ReloadRenderersEvent.java +++ b/src/main/java/com/jozufozu/flywheel/api/event/ReloadLevelRendererEvent.java @@ -5,10 +5,14 @@ import org.jetbrains.annotations.Nullable; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraftforge.eventbus.api.Event; -public class ReloadRenderersEvent extends Event { +/** + * This event is posted to the Forge event bus. + */ +public final class ReloadLevelRendererEvent extends Event { + @Nullable private final ClientLevel level; - public ReloadRenderersEvent(ClientLevel level) { + public ReloadLevelRendererEvent(@Nullable ClientLevel level) { this.level = level; } diff --git a/src/main/java/com/jozufozu/flywheel/api/event/RenderStageEvent.java b/src/main/java/com/jozufozu/flywheel/api/event/RenderStageEvent.java index 0f7a50222..5c0234b33 100644 --- a/src/main/java/com/jozufozu/flywheel/api/event/RenderStageEvent.java +++ b/src/main/java/com/jozufozu/flywheel/api/event/RenderStageEvent.java @@ -9,7 +9,10 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.RenderBuffers; import net.minecraftforge.eventbus.api.Event; -public class RenderStageEvent extends Event { +/** + * This event is posted to the Forge event bus. + */ +public final class RenderStageEvent extends Event { private final RenderContext context; private final RenderStage stage; diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java deleted file mode 100644 index 610864209..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.jozufozu.flywheel.backend; - -import com.jozufozu.flywheel.backend.compile.FlwPrograms; -import com.jozufozu.flywheel.impl.BackendManagerImpl; - -import net.minecraft.client.Minecraft; -import net.minecraft.server.packs.resources.ReloadableResourceManager; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.ResourceManagerReloadListener; - -/** - * The main entity for loading shaders. - * - *

- * This class is responsible for invoking the loading, parsing, and compilation stages. - *

- */ -public class Loader implements ResourceManagerReloadListener { - public static final Loader INSTANCE = new Loader(); - - private Loader() { - } - - @Override - public void onResourceManagerReload(ResourceManager manager) { - FlwPrograms.reload(manager); - - // TODO: Move this to the impl package - // TODO: To ensure this runs after all backends are ready, inject into Minecraft after the reload and before levelRenderer.allChanged() - // Alternatively, consider adding API - // TODO: This should reset all VisualizationManagerImpls, not just the one for the static client level - BackendManagerImpl.refresh(Minecraft.getInstance().level); - } - - public static void init() { - // Can be null when running data generators due to the unfortunate time we call this - Minecraft minecraft = Minecraft.getInstance(); - if (minecraft == null) { - return; - } - - if (minecraft.getResourceManager() instanceof ReloadableResourceManager reloadable) { - reloadable.registerReloadListener(INSTANCE); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java index b5304bfe3..54f029fa8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwPrograms.java @@ -14,7 +14,10 @@ import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.lib.material.MaterialIndices; +import net.minecraft.client.Minecraft; +import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.ResourceManagerReloadListener; public class FlwPrograms { private FlwPrograms() { @@ -86,4 +89,28 @@ public class FlwPrograms { } return builder.build(); } + + public static class ResourceReloadListener implements ResourceManagerReloadListener { + public static final ResourceReloadListener INSTANCE = new ResourceReloadListener(); + + private ResourceReloadListener() { + } + + @Override + public void onResourceManagerReload(ResourceManager manager) { + FlwPrograms.reload(manager); + } + + public static void register() { + // Can be null when running data generators due to the unfortunate time we call this + Minecraft minecraft = Minecraft.getInstance(); + if (minecraft == null) { + return; + } + + if (minecraft.getResourceManager() instanceof ReloadableResourceManager reloadable) { + reloadable.registerReloadListener(INSTANCE); + } + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java index ab3734a97..c9d534576 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java @@ -104,12 +104,11 @@ public abstract class AbstractInstancer implements Instancer deleted.clear(); } + public void delete() { + } + @Override public String toString() { return "AbstractInstancer[" + getInstanceCount() + ']'; } - - public void delete() { - - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java index 2e524145b..6956b97f2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerStorage.java @@ -33,7 +33,6 @@ public abstract class InstancerStorage> { */ private final Object creationLock = new Object(); - /** * A list of initialized instancers. *
diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java index 569f88ed0..3efd685d0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java @@ -6,7 +6,7 @@ import java.util.Set; import org.lwjgl.opengl.GL32; import com.google.common.collect.ImmutableList; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.gl.buffer.GlBuffer; import com.jozufozu.flywheel.gl.shader.GlProgram; @@ -66,7 +66,7 @@ public class UniformBuffer { buffer.delete(); } - public static void onReloadRenderers(ReloadRenderersEvent event) { + public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) { if (instance != null) { instance.delete(); instance = null; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java index e98a0fe7f..a54808494 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java @@ -44,7 +44,7 @@ public class BatchingEngine extends AbstractEngine { } @Override - public void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List crumblingBlocks) { + public void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks) { executor.syncUntil(flushFlag::isRaised); var batchContext = BatchContext.create(context, this.renderOrigin); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java index 688765cb1..7cfabf6c5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java @@ -4,7 +4,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexListProvider; @@ -172,7 +172,7 @@ public class DrawBuffer { buffer = null; } - public static void onReloadRenderers(ReloadRenderersEvent event) { + public static void onReloadRenderers(ReloadLevelRendererEvent event) { ALL.forEach(DrawBuffer::free); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java index 631d18b5c..81cc538b7 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -15,31 +15,6 @@ import com.jozufozu.flywheel.lib.util.Pair; public class IndirectDrawManager extends InstancerStorage> { public final Map, VertexType>, IndirectCullingGroup> renderLists = new HashMap<>(); - public void flush() { - super.flush(); - - for (IndirectCullingGroup value : renderLists.values()) { - value.beginFrame(); - } - } - - public void invalidate() { - super.invalidate(); - - renderLists.values() - .forEach(IndirectCullingGroup::delete); - renderLists.clear(); - } - - public boolean hasStage(RenderStage stage) { - for (var list : renderLists.values()) { - if (list.hasStage(stage)) { - return true; - } - } - return false; - } - @Override protected IndirectInstancer create(InstanceType type) { return new IndirectInstancer<>(type); @@ -59,4 +34,31 @@ public class IndirectDrawManager extends InstancerStorage> break; // TODO: support multiple meshes per model } } + + public boolean hasStage(RenderStage stage) { + for (var list : renderLists.values()) { + if (list.hasStage(stage)) { + return true; + } + } + return false; + } + + @Override + public void flush() { + super.flush(); + + for (IndirectCullingGroup value : renderLists.values()) { + value.beginFrame(); + } + } + + @Override + public void invalidate() { + super.invalidate(); + + renderLists.values() + .forEach(IndirectCullingGroup::delete); + renderLists.clear(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java index 4299fb8ce..642f25683 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java @@ -61,7 +61,7 @@ public class IndirectEngine extends AbstractEngine { } @Override - public void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List crumblingBlocks) { + public void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks) { // TODO: implement } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java index 728359f25..3d8a4a407 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedDrawManager.java @@ -21,7 +21,6 @@ import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerStorage; public class InstancedDrawManager extends InstancerStorage> { - /** * The set of draw calls to make in each {@link RenderStage}. */ diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java index 2c9bb89f2..33eb1632c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java @@ -79,7 +79,7 @@ public class InstancedInstancer extends AbstractInstancer changed.clear(); } catch (Exception e) { - Flywheel.LOGGER.error("Error updating GPUInstancer:", e); + Flywheel.LOGGER.error("Error updating InstancedInstancer:", e); } } @@ -111,6 +111,7 @@ public class InstancedInstancer extends AbstractInstancer vao.bindAttributes(1, startAttrib, instanceFormat.attributes()); } + @Override public void delete() { vbo.delete(); vbo = null; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java index 2fc88f4bb..1cea1109b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java @@ -68,11 +68,7 @@ public class InstancingEngine extends AbstractEngine { } @Override - public void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List crumblingBlocks) { - if (crumblingBlocks.isEmpty()) { - return; - } - + public void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks) { // Need to wait for flush before we can inspect instancer state. executor.syncUntil(flushFlag::isRaised); diff --git a/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java b/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java index aae2dc1bf..93ee2da72 100644 --- a/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java +++ b/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java @@ -2,11 +2,9 @@ package com.jozufozu.flywheel.config; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.concurrent.CompletableFuture; -import org.jetbrains.annotations.NotNull; - -import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.backend.Backend; import com.jozufozu.flywheel.lib.util.ResourceUtil; import com.mojang.brigadier.StringReader; @@ -14,31 +12,17 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.ResourceLocationException; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; public class BackendArgument implements ArgumentType { - private static final List STRING_IDS = Backend.REGISTRY.getAllIds() - .stream() - .map(rl -> { - if (Flywheel.ID - .equals(rl.getNamespace())) { - return rl.getPath(); - } else { - return rl.toString(); - } - }) - .toList(); + private static final List EXAMPLES = List.of("off", "flywheel:off", "instancing"); - private static final SimpleCommandExceptionType ERROR_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.id.invalid")); - - public static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> { + private static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> { return Component.literal("Unknown backend '" + arg + "'"); }); @@ -46,7 +30,7 @@ public class BackendArgument implements ArgumentType { @Override public Backend parse(StringReader reader) throws CommandSyntaxException { - ResourceLocation id = getRead(reader); + ResourceLocation id = ResourceUtil.readFlywheelDefault(reader); Backend backend = Backend.REGISTRY.get(id); if (backend == null) { @@ -56,34 +40,20 @@ public class BackendArgument implements ArgumentType { return backend; } - /** - * Copied from {@link ResourceLocation#read}, but defaults to flywheel namespace. - */ - @NotNull - private static ResourceLocation getRead(StringReader reader) throws CommandSyntaxException { - int i = reader.getCursor(); - - while(reader.canRead() && ResourceLocation.isAllowedInResourceLocation(reader.peek())) { - reader.skip(); - } - - String s = reader.getString().substring(i, reader.getCursor()); - - try { - return ResourceUtil.defaultToFlywheelNamespace(s); - } catch (ResourceLocationException resourcelocationexception) { - reader.setCursor(i); - throw ERROR_INVALID.createWithContext(reader); - } - } - @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - return SharedSuggestionProvider.suggest(STRING_IDS, builder); + String input = builder.getRemaining().toLowerCase(Locale.ROOT); + for (ResourceLocation id : Backend.REGISTRY.getAllIds()) { + String idStr = id.toString(); + if (SharedSuggestionProvider.matchesSubStr(input, idStr) || SharedSuggestionProvider.matchesSubStr(input, id.getPath())) { + builder.suggest(idStr); + } + } + return builder.buildFuture(); } @Override public Collection getExamples() { - return STRING_IDS; + return EXAMPLES; } } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java index 8dc6cb603..8102c375e 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java @@ -23,7 +23,7 @@ public class FlwConfig { public final ClientConfig client; private final ForgeConfigSpec clientSpec; - public FlwConfig() { + private FlwConfig() { Pair clientPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new); this.client = clientPair.getLeft(); clientSpec = clientPair.getRight(); @@ -74,7 +74,7 @@ public class FlwConfig { public final ConfigValue backend; public final BooleanValue limitUpdates; - public ClientConfig(ForgeConfigSpec.Builder builder) { + private ClientConfig(ForgeConfigSpec.Builder builder) { backend = builder.comment("Select the backend to use.") .define("backend", Backend.REGISTRY.getIdOrThrow(BackendManager.getDefaultBackend()).toString()); diff --git a/src/main/java/com/jozufozu/flywheel/extension/ClientLevelExtension.java b/src/main/java/com/jozufozu/flywheel/extension/LevelExtension.java similarity index 50% rename from src/main/java/com/jozufozu/flywheel/extension/ClientLevelExtension.java rename to src/main/java/com/jozufozu/flywheel/extension/LevelExtension.java index 79baf9647..3c4e7ba68 100644 --- a/src/main/java/com/jozufozu/flywheel/extension/ClientLevelExtension.java +++ b/src/main/java/com/jozufozu/flywheel/extension/LevelExtension.java @@ -2,21 +2,21 @@ package com.jozufozu.flywheel.extension; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; -public interface ClientLevelExtension { - +public interface LevelExtension { /** * Get an iterator over all entities in this level. * *

- * Normally, this would be accomplished by {@link ClientLevel#entitiesForRendering()}, but the output of that - * method is filtered of entities that are rendered by flywheel. This interface provides a workaround. + * Normally, this would be accomplished by {@link ClientLevel#entitiesForRendering}, but the output of that + * method does not include entities that are rendered by Flywheel. This interface provides a workaround. *

- * @return An iterator over all entities in the level, including entities that are rendered by flywheel. + * @return An iterator over all entities in the level, including entities that are rendered by Flywheel. */ Iterable flywheel$getAllLoadedEntities(); - static Iterable getAllLoadedEntities(ClientLevel level) { - return ((ClientLevelExtension) level).flywheel$getAllLoadedEntities(); + static Iterable getAllLoadedEntities(Level level) { + return ((LevelExtension) level).flywheel$getAllLoadedEntities(); } } diff --git a/src/main/java/com/jozufozu/flywheel/glsl/SourceFile.java b/src/main/java/com/jozufozu/flywheel/glsl/SourceFile.java index 7d945189f..a3b9ed04e 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/SourceFile.java @@ -85,7 +85,7 @@ public class SourceFile implements SourceComponent { ResourceLocation location; try { - location = ResourceUtil.defaultToFlywheelNamespace(string); + location = ResourceUtil.parseFlywheelDefault(string); } catch (ResourceLocationException e) { failures.add(Pair.of(fileSpan, new LoadError.MalformedInclude(e))); continue; diff --git a/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java b/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java index bc67ece63..b36a8fc0b 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java +++ b/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java @@ -1,11 +1,11 @@ package com.jozufozu.flywheel.impl; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.backend.Backend; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent; +import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.backend.Backends; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl; @@ -59,19 +59,7 @@ public final class BackendManagerImpl { return Backends.INDIRECT; } - public static void onReloadRenderers(ReloadRenderersEvent event) { - refresh(event.getLevel()); - } - - public static void refresh(@Nullable ClientLevel level) { - backend = chooseBackend(); - - if (level != null) { - VisualizationManagerImpl.reset(level); - } - } - - private static Backend chooseBackend() { + private static void chooseBackend() { var preferred = FlwConfig.get().getBackend(); var actual = preferred.findFallback(); @@ -79,7 +67,7 @@ public final class BackendManagerImpl { LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getIdOrThrow(preferred), Backend.REGISTRY.getIdOrThrow(actual)); } - return actual; + backend = actual; } public static String getBackendString() { @@ -93,4 +81,22 @@ public final class BackendManagerImpl { public static void init() { CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString); } + + public static void onEndClientResourceReload(EndClientResourceReloadEvent event) { + if (event.getError().isPresent()) { + return; + } + + chooseBackend(); + VisualizationManagerImpl.resetAll(); + } + + public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) { + chooseBackend(); + + ClientLevel level = event.getLevel(); + if (level != null) { + VisualizationManagerImpl.reset(level); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java b/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java index 0aaa040f8..625ac7a17 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java +++ b/src/main/java/com/jozufozu/flywheel/impl/visualization/VisualizationManagerImpl.java @@ -18,7 +18,7 @@ import com.jozufozu.flywheel.api.visual.TickableVisual; import com.jozufozu.flywheel.api.visualization.VisualManager; import com.jozufozu.flywheel.api.visualization.VisualizationLevel; import com.jozufozu.flywheel.api.visualization.VisualizationManager; -import com.jozufozu.flywheel.extension.ClientLevelExtension; +import com.jozufozu.flywheel.extension.LevelExtension; import com.jozufozu.flywheel.impl.task.FlwTaskExecutor; import com.jozufozu.flywheel.impl.visualization.manager.BlockEntityVisualManager; import com.jozufozu.flywheel.impl.visualization.manager.EffectVisualManager; @@ -32,10 +32,10 @@ import com.jozufozu.flywheel.lib.util.LevelAttached; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.Vec3i; import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; @@ -88,6 +88,11 @@ public class VisualizationManagerImpl implements VisualizationManager { .then(engine.createFramePlan()) .then(RaisePlan.raise(frameFlag)) .simplify(); + + if (level instanceof Level l) { + LevelExtension.getAllLoadedEntities(l) + .forEach(entities::queueAdd); + } } public static boolean supportsVisualization(@Nullable LevelAccessor level) { @@ -127,19 +132,14 @@ public class VisualizationManagerImpl implements VisualizationManager { return MANAGERS.get(level); } - // TODO: Consider making this reset action reuse the existing added game objects instead of readding them, potentially by keeping the same VisualizationManagerImpl and not fully deleting it - // TODO: Consider changing parameter type to Level since it is also possible to get all entities from it - public static void reset(ClientLevel level) { + // TODO: Consider making these reset actions reuse the existing game objects instead of re-adding them + // potentially by keeping the same VisualizationManagerImpl and deleting the engine and visuals but not the game objects + public static void reset(LevelAccessor level) { MANAGERS.remove(level); - VisualizationManagerImpl manager = get(level); - if (manager == null) { - return; - } + } - // Block entities are loaded while chunks are baked. - // Entities are loaded with the level, so when chunks are reloaded they need to be re-added. - ClientLevelExtension.getAllLoadedEntities(level) - .forEach(manager.getEntities()::queueAdd); + public static void resetAll() { + MANAGERS.reset(); } @Override @@ -239,7 +239,9 @@ public class VisualizationManagerImpl implements VisualizationManager { crumblingBlocks.add(new Engine.CrumblingBlock(maxDestruction.getProgress(), maxDestruction.getPos(), instances)); } - engine.renderCrumblingInstances(taskExecutor, context, crumblingBlocks); + if (!crumblingBlocks.isEmpty()) { + engine.renderCrumbling(taskExecutor, context, crumblingBlocks); + } } /** diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/AbstractMemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/lib/memory/AbstractMemoryBlockImpl.java new file mode 100644 index 000000000..e7d29f331 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/AbstractMemoryBlockImpl.java @@ -0,0 +1,76 @@ +package com.jozufozu.flywheel.lib.memory; + +import java.lang.ref.Cleaner; +import java.nio.ByteBuffer; + +import org.lwjgl.system.MemoryUtil; + +non-sealed abstract class AbstractMemoryBlockImpl implements MemoryBlock { + static final Cleaner CLEANER = Cleaner.create(); + + final long ptr; + final long size; + + boolean freed; + + AbstractMemoryBlockImpl(long ptr, long size) { + this.ptr = ptr; + this.size = size; + } + + @Override + public long ptr() { + return ptr; + } + + @Override + public long size() { + return size; + } + + @Override + public boolean isFreed() { + return freed; + } + + @Override + public void copyTo(MemoryBlock block) { + long bytes = Math.min(size, block.size()); + copyTo(block.ptr(), bytes); + } + + @Override + public void copyTo(long ptr, long bytes) { + MemoryUtil.memCopy(this.ptr, ptr, bytes); + } + + @Override + public void copyTo(long ptr) { + copyTo(ptr, size); + } + + @Override + public void clear() { + MemoryUtil.memSet(ptr, 0, size); + } + + @Override + public ByteBuffer asBuffer() { + int intSize = (int) size; + if (intSize != size) { + throw new UnsupportedOperationException("Cannot create buffer with long capacity!"); + } + return MemoryUtil.memByteBuffer(ptr, intSize); + } + + void freeInner() { + FlwMemoryTracker._freeCPUMemory(size); + freed = true; + } + + @Override + public void free() { + FlwMemoryTracker.free(ptr); + freeInner(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/DebugMemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/lib/memory/DebugMemoryBlockImpl.java index 004a4ba62..b91dc53a6 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/memory/DebugMemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/DebugMemoryBlockImpl.java @@ -5,16 +5,23 @@ import java.lang.ref.Cleaner; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.lib.util.StringUtil; -class DebugMemoryBlockImpl extends MemoryBlockImpl { +class DebugMemoryBlockImpl extends AbstractMemoryBlockImpl { + final Cleaner cleaner; final CleaningAction cleaningAction; final Cleaner.Cleanable cleanable; - DebugMemoryBlockImpl(long ptr, long size, Cleaner cleaner) { + DebugMemoryBlockImpl(long ptr, long size, Cleaner cleaner, int skipFrames) { super(ptr, size); - cleaningAction = new CleaningAction(ptr, size, getStackTrace()); + this.cleaner = cleaner; + cleaningAction = new CleaningAction(ptr, size, getStackTrace(skipFrames + 1)); cleanable = cleaner.register(this, cleaningAction); } + @Override + public boolean isTracked() { + return false; + } + @Override void freeInner() { super.freeInner(); @@ -22,24 +29,37 @@ class DebugMemoryBlockImpl extends MemoryBlockImpl { cleanable.clean(); } - static StackWalker.StackFrame[] getStackTrace() { - // skip 4 frames to get to the caller: + @Override + public MemoryBlock realloc(long size) { + MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, cleaner, 1); + FlwMemoryTracker._allocCPUMemory(block.size()); + freeInner(); + return block; + } + + static StackWalker.StackFrame[] getStackTrace(int skipFrames) { + // for DebugMemoryBlockImpl::realloc, skip 3 frames to get the allocation site: + // - this method + // - DebugMemoryBlockImpl::new + // - DebugMemoryBlockImpl::realloc + // - {caller is here} + // for DebugMemoryBlockImpl::malloc/calloc, skip 4 frames to get the allocation site: // - this method // - DebugMemoryBlockImpl::new // - DebugMemoryBlockImpl::malloc/calloc // - MemoryBlock::malloc/calloc // - {caller is here} - return StackWalker.getInstance().walk(s -> s.skip(4).toArray(StackWalker.StackFrame[]::new)); + return StackWalker.getInstance().walk(s -> s.skip(skipFrames + 1).toArray(StackWalker.StackFrame[]::new)); } static MemoryBlock malloc(long size) { - MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, FlwMemoryTracker.CLEANER); + MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, CLEANER, 2); FlwMemoryTracker._allocCPUMemory(block.size()); return block; } static MemoryBlock calloc(long num, long size) { - MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, FlwMemoryTracker.CLEANER); + MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, CLEANER, 2); FlwMemoryTracker._allocCPUMemory(block.size()); return block; } diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java b/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java index ba3afb1d1..82eb4b2eb 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.lib.memory; -import java.lang.ref.Cleaner; import java.util.concurrent.atomic.AtomicLong; import org.lwjgl.system.MemoryUtil; @@ -10,8 +9,6 @@ import com.jozufozu.flywheel.lib.util.StringUtil; public final class FlwMemoryTracker { public static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null; - static final Cleaner CLEANER = Cleaner.create(); - private static final AtomicLong CPU_MEMORY = new AtomicLong(0); private static final AtomicLong GPU_MEMORY = new AtomicLong(0); diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlock.java b/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlock.java index bb89df2d1..8f74c1b73 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlock.java +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlock.java @@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.memory; import java.nio.ByteBuffer; -public sealed interface MemoryBlock permits MemoryBlockImpl { +public sealed interface MemoryBlock permits AbstractMemoryBlockImpl { long ptr(); long size(); @@ -11,6 +11,8 @@ public sealed interface MemoryBlock permits MemoryBlockImpl { boolean isTracked(); + void copyTo(MemoryBlock block); + void copyTo(long ptr, long bytes); void copyTo(long ptr); @@ -21,8 +23,6 @@ public sealed interface MemoryBlock permits MemoryBlockImpl { MemoryBlock realloc(long size); - MemoryBlock reallocTracked(long size); - void free(); static MemoryBlock malloc(long size) { diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlockImpl.java index 0aaaed46b..cc42d0517 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/MemoryBlockImpl.java @@ -1,33 +1,8 @@ package com.jozufozu.flywheel.lib.memory; -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -non-sealed class MemoryBlockImpl implements MemoryBlock { - final long ptr; - final long size; - - boolean freed; - +class MemoryBlockImpl extends AbstractMemoryBlockImpl { MemoryBlockImpl(long ptr, long size) { - this.ptr = ptr; - this.size = size; - } - - @Override - public long ptr() { - return ptr; - } - - @Override - public long size() { - return size; - } - - @Override - public boolean isFreed() { - return freed; + super(ptr, size); } @Override @@ -35,35 +10,6 @@ non-sealed class MemoryBlockImpl implements MemoryBlock { return false; } - @Override - public void copyTo(long ptr, long bytes) { - MemoryUtil.memCopy(this.ptr, ptr, bytes); - } - - @Override - public void copyTo(long ptr) { - copyTo(ptr, size); - } - - @Override - public void clear() { - MemoryUtil.memSet(ptr, 0, size); - } - - @Override - public ByteBuffer asBuffer() { - int intSize = (int) size; - if (intSize != size) { - throw new UnsupportedOperationException("Cannot create buffer with long capacity!"); - } - return MemoryUtil.memByteBuffer(ptr, intSize); - } - - void freeInner() { - FlwMemoryTracker._freeCPUMemory(size); - freed = true; - } - @Override public MemoryBlock realloc(long size) { MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size); @@ -72,20 +18,6 @@ non-sealed class MemoryBlockImpl implements MemoryBlock { return block; } - @Override - public MemoryBlock reallocTracked(long size) { - MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, FlwMemoryTracker.CLEANER); - FlwMemoryTracker._allocCPUMemory(block.size()); - freeInner(); - return block; - } - - @Override - public void free() { - FlwMemoryTracker.free(ptr); - freeInner(); - } - static MemoryBlock malloc(long size) { MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.malloc(size), size); FlwMemoryTracker._allocCPUMemory(block.size()); diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/TrackedMemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/lib/memory/TrackedMemoryBlockImpl.java index 71c650c32..3f3d2a7ac 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/memory/TrackedMemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/TrackedMemoryBlockImpl.java @@ -2,12 +2,14 @@ package com.jozufozu.flywheel.lib.memory; import java.lang.ref.Cleaner; -class TrackedMemoryBlockImpl extends MemoryBlockImpl { +class TrackedMemoryBlockImpl extends AbstractMemoryBlockImpl { + final Cleaner cleaner; final CleaningAction cleaningAction; final Cleaner.Cleanable cleanable; TrackedMemoryBlockImpl(long ptr, long size, Cleaner cleaner) { super(ptr, size); + this.cleaner = cleaner; cleaningAction = new CleaningAction(ptr, size); cleanable = cleaner.register(this, cleaningAction); } @@ -24,14 +26,22 @@ class TrackedMemoryBlockImpl extends MemoryBlockImpl { cleanable.clean(); } + @Override + public MemoryBlock realloc(long size) { + MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, cleaner); + FlwMemoryTracker._allocCPUMemory(block.size()); + freeInner(); + return block; + } + static MemoryBlock malloc(long size) { - MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, FlwMemoryTracker.CLEANER); + MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, CLEANER); FlwMemoryTracker._allocCPUMemory(block.size()); return block; } static MemoryBlock calloc(long num, long size) { - MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, FlwMemoryTracker.CLEANER); + MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, CLEANER); FlwMemoryTracker._allocCPUMemory(block.size()); return block; } diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/ModelCache.java b/src/main/java/com/jozufozu/flywheel/lib/model/ModelCache.java index 2cbba1a24..9f12cfc0b 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/ModelCache.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/ModelCache.java @@ -8,7 +8,7 @@ import java.util.function.Function; import org.jetbrains.annotations.ApiStatus; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent; import com.jozufozu.flywheel.api.model.Model; public class ModelCache { @@ -31,7 +31,7 @@ public class ModelCache { } @ApiStatus.Internal - public static void onReloadRenderers(ReloadRenderersEvent event) { + public static void onEndClientResourceReload(EndClientResourceReloadEvent event) { for (ModelCache cache : ALL) { cache.clear(); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/ModelHolder.java b/src/main/java/com/jozufozu/flywheel/lib/model/ModelHolder.java index ee9d3f4a0..84088f6e8 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/ModelHolder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/ModelHolder.java @@ -7,7 +7,7 @@ import java.util.function.Supplier; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent; import com.jozufozu.flywheel.api.model.Model; public class ModelHolder { @@ -51,7 +51,7 @@ public class ModelHolder { } @ApiStatus.Internal - public static void onReloadRenderers(ReloadRenderersEvent event) { + public static void onEndClientResourceReload(EndClientResourceReloadEvent event) { for (ModelHolder holder : ALL) { holder.clear(); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java b/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java index e923996d5..bf12ab141 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBufferer.java @@ -56,9 +56,11 @@ public final class BakedModelBufferer { blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, buffer, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData, renderType); poseStack.popPose(); - RenderedBuffer data = buffer.end(); - resultConsumer.accept(renderType, data); - data.release(); + RenderedBuffer data = buffer.endOrDiscardIfEmpty(); + if (data != null) { + resultConsumer.accept(renderType, data); + data.release(); + } } } @@ -89,12 +91,16 @@ public final class BakedModelBufferer { blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, shadeSeparatingWrapper, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData, renderType); poseStack.popPose(); - RenderedBuffer shadedData = shadedBuffer.end(); - RenderedBuffer unshadedData = unshadedBuffer.end(); - resultConsumer.accept(renderType, true, shadedData); - shadedData.release(); - resultConsumer.accept(renderType, false, unshadedData); - unshadedData.release(); + RenderedBuffer shadedData = shadedBuffer.endOrDiscardIfEmpty(); + if (shadedData != null) { + resultConsumer.accept(renderType, true, shadedData); + shadedData.release(); + } + RenderedBuffer unshadedData = unshadedBuffer.endOrDiscardIfEmpty(); + if (unshadedData != null) { + resultConsumer.accept(renderType, false, unshadedData); + unshadedData.release(); + } } shadeSeparatingWrapper.clear(); @@ -163,9 +169,11 @@ public final class BakedModelBufferer { for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) { RenderType renderType = CHUNK_LAYERS[layerIndex]; BufferBuilder buffer = buffers[layerIndex]; - RenderedBuffer data = buffer.end(); - resultConsumer.accept(renderType, data); - data.release(); + RenderedBuffer data = buffer.endOrDiscardIfEmpty(); + if (data != null) { + resultConsumer.accept(renderType, data); + data.release(); + } } } @@ -224,12 +232,16 @@ public final class BakedModelBufferer { RenderType renderType = CHUNK_LAYERS[layerIndex]; BufferBuilder shadedBuffer = shadedBuffers[layerIndex]; BufferBuilder unshadedBuffer = unshadedBuffers[layerIndex]; - RenderedBuffer shadedData = shadedBuffer.end(); - RenderedBuffer unshadedData = unshadedBuffer.end(); - resultConsumer.accept(renderType, true, shadedData); - shadedData.release(); - resultConsumer.accept(renderType, false, unshadedData); - unshadedData.release(); + RenderedBuffer shadedData = shadedBuffer.endOrDiscardIfEmpty(); + if (shadedData != null) { + resultConsumer.accept(renderType, true, shadedData); + shadedData.release(); + } + RenderedBuffer unshadedData = unshadedBuffer.endOrDiscardIfEmpty(); + if (unshadedBuffer != null) { + resultConsumer.accept(renderType, false, unshadedData); + unshadedData.release(); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBuilder.java index ec6e911be..5725b57a5 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/baked/BakedModelBuilder.java @@ -81,23 +81,19 @@ public class BakedModelBuilder { if (shadeSeparated) { ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, data) -> { - if (!data.isEmpty()) { - Material material = materialFunc.apply(renderType, shaded); - if (material != null) { - MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); - meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType + ",shaded=" + shaded)); - } + Material material = materialFunc.apply(renderType, shaded); + if (material != null) { + MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType + ",shaded=" + shaded)); } }; BakedModelBufferer.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, modelData, resultConsumer); } else { ResultConsumer resultConsumer = (renderType, data) -> { - if (!data.isEmpty()) { - Material material = materialFunc.apply(renderType, true); - if (material != null) { - MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); - meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType)); - } + Material material = materialFunc.apply(renderType, true); + if (material != null) { + MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType)); } }; BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, modelData, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/baked/BlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/baked/BlockModelBuilder.java index 61cd3c292..0f54b5362 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/baked/BlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/baked/BlockModelBuilder.java @@ -70,23 +70,19 @@ public class BlockModelBuilder { if (shadeSeparated) { ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, data) -> { - if (!data.isEmpty()) { - Material material = materialFunc.apply(renderType, shaded); - if (material != null) { - MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); - meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType + ",shaded=" + shaded)); - } + Material material = materialFunc.apply(renderType, shaded); + if (material != null) { + MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType + ",shaded=" + shaded)); } }; BakedModelBufferer.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, modelData, resultConsumer); } else { ResultConsumer resultConsumer = (renderType, data) -> { - if (!data.isEmpty()) { - Material material = materialFunc.apply(renderType, true); - if (material != null) { - MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); - meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType)); - } + Material material = materialFunc.apply(renderType, true); + if (material != null) { + MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType)); } }; BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, modelData, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/baked/MultiBlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/baked/MultiBlockModelBuilder.java index c1bbd7652..294a6c19b 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/baked/MultiBlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/baked/MultiBlockModelBuilder.java @@ -74,23 +74,19 @@ public class MultiBlockModelBuilder { if (shadeSeparated) { ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, data) -> { - if (!data.isEmpty()) { - Material material = materialFunc.apply(renderType, shaded); - if (material != null) { - MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); - meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded)); - } + Material material = materialFunc.apply(renderType, shaded); + if (material != null) { + MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded)); } }; BakedModelBufferer.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, modelDataMap, resultConsumer); } else { ResultConsumer resultConsumer = (renderType, data) -> { - if (!data.isEmpty()) { - Material material = materialFunc.apply(renderType, true); - if (material != null) { - MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); - meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType)); - } + Material material = materialFunc.apply(renderType, true); + if (material != null) { + MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType)); } }; BakedModelBufferer.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, modelDataMap, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/part/VertexWriter.java b/src/main/java/com/jozufozu/flywheel/lib/model/part/VertexWriter.java index d0b043d01..2ede91c56 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/part/VertexWriter.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/part/VertexWriter.java @@ -126,7 +126,7 @@ class VertexWriter implements VertexConsumer { public MemoryBlock copyDataAndReset() { MemoryBlock dataCopy = MemoryBlock.malloc(vertexCount * STRIDE); - data.copyTo(dataCopy.ptr(), dataCopy.size()); + data.copyTo(dataCopy); vertexCount = 0; filledPosition = false; diff --git a/src/main/java/com/jozufozu/flywheel/lib/util/ResourceUtil.java b/src/main/java/com/jozufozu/flywheel/lib/util/ResourceUtil.java index 3d7b2c445..7712b19f6 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/util/ResourceUtil.java +++ b/src/main/java/com/jozufozu/flywheel/lib/util/ResourceUtil.java @@ -1,11 +1,24 @@ package com.jozufozu.flywheel.lib.util; import com.jozufozu.flywheel.Flywheel; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.minecraft.ResourceLocationException; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -public class ResourceUtil { - public static ResourceLocation defaultToFlywheelNamespace(String location) { +public final class ResourceUtil { + private static final SimpleCommandExceptionType ERROR_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.id.invalid")); + + private ResourceUtil() { + } + + /** + * Same as {@link ResourceLocation#ResourceLocation(String)}, but defaults to Flywheel namespace. + */ + public static ResourceLocation parseFlywheelDefault(String location) { String namespace = Flywheel.ID; String path = location; @@ -19,4 +32,24 @@ public class ResourceUtil { return new ResourceLocation(namespace, path); } + + /** + * Same as {@link ResourceLocation#read(StringReader)}, but defaults to Flywheel namespace. + */ + public static ResourceLocation readFlywheelDefault(StringReader reader) throws CommandSyntaxException { + int i = reader.getCursor(); + + while (reader.canRead() && ResourceLocation.isAllowedInResourceLocation(reader.peek())) { + reader.skip(); + } + + String s = reader.getString().substring(i, reader.getCursor()); + + try { + return parseFlywheelDefault(s); + } catch (ResourceLocationException resourcelocationexception) { + reader.setCursor(i); + throw ERROR_INVALID.createWithContext(reader); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java index dcb277da3..20ca6577f 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BlockEntityTypeMixin.java @@ -11,7 +11,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @Mixin(BlockEntityType.class) -public class BlockEntityTypeMixin implements BlockEntityTypeExtension { +abstract class BlockEntityTypeMixin implements BlockEntityTypeExtension { @Unique private BlockEntityVisualizer flywheel$visualizer; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java index f4582fc81..973d9f4dd 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java @@ -14,7 +14,7 @@ import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; @Mixin(BufferBuilder.class) -public abstract class BufferBuilderMixin implements BufferBuilderExtension { +abstract class BufferBuilderMixin implements BufferBuilderExtension { @Shadow private ByteBuffer buffer; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java index ba1513e0f..7928a85df 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java @@ -3,30 +3,19 @@ package com.jozufozu.flywheel.mixin; import java.util.ArrayList; 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.CallbackInfoReturnable; import com.google.common.collect.Lists; import com.jozufozu.flywheel.api.visualization.VisualizationManager; -import com.jozufozu.flywheel.extension.ClientLevelExtension; import com.jozufozu.flywheel.impl.visualization.VisualizationHelper; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.entity.LevelEntityGetter; @Mixin(ClientLevel.class) -public abstract class ClientLevelMixin implements ClientLevelExtension { - @Shadow - protected abstract LevelEntityGetter getEntities(); - - @Override - public Iterable flywheel$getAllLoadedEntities() { - return getEntities().getAll(); - } - +abstract class ClientLevelMixin { @Inject(method = "entitiesForRendering()Ljava/lang/Iterable;", at = @At("RETURN"), cancellable = true) private void flywheel$filterEntities(CallbackInfoReturnable> cir) { if (!VisualizationManager.supportsVisualization((ClientLevel) (Object) this)) { diff --git a/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java index 65cc060ec..253d00d2d 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/EntityTypeMixin.java @@ -11,7 +11,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @Mixin(EntityType.class) -public class EntityTypeMixin implements EntityTypeExtension { +abstract class EntityTypeMixin implements EntityTypeExtension { @Unique private EntityVisualizer flywheel$visualizer; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java index cfdc009d5..e557076f0 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/FogUpdateMixin.java @@ -11,7 +11,7 @@ import com.jozufozu.flywheel.lib.uniform.FlwShaderUniforms; import net.minecraft.client.renderer.FogRenderer; @Mixin(FogRenderer.class) -public class FogUpdateMixin { +abstract class FogUpdateMixin { @Unique private static void flywheel$updateFog() { FlwShaderUniforms.FOG_UPDATE = true; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java index 9e6a13497..f236ce080 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/GlStateManagerMixin.java @@ -10,7 +10,7 @@ import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.mojang.blaze3d.platform.GlStateManager; @Mixin(GlStateManager.class) -public class GlStateManagerMixin { +abstract class GlStateManagerMixin { @Inject(method = "_glBindBuffer(II)V", at = @At("RETURN")) private static void flywheel$onBindBuffer(int target, int buffer, CallbackInfo ci) { GlStateTracker._setBuffer(GlBufferType.fromTarget(target), buffer); diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelMixin.java new file mode 100644 index 000000000..4739c28ba --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelMixin.java @@ -0,0 +1,21 @@ +package com.jozufozu.flywheel.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.jozufozu.flywheel.extension.LevelExtension; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.entity.LevelEntityGetter; + +@Mixin(Level.class) +abstract class LevelMixin implements LevelExtension { + @Shadow + protected abstract LevelEntityGetter getEntities(); + + @Override + public Iterable flywheel$getAllLoadedEntities() { + return getEntities().getAll(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java index 79b1090e7..a0dcdcc13 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java @@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.api.event.BeginFrameEvent; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStageEvent; @@ -32,7 +32,7 @@ import net.minecraft.server.level.BlockDestructionProgress; import net.minecraftforge.common.MinecraftForge; @Mixin(value = LevelRenderer.class, priority = 1001) // Higher priority to go after Sodium -public class LevelRendererMixin { +abstract class LevelRendererMixin { @Shadow private ClientLevel level; @@ -61,7 +61,7 @@ public class LevelRendererMixin { @Inject(method = "allChanged", at = @At("RETURN")) private void flywheel$refresh(CallbackInfo ci) { - MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(level)); + MinecraftForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level)); } @Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=destroyProgress")) diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LightUpdateMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LightUpdateMixin.java index 8824a9221..128048c47 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/LightUpdateMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/LightUpdateMixin.java @@ -16,7 +16,7 @@ import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.chunk.ChunkSource; @Mixin(ClientChunkCache.class) -public abstract class LightUpdateMixin extends ChunkSource { +abstract class LightUpdateMixin extends ChunkSource { @Shadow @Final ClientLevel level; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/MinecraftMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/MinecraftMixin.java new file mode 100644 index 000000000..1029a8e80 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/MinecraftMixin.java @@ -0,0 +1,37 @@ +package com.jozufozu.flywheel.mixin; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +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.api.event.EndClientResourceReloadEvent; +import com.mojang.realmsclient.client.RealmsClient; + +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; + +@Mixin(Minecraft.class) +abstract class MinecraftMixin { + @Shadow + @Final + private ReloadableResourceManager resourceManager; + + @Inject(method = "lambda$new$5", at = @At("HEAD")) + private void flywheel$onEndInitialResourceReload(RealmsClient realmsClient, ReloadInstance reloadInstance, GameConfig gameConfig, Optional error, CallbackInfo ci) { + ModLoader.get().postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, true, error)); + } + + @Inject(method = "lambda$reloadResourcePacks$28", at = @At("HEAD")) + private void flywheel$onEndManualResourceReload(boolean recovery, CompletableFuture future, Optional error, CallbackInfo ci) { + ModLoader.get().postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, false, error)); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/PoseStackMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/PoseStackMixin.java index 378a0b3d2..4b9d0d08f 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/PoseStackMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/PoseStackMixin.java @@ -7,7 +7,7 @@ import com.jozufozu.flywheel.lib.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; @Mixin(PoseStack.class) -public abstract class PoseStackMixin implements TransformStack { +abstract class PoseStackMixin implements TransformStack { @Override public TransformStack pushPose() { ((PoseStack) (Object) this).pushPose(); diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java index fa4ea4d7b..1644c2c08 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java @@ -12,10 +12,11 @@ import com.jozufozu.flywheel.extension.RenderTypeExtension; import net.minecraft.client.renderer.RenderType; @Mixin(RenderType.class) -public class RenderTypeMixin implements RenderTypeExtension { +abstract class RenderTypeMixin implements RenderTypeExtension { @Shadow @Final private boolean sortOnUpload; + @Unique private DrawBufferSet flywheel$drawBufferSet; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/VertexFormatMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/VertexFormatMixin.java index d85b33ede..2fa1f7510 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/VertexFormatMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/VertexFormatMixin.java @@ -8,7 +8,7 @@ import com.jozufozu.flywheel.extension.VertexFormatExtension; import com.mojang.blaze3d.vertex.VertexFormat; @Mixin(VertexFormat.class) -public class VertexFormatMixin implements VertexFormatExtension { +abstract class VertexFormatMixin implements VertexFormatExtension { @Unique private VertexListProvider flywheel$vertexListProvider; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/fix/FixFabulousDepthMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/fix/FixFabulousDepthMixin.java index a119b1e09..70a99b62e 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/fix/FixFabulousDepthMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/fix/FixFabulousDepthMixin.java @@ -10,7 +10,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.renderer.LevelRenderer; @Mixin(LevelRenderer.class) -public class FixFabulousDepthMixin { +abstract class FixFabulousDepthMixin { @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/PostChain;process(F)V", ordinal = 1)) private void flywheel$disableTransparencyShaderDepth(CallbackInfo ci) { GlStateManager._depthMask(false); diff --git a/src/main/java/com/jozufozu/flywheel/mixin/fix/FixNormalScalingMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/fix/FixNormalScalingMixin.java index 37fa78ecb..16ef24ff0 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/fix/FixNormalScalingMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/fix/FixNormalScalingMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.mojang.blaze3d.vertex.PoseStack; @Mixin(PoseStack.class) -public class FixNormalScalingMixin { +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 diff --git a/src/main/java/com/jozufozu/flywheel/mixin/sodium/ChunkBuilderMeshingTaskMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/sodium/ChunkBuilderMeshingTaskMixin.java index e89dda92f..41b26daff 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/sodium/ChunkBuilderMeshingTaskMixin.java @@ -12,7 +12,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.world.level.block.entity.BlockEntity; @Mixin(value = ChunkBuilderMeshingTask.class, remap = false) -public class ChunkBuilderMeshingTaskMixin { +abstract class ChunkBuilderMeshingTaskMixin { @Redirect(method = "execute", 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)) private BlockEntityRenderer flywheel$redirectGetRenderer(BlockEntityRenderDispatcher dispatcher, BlockEntity blockEntity) { if (VisualizationHelper.tryAddBlockEntity(blockEntity)) { @@ -20,4 +20,4 @@ public class ChunkBuilderMeshingTaskMixin { } return dispatcher.getRenderer(blockEntity); } -} \ No newline at end of file +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/ChunkRebuildHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/ChunkRebuildHooksMixin.java index 387db883d..116f7b236 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/ChunkRebuildHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/ChunkRebuildHooksMixin.java @@ -11,7 +11,7 @@ import com.jozufozu.flywheel.impl.visualization.VisualizationHelper; import net.minecraft.world.level.block.entity.BlockEntity; @Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask") -public class ChunkRebuildHooksMixin { +abstract class ChunkRebuildHooksMixin { @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) private void flywheel$tryAddBlockEntity(@Coerce Object compileResults, BlockEntity blockEntity, CallbackInfo ci) { if (VisualizationHelper.tryAddBlockEntity(blockEntity)) { diff --git a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualAddMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualAddMixin.java index 6f3435623..3144de0f9 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualAddMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualAddMixin.java @@ -14,7 +14,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; @Mixin(LevelChunk.class) -public class VisualAddMixin { +abstract class VisualAddMixin { @Shadow @Final Level level; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualRemoveMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualRemoveMixin.java index b5167d56a..b924127b8 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualRemoveMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualRemoveMixin.java @@ -13,7 +13,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @Mixin(BlockEntity.class) -public class VisualRemoveMixin { +abstract class VisualRemoveMixin { @Shadow @Nullable protected Level level; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualUpdateMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualUpdateMixin.java index 7e7021975..1ddff522d 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualUpdateMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/visualmanage/VisualUpdateMixin.java @@ -15,7 +15,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @Mixin(LevelRenderer.class) -public class VisualUpdateMixin { +abstract class VisualUpdateMixin { @Shadow private ClientLevel level; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java index b80c75bbe..879bc851a 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java @@ -5,7 +5,7 @@ import java.util.List; import org.joml.Vector3f; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.task.Plan; import com.jozufozu.flywheel.api.visual.Effect; @@ -65,7 +65,7 @@ public class ExampleEffect implements Effect { trySpawnNewEffect(); } - public static void onReload(ReloadRenderersEvent event) { + public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) { ALL_EFFECTS.clear(); } diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 293b9695b..5d0885cc2 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -11,8 +11,10 @@ "EntityTypeMixin", "FogUpdateMixin", "GlStateManagerMixin", + "LevelMixin", "LevelRendererMixin", "LightUpdateMixin", + "MinecraftMixin", "PoseStackMixin", "RenderTypeMixin", "VertexFormatMixin",