From db20e3e348c8f2555a52aed804a1674bf161eebc Mon Sep 17 00:00:00 2001 From: Grondag Date: Sun, 6 Sep 2020 20:38:52 -0700 Subject: [PATCH] VoxelMap compatibility --- .../grondag/canvas/compat/VoxelMapHolder.java | 98 +++++++++++++++++++ .../canvas/render/CanvasWorldRenderer.java | 20 ++-- 2 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 src/main/java/grondag/canvas/compat/VoxelMapHolder.java diff --git a/src/main/java/grondag/canvas/compat/VoxelMapHolder.java b/src/main/java/grondag/canvas/compat/VoxelMapHolder.java new file mode 100644 index 000000000..77348dda8 --- /dev/null +++ b/src/main/java/grondag/canvas/compat/VoxelMapHolder.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019, 2020 grondag + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package grondag.canvas.compat; + +import grondag.canvas.CanvasMod; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Matrix4f; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; + +public class VoxelMapHolder { + private static final PostRenderHandler DUMMY_RENDER_HANDLER = (WorldRenderer wr, MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f) -> {}; + public static PostRenderHandler postRenderHandler = DUMMY_RENDER_HANDLER; + + private static final PostRenderLayerHandler DUMMY_RENDER_LAYER_HANDLER = (WorldRenderer wr, RenderLayer renderLayer, MatrixStack matrixStack, double d, double e, double f) -> {}; + public static PostRenderLayerHandler postRenderLayerHandler = DUMMY_RENDER_LAYER_HANDLER; + + static { + if (FabricLoader.getInstance().isModLoaded("voxelmap")) { + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + try { + final Class clazz = WorldRenderer.class; + + for (final Method m : clazz.getDeclaredMethods()) { + final String name = m.getName(); + + if (name.contains("handler$")) { + if (name.endsWith("$postRender")) { + m.setAccessible(true); + final MethodHandle handler = lookup.unreflect(m); + + postRenderHandler = (WorldRenderer wr, MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f) -> { + try { + handler.invokeExact(wr, matrices, tickDelta, limitTime, renderBlockOutline, camera, gameRenderer, lightmapTextureManager, matrix4f, (CallbackInfo) null); + } catch (final Throwable e) { + CanvasMod.LOG.warn("Unable to call VoxelMap postRender hook due to exception:", e); + CanvasMod.LOG.warn("Subsequent errors will be suppressed"); + postRenderHandler = DUMMY_RENDER_HANDLER; + } + }; + } else if (name.endsWith("$postRenderLayer")) { + m.setAccessible(true); + final MethodHandle handler = lookup.unreflect(m); + + postRenderLayerHandler = (WorldRenderer wr, RenderLayer renderLayer, MatrixStack matrixStack, double x, double y, double z) -> { + try { + handler.invokeExact(wr, renderLayer, matrixStack, x, y, z, (CallbackInfo) null); + } catch (final Throwable e) { + CanvasMod.LOG.warn("Unable to call VoxelMap postRenderLayer hook due to exception:", e); + CanvasMod.LOG.warn("Subsequent errors will be suppressed"); + postRenderLayerHandler = DUMMY_RENDER_LAYER_HANDLER; + } + }; + } + } + } + + if (postRenderHandler == DUMMY_RENDER_HANDLER || postRenderLayerHandler == DUMMY_RENDER_LAYER_HANDLER) { + postRenderLayerHandler = DUMMY_RENDER_LAYER_HANDLER; + postRenderHandler = DUMMY_RENDER_HANDLER; + CanvasMod.LOG.warn("Unable to enable all VoxelMap compatibility hooks - method matches not found"); + } else { + CanvasMod.LOG.info("Found VoxelMap - compatibility hooks enabled"); + } + } catch (final Exception e) { + CanvasMod.LOG.warn("Unable to enable all VoxelMap compatibility hooks due to exception:", e); + } + } + } + + public interface PostRenderHandler { + void render(WorldRenderer wr, MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f); + } + + public interface PostRenderLayerHandler { + void render(WorldRenderer wr, RenderLayer renderLayer, MatrixStack matrixStack, double d, double e, double f); + } +} diff --git a/src/main/java/grondag/canvas/render/CanvasWorldRenderer.java b/src/main/java/grondag/canvas/render/CanvasWorldRenderer.java index cbeb2bbae..457ba0a07 100644 --- a/src/main/java/grondag/canvas/render/CanvasWorldRenderer.java +++ b/src/main/java/grondag/canvas/render/CanvasWorldRenderer.java @@ -464,8 +464,8 @@ public void renderWorld(MatrixStack matrixStack, float tickDelta, long limitTime while (entities.hasNext()) { final Entity entity = entities.next(); if ((!entityRenderDispatcher.shouldRender(entity, frustum, cameraX, cameraY, cameraZ) && !entity.hasPassengerDeep(mc.player)) - || (entity == camera.getFocusedEntity() && !camera.isThirdPerson() && (!(camera.getFocusedEntity() instanceof LivingEntity) || !((LivingEntity) camera.getFocusedEntity()).isSleeping())) - || (entity instanceof ClientPlayerEntity && camera.getFocusedEntity() != entity)) { + || (entity == camera.getFocusedEntity() && !camera.isThirdPerson() && (!(camera.getFocusedEntity() instanceof LivingEntity) || !((LivingEntity) camera.getFocusedEntity()).isSleeping())) + || (entity instanceof ClientPlayerEntity && camera.getFocusedEntity() != entity)) { continue; } @@ -643,7 +643,7 @@ public void renderWorld(MatrixStack matrixStack, float tickDelta, long limitTime profiler.swap("translucent"); renderTerrainLayer(true, matrixStack, cameraX, cameraY, cameraZ); - + VoxelMapHolder.postRenderLayerHandler.render(this, RenderLayer.getTranslucent(), matrixStack, cameraX, cameraY, cameraZ); fb = mcwr.getParticlesFramebuffer(); fb.clear(MinecraftClient.IS_SYSTEM_MAC); fb.copyDepthFrom(mcfb); @@ -656,6 +656,7 @@ public void renderWorld(MatrixStack matrixStack, float tickDelta, long limitTime } else { profiler.swap("translucent"); renderTerrainLayer(true, matrixStack, cameraX, cameraY, cameraZ); + VoxelMapHolder.postRenderLayerHandler.render(this, RenderLayer.getTranslucent(), matrixStack, cameraX, cameraY, cameraZ); profiler.swap("particles"); mc.particleManager.renderParticles(matrixStack, immediate, lightmapTextureManager, camera, tickDelta); } @@ -1018,24 +1019,24 @@ public boolean isEntityVisible(T entity) { case 0b011: return regions.wasSeen(rx0, ry0, rz0) || regions.wasSeen(rx1, ry0, rz0) - || regions.wasSeen(rx0, ry1, rz0) || regions.wasSeen(rx1, ry1, rz0); + || regions.wasSeen(rx0, ry1, rz0) || regions.wasSeen(rx1, ry1, rz0); case 0b100: return regions.wasSeen(rx0, ry0, rz0) || regions.wasSeen(rx0, ry0, rz1); case 0b101: return regions.wasSeen(rx0, ry0, rz0) || regions.wasSeen(rx1, ry0, rz0) - || regions.wasSeen(rx0, ry0, rz1) || regions.wasSeen(rx1, ry0, rz1); + || regions.wasSeen(rx0, ry0, rz1) || regions.wasSeen(rx1, ry0, rz1); case 0b110: return regions.wasSeen(rx0, ry0, rz0) || regions.wasSeen(rx0, ry1, rz0) - || regions.wasSeen(rx0, ry0, rz1) || regions.wasSeen(rx0, ry1, rz1); + || regions.wasSeen(rx0, ry0, rz1) || regions.wasSeen(rx0, ry1, rz1); case 0b111: return regions.wasSeen(rx0, ry0, rz0) || regions.wasSeen(rx1, ry0, rz0) - || regions.wasSeen(rx0, ry1, rz0) || regions.wasSeen(rx1, ry1, rz0) - || regions.wasSeen(rx0, ry0, rz1) || regions.wasSeen(rx1, ry0, rz1) - || regions.wasSeen(rx0, ry1, rz1) || regions.wasSeen(rx1, ry1, rz1); + || regions.wasSeen(rx0, ry1, rz0) || regions.wasSeen(rx1, ry1, rz0) + || regions.wasSeen(rx0, ry0, rz1) || regions.wasSeen(rx1, ry0, rz1) + || regions.wasSeen(rx0, ry1, rz1) || regions.wasSeen(rx1, ry1, rz1); } return true; @@ -1053,6 +1054,7 @@ public void render(MatrixStack matrices, float tickDelta, long limitTime, boolea WorldRenderEvent.BEFORE_WORLD_RENDER.invoker().beforeWorldRender(matrices, tickDelta, limitTime, renderBlockOutline, camera, gameRenderer, lightmapTextureManager, matrix4f); renderWorld(matrices, tickDelta, limitTime, renderBlockOutline, camera, gameRenderer, lightmapTextureManager, matrix4f); + VoxelMapHolder.postRenderHandler.render(this, matrices, tickDelta, limitTime, renderBlockOutline, camera, gameRenderer, lightmapTextureManager, matrix4f); WorldRenderEvent.AFTER_WORLD_RENDER.invoker().afterWorldRender(matrices, tickDelta, limitTime, renderBlockOutline, camera, gameRenderer, lightmapTextureManager, matrix4f); }