diff --git a/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/ReacharoundRenderCompat.java b/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/ReacharoundRenderCompat.java new file mode 100644 index 00000000..beb0d5b5 --- /dev/null +++ b/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/ReacharoundRenderCompat.java @@ -0,0 +1,52 @@ +package org.vmstudio.visor.compatibility.reacharound; + +import org.vmstudio.visor.MixinModLoader; +import org.vmstudio.visor.api.client.render.RenderPhase; +import org.vmstudio.visor.core.client.VisorState; +import org.vmstudio.visor.core.client.render.VRRenderState; + +import java.lang.reflect.Method; + +public final class ReacharoundRenderCompat { + private static final String IRIS_BUFFER_SOURCE = + "net.irisshaders.batchedentityrendering.impl.FullyBufferedMultiBufferSource"; + + private ReacharoundRenderCompat() {} + + public static void flushPreviewBuffer(Object context) { + if (!MixinModLoader.get().isModLoaded("connector") + || !VisorState.get().isActive() + || VRRenderState.getPhase() != RenderPhase.VR_WORLD) { + return; + } + + try { + Object buffers = invoke(context, "submitNodeCollector", "consumers"); + if (!IRIS_BUFFER_SOURCE.equals(buffers.getClass().getName())) { + return; + } + + Object usedSize = invoke(buffers, "getUsedSize"); + if (!(usedSize instanceof Number size) || size.longValue() <= 0L) { + return; + } + + invoke(buffers, "endBatch"); + } catch (ReflectiveOperationException ignored) { + // Fall back to the normal flush if the Connector or Iris API is unavailable. + } + } + + private static Object invoke(Object target, String... methodNames) throws ReflectiveOperationException { + for (String methodName : methodNames) { + Method method; + try { + method = target.getClass().getMethod(methodName); + } catch (NoSuchMethodException ignored) { + continue; + } + return method.invoke(target); + } + throw new NoSuchMethodException(String.join("/", methodNames)); + } +} diff --git a/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/RayTraceHandlerMixin.java b/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/RayTraceHandlerMixin.java index 3aa1568f..a5a1b086 100644 --- a/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/RayTraceHandlerMixin.java +++ b/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/RayTraceHandlerMixin.java @@ -1,21 +1,18 @@ package org.vmstudio.visor.compatibility.reacharound.mixin; +import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; +import org.apache.commons.lang3.tuple.Pair; import org.spongepowered.asm.mixin.Mixin; -import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Pseudo; -import org.apache.commons.lang3.tuple.Pair; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.vmstudio.visor.api.VisorAPI; -import org.vmstudio.visor.api.VisorClientState; import org.vmstudio.visor.api.client.player.VRLocalPlayer; import org.vmstudio.visor.api.client.player.pose.VRPlayerPoseClient; import org.vmstudio.visor.api.common.HandType; import org.vmstudio.visor.api.common.player.VRPose; -import org.vmstudio.visor.api.common.player.VisorPlayer; import org.vmstudio.visor.compatibility.MixinGate; import org.vmstudio.visor.core.client.VisorState; @@ -23,25 +20,17 @@ @MixinGate(classes = "com.spanser.reacharound.client.handler.RayTraceHandler") @Pseudo public class RayTraceHandlerMixin { - - @Inject(method = "getEntityParams", at = @At("HEAD"), cancellable = true) - - private static void visor$useControllerPose( Entity player, - CallbackInfoReturnable> cir - ){ - if(VisorState.get().isActive()){ - + @Inject(method = "getEntityParams", at = @At("HEAD"), cancellable = true, remap = false) + private static void visor$useControllerPose( + Entity player, + CallbackInfoReturnable> cir + ) { + if (VisorState.get().isActive()) { VRLocalPlayer vrPlayer = VisorAPI.client().getVRLocalPlayer(); HandType activeHand = vrPlayer.getActiveHand(); VRPlayerPoseClient playerPoseData = vrPlayer.getPoseData(); - VRPose handPose = playerPoseData.getHand(activeHand); - - cir.setReturnValue(Pair.of(handPose.getPositionVec3(), handPose.getDirectionVec3())); - - } } - } diff --git a/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/ReacharoundOverlayMixin.java b/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/ReacharoundOverlayMixin.java new file mode 100644 index 00000000..1cb83f98 --- /dev/null +++ b/visor-core/src/main/java/org/vmstudio/visor/compatibility/reacharound/mixin/ReacharoundOverlayMixin.java @@ -0,0 +1,62 @@ +package org.vmstudio.visor.compatibility.reacharound.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.vmstudio.visor.compatibility.MixinGate; +import org.vmstudio.visor.compatibility.reacharound.ReacharoundRenderCompat; + +@Pseudo +@Mixin(targets = "com.spanser.reacharound.client.gui.Overlay", remap = false) +@MixinGate(classes = "com.spanser.reacharound.client.gui.Overlay") +public class ReacharoundOverlayMixin { + @Unique + private boolean visor$previewSubmitted; + + @Inject(method = "render", at = @At("HEAD"), require = 0, remap = false) + private void visor$beginRender(CallbackInfo ci) { + visor$previewSubmitted = false; + } + + @Inject( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitCustomGeometry(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/RenderType;Lnet/minecraft/client/renderer/SubmitNodeCollector$CustomGeometryRenderer;)V", + shift = At.Shift.AFTER, + remap = false + ), + require = 0, + remap = false + ) + private void visor$afterFilledPreviewSubmit(CallbackInfo ci) { + visor$previewSubmitted = true; + } + + @Inject( + method = "render", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitShapeOutline(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/phys/shapes/VoxelShape;Lnet/minecraft/client/renderer/RenderType;IFZ)V", + shift = At.Shift.AFTER, + remap = false + ), + require = 0, + remap = false + ) + private void visor$afterOutlinePreviewSubmit(CallbackInfo ci) { + visor$previewSubmitted = true; + } + + @Inject(method = "render", at = @At("RETURN"), require = 0, remap = false) + private void visor$flushPreview(@Coerce Object context, CallbackInfo ci) { + if (visor$previewSubmitted) { + ReacharoundRenderCompat.flushPreviewBuffer(context); + visor$previewSubmitted = false; + } + } +} diff --git a/visor-core/src/main/resources/visor.reacharound.mixins.json b/visor-core/src/main/resources/visor.reacharound.mixins.json index 915de102..1f20747f 100644 --- a/visor-core/src/main/resources/visor.reacharound.mixins.json +++ b/visor-core/src/main/resources/visor.reacharound.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_${mixin_compat_level}", "refmap": "${mod_id}.refmap.json", "client": [ - "RayTraceHandlerMixin" + "RayTraceHandlerMixin", + "ReacharoundOverlayMixin" ], "server": [ ],