From 8bde5b87b1e2d8f9637d4d553d424bbba186bd1a Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 16:22:24 +0100 Subject: [PATCH 01/14] fix memory leak when toggling vr --- .../java/org/vivecraft/client_vr/provider/VRRenderer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java index cbcaa28dc..cc3df1c66 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java @@ -946,6 +946,11 @@ protected void destroyBuffers() { this.framebufferEye1 = null; this.RightEyeTextureId = -1; } + + if (this.mirrorFramebuffer != null) { + this.mirrorFramebuffer.destroyBuffers(); + this.mirrorFramebuffer = null; + } } /** From 5e7bf9df9d23304c76b3804400c4faef7bc36d4f Mon Sep 17 00:00:00 2001 From: fayer3 Date: Fri, 10 Jan 2025 04:46:06 +0100 Subject: [PATCH 02/14] fix main player animations when something tries to get rotinfo during tick --- .../org/vivecraft/client/ClientVRPlayers.java | 27 +++++++++++++++++++ .../player/AbstractClientPlayerMixin.java | 2 +- .../entity/EntityRenderDispatcherMixin.java | 5 ++-- .../state/ArmedEntityRenderStateMixin.java | 2 +- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index fd9e48c01..72910c494 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -88,6 +88,19 @@ public boolean isVRPlayer(UUID uuid) { (VRState.VR_RUNNING && this.mc.player != null && uuid.equals(this.mc.player.getUUID())); } + /** + * checks if the given player is in VR and using seated mode, without lerping the RotInfo + * + * @param uuid UUID of the player + * @return if the player is in VR and using seated modes + */ + public boolean isVRAndSeated(UUID uuid) { + return (this.vivePlayers.containsKey(uuid) && this.vivePlayers.get(uuid).seated) || + (VRState.VR_RUNNING && this.mc.player != null && uuid.equals(this.mc.player.getUUID()) && + ClientDataHolderVR.getInstance().vrSettings.seated + ); + } + /** * checks if the given player is in VR and using reversed hands, without lerping the RotInfo * @@ -281,6 +294,20 @@ public boolean hasHMD(UUID uuid) { return this.donors.containsKey(uuid); } + /** + * gets the latest clientside player data, use this when not rendering, i.e. on tick + * @param uuid uuid of the player to get the data for + * @return latest available player data + */ + public RotInfo getLatestRotationsForPlayer(UUID uuid) { + return this.vivePlayers.containsKey(uuid) ? this.vivePlayers.get(uuid) : this.vivePlayersLast.get(uuid); + } + + /** + * gets the clientside interpolated player data, this one should only be called during rendering + * @param uuid uuid of the player to get the data for + * @return interpolated data + */ public RotInfo getRotationsForPlayer(UUID uuid) { float partialTick = ClientUtils.getCurrentPartialTick(); diff --git a/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java b/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java index a7f6021c8..42d1f59f1 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/player/AbstractClientPlayerMixin.java @@ -52,7 +52,7 @@ public AbstractClientPlayerMixin( vivecraft$particlesWithRandomOffset(instance, particleData, original, pos, dir); } else { // remote players - ClientVRPlayers.RotInfo rotInfo = ClientVRPlayers.getInstance().getRotationsForPlayer(this.uuid); + ClientVRPlayers.RotInfo rotInfo = ClientVRPlayers.getInstance().getLatestRotationsForPlayer(this.uuid); if (rotInfo != null) { Vec3 pos; if (this.getUsedItemHand() == InteractionHand.MAIN_HAND) { diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/EntityRenderDispatcherMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/EntityRenderDispatcherMixin.java index 3f5bef927..36808b664 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/EntityRenderDispatcherMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/EntityRenderDispatcherMixin.java @@ -94,10 +94,9 @@ public abstract class EntityRenderDispatcherMixin implements ResourceManagerRelo (player.getClass() == LocalPlayer.class || player.getClass() == RemotePlayer.class)) { String skinType = player.getSkin().model().id(); - ClientVRPlayers.RotInfo rotInfo = ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()); - if (rotInfo != null) { + if (ClientVRPlayers.getInstance().isVRPlayer(player)) { VRPlayerRenderer vrPlayerRenderer; - if (rotInfo.seated || + if (ClientVRPlayers.getInstance().isVRAndSeated(player.getUUID()) || ClientDataHolderVR.getInstance().vrSettings.playerModelType == VRSettings.PlayerModelType.VANILLA) { vrPlayerRenderer = this.vivecraft$skinMapVRVanilla.getOrDefault(skinType, diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/state/ArmedEntityRenderStateMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/state/ArmedEntityRenderStateMixin.java index bd14b3e08..0cae3485c 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/state/ArmedEntityRenderStateMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/state/ArmedEntityRenderStateMixin.java @@ -41,7 +41,7 @@ public class ArmedEntityRenderStateMixin { { ItemStack otherStack = original.call(instance, humanoidArm.getOpposite()); if (ClimbTracker.isClaws(otherStack) && - !ClientVRPlayers.getInstance().getRotationsForPlayer(instance.getUUID()).seated) + !ClientVRPlayers.getInstance().isVRAndSeated(instance.getUUID())) { return otherStack; } From 2176c321058e735c5863bf2e9116547dcb7e9a2b Mon Sep 17 00:00:00 2001 From: fayer3 Date: Fri, 10 Jan 2025 18:51:08 +0100 Subject: [PATCH 03/14] fix vr player held items, with more than one player --- .../mixin/client/renderer/entity/PlayerRendererMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java index 045226d29..3744b66e0 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/entity/PlayerRendererMixin.java @@ -40,7 +40,7 @@ protected PlayerRendererMixin(EntityRendererProvider.Context context) { super(context); } - @Inject(method = "extractRenderState(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/client/renderer/entity/state/PlayerRenderState;F)V", at = @At("TAIL")) + @Inject(method = "extractRenderState(Lnet/minecraft/client/player/AbstractClientPlayer;Lnet/minecraft/client/renderer/entity/state/PlayerRenderState;F)V", at = @At("HEAD")) private void vivecraft$addRotInfo( AbstractClientPlayer entity, PlayerRenderState reusedState, float partialTick, CallbackInfo ci) { From b1c05c4c23ca3768b5ddaf604d1c7a72693ffa4b Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sat, 11 Jan 2025 00:04:13 +0100 Subject: [PATCH 04/14] fix slim first person hands offset --- .../mixin/client_vr/renderer/ItemInHandRendererVRMixin.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java index 4573d0faf..4272db574 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/ItemInHandRendererVRMixin.java @@ -270,13 +270,12 @@ protected abstract void renderPlayerArm( z offset: (arm y origin + arm y offset + arm y dimension) / 16 slim x offset: (5 + -1 + 3*0.5) / 16 = 0.34375 - z offset: (-2 + 2.5 + 12) / 16 = 0.78125 regular x offset: (5 - 1 + 4*0.5) / 16 = 0.375 z offset: (-2 + 2 + 12) / 16 = 0.75 */ - poseStack.translate((slim ? -0.34375F : -0.375F) * offsetDirection, 0.0F, slim ? 0.78125F : 0.75F); + poseStack.translate((slim ? -0.34375F : -0.375F) * offsetDirection, 0.0F, 0.75F); poseStack.mulPose(Axis.XP.rotationDegrees(-90)); poseStack.mulPose(Axis.YP.rotationDegrees(180)); From 042c162fb4a4518a6c880e6e30ecff2804d1d827 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sat, 11 Jan 2025 14:46:52 +0100 Subject: [PATCH 05/14] fix textbox suggestions colliding with the show keyboard text --- .../vivecraft/mixin/client_vr/gui/EditBoxVRMixin.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/EditBoxVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/EditBoxVRMixin.java index 27ff46dad..c58413368 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/gui/EditBoxVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/gui/EditBoxVRMixin.java @@ -40,6 +40,9 @@ public abstract class EditBoxVRMixin extends AbstractWidget { @Shadow public abstract int getInnerWidth(); + @Shadow + private String suggestion; + public EditBoxVRMixin(int x, int y, int width, int height, Component message) { super(x, y, width, height, message); } @@ -49,10 +52,10 @@ public EditBoxVRMixin(int x, int y, int width, int height, Component message) { GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, CallbackInfo ci, @Local String content, @Local(ordinal = 4) int xPos, @Local(ordinal = 5) int yPos) { - if (VRState.VR_RUNNING && content.isEmpty() && !ClientDataHolderVR.getInstance().vrSettings.seated && - !KeyboardHandler.SHOWING) + if (VRState.VR_RUNNING && !ClientDataHolderVR.getInstance().vrSettings.seated && !KeyboardHandler.SHOWING && + content.isEmpty()) { - if (this.hint == null || this.isFocused()) { + if ((this.hint == null && (this.suggestion == null || this.suggestion.isEmpty())) || this.isFocused()) { // limit text to field size String fullString = I18n.get("vivecraft.message.openKeyboard"); String cutString = this.font.plainSubstrByWidth(fullString, this.getInnerWidth()); From f0b0964ce119604b323bb70bef66a2bc50301b1a Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sat, 11 Jan 2025 23:50:26 +0100 Subject: [PATCH 06/14] fix scrolling button names on radial menu with non auto gui scale fix long radial button names slightly scrolling fix long radial buttons being able to overlap unify radial menu and radial config button layout --- .../gui/settings/GuiRadialConfiguration.java | 72 ++++------- .../vivecraft/client_vr/gui/GuiRadial.java | 113 ++++++++++-------- .../render/helpers/RenderHelper.java | 7 ++ 3 files changed, 94 insertions(+), 98 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRadialConfiguration.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRadialConfiguration.java index e5347384f..253358b8f 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRadialConfiguration.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRadialConfiguration.java @@ -10,8 +10,12 @@ import org.vivecraft.client.gui.framework.GuiVROptionButton; import org.vivecraft.client.gui.framework.GuiVROptionsBase; import org.vivecraft.client.gui.framework.VROptionLayout; +import org.vivecraft.client_vr.gui.GuiRadial; import org.vivecraft.client_vr.settings.VRSettings; +import java.util.Arrays; +import java.util.Optional; + public class GuiRadialConfiguration extends GuiVROptionsBase { private static final VROptionLayout[] OPTIONS = new VROptionLayout[]{ new VROptionLayout(VRSettings.VrOptions.RADIAL_MODE_HOLD, VROptionLayout.Position.POS_LEFT, 0.0F, true, "") @@ -87,12 +91,8 @@ public void init() { super.init(OPTIONS, false); - int numButtons = this.dataHolder.vrSettings.vrRadialButtons; - int buttonWidthMin = 120; - // distance from the center, with 14 buttons, move them closer together - float dist = numButtons * (numButtons >= 14 ? 5F : 5.5F); int centerX = this.width / 2; - int centerY = this.height / 2; + int centerY = this.height / 2 + 10; this.arr = ArrayUtils.clone(this.dataHolder.vrSettings.vrRadialItems); String[] altSet = ArrayUtils.clone(this.dataHolder.vrSettings.vrRadialItemsAlt); @@ -100,57 +100,29 @@ public void init() { this.arr = altSet; } - for (int i = 0; i < numButtons; i++) { - KeyMapping keymapping = null; - - for (KeyMapping keymapping1 : this.minecraft.options.keyMappings) { - if (i < this.arr.length && keymapping1.getName().equalsIgnoreCase(this.arr[i])) { - keymapping = keymapping1; - } - } - - String label = ""; - - if (keymapping != null) { - label = I18n.get(keymapping.getName()); - } - - int buttonWidth = Math.max(buttonWidthMin, this.font.width(label)); - - // coords of the button, button 0 is at the top with x = 0, y = -dist - float distX = numButtons * 4 + buttonWidth * 0.5F; - - // position buttons on equal y spacing - float btnIndex = (i < numButtons / 2 ? i : numButtons - i) / (float) (numButtons / 2); - int y = (int) (2.0F * dist * btnIndex - dist); - - // position x so the buttons produce an ellipse - int x = (int) (distX * (Math.sqrt(1.0F - (y * y) / (dist * dist)))); - - // move in between buttons closer to the middle - if (Math.abs(y) > 20) { - x = (int) (x * 0.87F); - } - - // second half of buttons should be on the left side - x *= i > numButtons / 2 ? -1 : 1; + for (int i = 0; i < this.dataHolder.vrSettings.vrRadialButtons; i++) { + // not all buttons need to be set + if (i >= this.arr.length) break; + String current = this.arr[i]; int index = i; - this.addRenderableWidget(new Button.Builder(Component.translatable(label), - (p) -> { - this.selectedIndex = index; - this.isselectmode = true; - this.reinit = true; - this.visibleList = this.list; - }) - .size(buttonWidth, 20) - .pos(centerX + x - buttonWidth / 2, centerY + y) - .build()); + Optional keyMapping = Arrays.stream(this.minecraft.options.keyMappings) + .filter(keymapping -> keymapping.getName().equalsIgnoreCase(current)) + .findFirst(); + + String label = keyMapping.map(mapping -> I18n.get(mapping.getName())).orElse(""); + this.addRenderableWidget(GuiRadial.createButton(label, (p) -> { + this.selectedIndex = index; + this.isselectmode = true; + this.reinit = true; + this.visibleList = this.list; + }, index, centerX, centerY)); } + // add button count button this.addRenderableWidget( new GuiVROptionButton(VRSettings.VrOptions.RADIAL_NUMBER.ordinal(), - centerX - 10, centerY, 20, 20, + centerX - 10, centerY - 10, 20, 20, VRSettings.VrOptions.RADIAL_NUMBER, "" + this.dataHolder.vrSettings.vrRadialButtons, (p) -> { this.dataHolder.vrSettings.vrRadialButtons += 2; diff --git a/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java b/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java index 294b83ddf..fd7392875 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java +++ b/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java @@ -1,14 +1,17 @@ package org.vivecraft.client_vr.gui; -import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.framework.TwoHandedScreen; +import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; +import java.util.Arrays; + public class GuiRadial extends TwoHandedScreen { private boolean isShift = false; String[] arr; @@ -19,10 +22,6 @@ public void init() { String[] altSet = this.dh.vrSettings.vrRadialItemsAlt; this.clearWidgets(); - int numButtons = this.dh.vrSettings.vrRadialButtons; - int buttonWidthMin = 120; - // distance from the center, with 14 buttons, move them closer together - float dist = numButtons * (numButtons >= 14 ? 5F : 5.5F); int centerX = this.width / 2; int centerY = this.height / 2; @@ -30,56 +29,25 @@ public void init() { this.arr = altSet; } - for (int i = 0; i < numButtons; i++) { - KeyMapping keymapping = null; - - for (KeyMapping keymapping1 : this.minecraft.options.keyMappings) { - if (i < this.arr.length && keymapping1.getName().equalsIgnoreCase(this.arr[i])) { - keymapping = keymapping1; - } - } - - String label = "?"; - - if (keymapping != null) { - label = I18n.get(keymapping.getName()); - } - - int buttonWidth = Math.max(buttonWidthMin, this.font.width(label)); - // coords of the button, button 0 is at the top with x = 0, y = -dist - float distX = numButtons * 4 + buttonWidth * 0.5F; - - // position buttons on equal y spacing - float btnIndex = (i < numButtons / 2 ? i : numButtons - i) / (float) (numButtons / 2); - int y = (int) (2.0F * dist * btnIndex - dist); - - // position x so the buttons produce an ellipse - int x = (int) (distX * (Math.sqrt(1.0F - (y * y) / (dist * dist)))); - - // move in between buttons closer to the middle - if (Math.abs(y) > 20) { - x = (int) (x * 0.87F); - } - - // second half of buttons should be on the left side - x *= i > numButtons / 2 ? -1 : 1; + for (int i = 0; i < this.dh.vrSettings.vrRadialButtons; i++) { + // not all buttons need to be set + if (i >= this.arr.length) break; + String current = this.arr[i]; int index = i; - - if (!"?".equals(label)) { - this.addRenderableWidget(new Button.Builder(Component.translatable(label), - (p) -> { + Arrays.stream(this.minecraft.options.keyMappings) + .filter(keymapping -> keymapping.getName().equalsIgnoreCase(current)) + .findFirst() + .ifPresent(keymapping -> { + String label = I18n.get(keymapping.getName()); + this.addRenderableWidget(createButton(label, (p) -> { VRInputAction vrinputaction = MCVR.get().getInputAction(this.arr[index]); - if (vrinputaction != null) { vrinputaction.pressBinding(); vrinputaction.unpressBinding(2); } - }) - .size(buttonWidth, 20) - .pos(centerX + x - buttonWidth / 2, centerY + y - 10) - .build()); - } + }, index, centerX, centerY)); + }); } } @@ -95,4 +63,53 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia this.renderBackground(guiGraphics, mouseX, mouseY, partialTick); super.render(guiGraphics, 0, 0, partialTick); } + + /** + * creates a Button withte given {@code action} and positions it in the radial circle + * + * @param label label of the button + * @param action action to call when pressing the button + * @param index button index in the circle + * @param centerX center of the circle on the screen, x coordinate + * @param centerY center of the circle on the screen, y coordinate + * @return Button positioned athte right spot + */ + public static Button createButton( + String label, Button.OnPress action, int index, int centerX, int centerY) + { + int buttonWidthMin = 120; + int numButtons = ClientDataHolderVR.getInstance().vrSettings.vrRadialButtons; + + // distance from the center, with 14 buttons, move them closer together + float dist = numButtons * (numButtons >= 14 ? 5F : 5.5F); + + int buttonWidth = Math.max(buttonWidthMin, Minecraft.getInstance().font.width(label) + 4); + // coords of the button, button 0 is at the top with x = 0, y = -dist + float distX = numButtons * 4 + buttonWidth * 0.5F; + + // position buttons on equal y spacing + float btnIndex = (index < numButtons / 2 ? index : numButtons - index) / (float) (numButtons / 2); + int y = (int) (2.0F * dist * btnIndex - dist); + + // position x so the buttons produce an ellipse + int x = (int) (distX * (Math.sqrt(1.0F - (y * y) / (dist * dist)))); + + // move in between buttons closer to the middle + if (Math.abs(y) > 20) { + x = (int) (x * 0.87F); + } + + // don't go over the center + if (index != 0 && index != numButtons / 2) { + x = Math.max(buttonWidth / 2, x); + } + + // second half of buttons should be on the left side + x *= index > numButtons / 2 ? -1 : 1; + + return new Button.Builder(Component.translatable(label), action) + .size(buttonWidth, 20) + .pos(centerX + x - buttonWidth / 2, centerY + y - 10) + .build(); + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/RenderHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/RenderHelper.java index 8c3752642..fb3156097 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/RenderHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/RenderHelper.java @@ -283,6 +283,10 @@ public static void drawScreen( double guiScale = maxGuiScale ? GuiHandler.GUI_SCALE_FACTOR_MAX : MC.getWindow().getGuiScale(); + // set gui scale to make the scissor work, that checks the window gui scale + int backupGuiScale = GuiHandler.GUI_SCALE_FACTOR; + GuiHandler.GUI_SCALE_FACTOR = (int) guiScale; + Matrix4f guiProjection = (new Matrix4f()).setOrtho( 0.0F, (float) (MC.getMainRenderTarget().width / guiScale), (float) (MC.getMainRenderTarget().height / guiScale), 0.0F, @@ -304,6 +308,9 @@ public static void drawScreen( GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); + // reset gui scale + GuiHandler.GUI_SCALE_FACTOR = backupGuiScale; + poseStack.popMatrix(); if (DATA_HOLDER.vrSettings.guiMipmaps) { From d82b4beb7075f4fc36e5ca3a97e2f7fb3c01badb Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 01:08:43 +0100 Subject: [PATCH 07/14] add armor based feet damage --- .../vivecraft/common/network/BodyPart.java | 8 +++++ .../mixin/server/ServerPlayerMixin.java | 33 +++++++++++++++++++ .../mixin/world/entity/PlayerMixin.java | 14 ++++++++ .../vivecraft/server/config/ServerConfig.java | 5 +++ 4 files changed, 60 insertions(+) diff --git a/common/src/main/java/org/vivecraft/common/network/BodyPart.java b/common/src/main/java/org/vivecraft/common/network/BodyPart.java index 35b2109da..87f23f695 100644 --- a/common/src/main/java/org/vivecraft/common/network/BodyPart.java +++ b/common/src/main/java/org/vivecraft/common/network/BodyPart.java @@ -39,4 +39,12 @@ public boolean isValid(FBTMode fbtMode) { case RIGHT_KNEE, LEFT_KNEE, RIGHT_ELBOW, LEFT_ELBOW -> fbtMode == FBTMode.WITH_JOINTS; }; } + + public boolean isFoot() { + return this == RIGHT_FOOT || this == LEFT_FOOT; + } + + public boolean isHand() { + return this == MAIN_HAND || this == OFF_HAND; + } } diff --git a/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java b/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java index 48a7b1f1e..df80d9722 100644 --- a/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/server/ServerPlayerMixin.java @@ -12,7 +12,9 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; @@ -20,6 +22,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.item.component.ItemAttributeModifiers; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Final; @@ -29,6 +32,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.vivecraft.mixin.world.entity.PlayerMixin; @@ -104,6 +108,35 @@ protected ServerPlayerMixin(EntityType entityType, Level } } + /** + * inject into {@link Player#attack} + */ + @Override + protected float vivecraft$damageModifier(float damage) { + // feet make more damage with boots + if (ServerConfig.DUAL_WIELDING.get() && ServerConfig.BOOTS_ARMOR_DAMAGE.get() > 0) { + ServerVivePlayer vivePlayer = vivecraft$getVivePlayer(); + if (vivePlayer.isVR() && vivePlayer.activeBodyPart.isFoot() && + !this.getItemBySlot(EquipmentSlot.FEET).isEmpty()) + { + float addedDamage = 0F; + for (ItemAttributeModifiers.Entry entry : this.getItemBySlot(EquipmentSlot.FEET) + .getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY).modifiers()) + { + if (entry.attribute().is(Attributes.ARMOR)) { + float amount = (float) entry.modifier().amount(); + switch (entry.modifier().operation()) { + case ADD_VALUE -> addedDamage += amount; + case ADD_MULTIPLIED_TOTAL -> addedDamage += amount * addedDamage; + } + } + } + return damage + addedDamage * ServerConfig.BOOTS_ARMOR_DAMAGE.get().floatValue(); + } + } + return damage; + } + @Inject(method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z") ) private void vivecraft$dropVive( diff --git a/common/src/main/java/org/vivecraft/mixin/world/entity/PlayerMixin.java b/common/src/main/java/org/vivecraft/mixin/world/entity/PlayerMixin.java index e1c4c645a..07625d8f4 100644 --- a/common/src/main/java/org/vivecraft/mixin/world/entity/PlayerMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/world/entity/PlayerMixin.java @@ -5,15 +5,18 @@ import net.minecraft.core.particles.ParticleOptions; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; 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.ModifyArg; import org.vivecraft.mixin.server.ServerPlayerMixin; @Mixin(Player.class) @@ -26,6 +29,9 @@ public abstract class PlayerMixin extends LivingEntity { @Final public InventoryMenu inventoryMenu; + @Shadow + public abstract ItemStack getItemBySlot(EquipmentSlot slot); + protected PlayerMixin(EntityType entityType, Level level) { super(entityType, level); } @@ -40,4 +46,12 @@ protected PlayerMixin(EntityType entityType, Level level { return original.call(instance, type, posX, posY, posZ, particleCount, xOffset, yOffset, zOffset, speed); } + + /** + * dummy to be overridden in {@link ServerPlayerMixin} + */ + @ModifyArg(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurtOrSimulate(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + protected float vivecraft$damageModifier(float damage) { + return damage; + } } diff --git a/common/src/main/java/org/vivecraft/server/config/ServerConfig.java b/common/src/main/java/org/vivecraft/server/config/ServerConfig.java index 0e2dfe808..632189de7 100644 --- a/common/src/main/java/org/vivecraft/server/config/ServerConfig.java +++ b/common/src/main/java/org/vivecraft/server/config/ServerConfig.java @@ -49,6 +49,7 @@ public class ServerConfig { public static ConfigBuilder.StringValue MESSAGES_KICK_VR_ONLY; public static ConfigBuilder.BooleanValue DUAL_WIELDING; + public static ConfigBuilder.DoubleValue BOOTS_ARMOR_DAMAGE; public static ConfigBuilder.DoubleValue CREEPER_SWELL_DISTANCE; public static ConfigBuilder.DoubleValue BOW_STANDING_MULTIPLIER; public static ConfigBuilder.DoubleValue BOW_SEATED_MULTIPLIER; @@ -249,6 +250,10 @@ private static void fixConfig(CommentedConfig config, ConfigSpec.CorrectionListe .push("dualWielding") .comment("Allows vr players to hit with their offhand items") .define(true); + BOOTS_ARMOR_DAMAGE = BUILDER + .push("bootsArmorDamage") + .comment("Melee damage addition for Vivecraft users when hitting with their feet.\n This scales with the armor attribute of the boots, doing 1 additional damage per Armor level, times the set multiplier\n Set to 0.0 to disable") + .defineInRange(0.0, 0.0, 5.0); BUILDER .push("bow") From bdb9423b5e431aec2a9ecffc83941a5998c38e4b Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 02:57:34 +0100 Subject: [PATCH 08/14] fix fbt trackers with origin offset fix tracker rendering in the main menu fixes #341 --- .../vivecraft/client_vr/provider/MCVR.java | 14 +++++++++++-- .../client_vr/provider/nullvr/NullVR.java | 15 ++++++++++++-- .../provider/openvr_lwjgl/MCOpenVR.java | 12 ++++++++++- .../org/vivecraft/common/utils/MathUtils.java | 20 +++++++++++++++---- .../renderer/GameRendererVRMixin.java | 2 ++ 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index 36281af82..4c9e03554 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -1347,9 +1347,18 @@ public void resetFBT() { */ public List> getTrackers() { List> poses = new ArrayList<>(); + + Vector3f offset = new Vector3f(); + if (!this.dh.vrSettings.seated && this.dh.vrSettings.allowStandingOriginOffset) { + if (this.dh.vr.isHMDTracking()) { + offset.set(this.dh.vrSettings.originOffset); + } + } + for (int i = 3; i < TRACKABLE_DEVICE_COUNT; i++) { if (this.deviceSource[i].isValid()) { - poses.add(Triple.of(this.deviceSource[i], i, this.controllerPose[i])); + poses.add(Triple.of(this.deviceSource[i], i, + MathUtils.addTranslation(new Matrix4f(this.controllerPose[i]), offset))); } } @@ -1360,7 +1369,8 @@ public List> getTrackers() { if (tracker.isTracking() && poses.stream().noneMatch(t -> t.getLeft().is(DeviceSource.Source.OSC, finalI))) { - poses.add(Triple.of(new DeviceSource(DeviceSource.Source.OSC, i), -1, tracker.pose)); + poses.add(Triple.of(new DeviceSource(DeviceSource.Source.OSC, i), -1, + MathUtils.addTranslation(new Matrix4f(tracker.pose), offset))); } } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java index 1248914bc..d4647887f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java @@ -217,18 +217,29 @@ public boolean hasCameraTracker() { public List> getTrackers() { List> trackers = super.getTrackers(); int trackerCount = this.fbtMode == FBTMode.ARMS_LEGS ? 3 : this.fbtMode == FBTMode.WITH_JOINTS ? 7 : 0; + + Vector3f offset = new Vector3f(); + if (!this.dh.vrSettings.seated && this.dh.vrSettings.allowStandingOriginOffset) { + if (this.dh.vr.isHMDTracking()) { + offset.set(this.dh.vrSettings.originOffset); + } + } + for (int i = 3; i < 3 + trackerCount; i++) { int type = -1; // check if we already know the role of the tracker for (int t = 0; t < TRACKABLE_DEVICE_COUNT; t++) { - if (this.deviceSource[i].is(DeviceSource.Source.NULL, i)) { + if (this.deviceSource[t].is(DeviceSource.Source.NULL, i)) { type = t; + break; } } int finalI = i; if (trackers.stream().noneMatch(t -> t.getLeft().is(DeviceSource.Source.NULL, finalI))) { trackers.add(Triple.of(new DeviceSource(DeviceSource.Source.NULL, i), type, - new Matrix4f().rotation(this.deviceRotations[i]).setTranslation(this.deviceOffsets[i]))); + new Matrix4f().rotation(this.deviceRotations[i]) + .setTranslation(this.deviceOffsets[i].x + offset.x, this.deviceOffsets[i].y + offset.y, + this.deviceOffsets[i].z + offset.z))); } } return trackers; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 364678f66..e2cf8020f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -1742,18 +1742,28 @@ private List getTrackerIds() { public List> getTrackers() { List> trackers = super.getTrackers(); List ovrTrackers = getTrackerIds(); + + Vector3f offset = new Vector3f(); + if (!this.dh.vrSettings.seated && this.dh.vrSettings.allowStandingOriginOffset) { + if (this.dh.vr.isHMDTracking()) { + offset.set(this.dh.vrSettings.originOffset); + } + } + for (int tracker : ovrTrackers) { int type = -1; // check if we already know the role of the tracker for (int i = 0; i < TRACKABLE_DEVICE_COUNT; i++) { if (this.deviceSource[i].is(DeviceSource.Source.OPENVR, tracker)) { type = i; + break; } } // super already adds the assigned trackers if (trackers.stream().noneMatch(t -> t.getLeft().is(DeviceSource.Source.OPENVR, tracker))) { trackers.add( - Triple.of(new DeviceSource(DeviceSource.Source.OPENVR, tracker), type, this.poseMatrices[tracker])); + Triple.of(new DeviceSource(DeviceSource.Source.OPENVR, tracker), type, + MathUtils.addTranslation(new Matrix4f(this.poseMatrices[tracker]), offset))); } } return trackers; diff --git a/common/src/main/java/org/vivecraft/common/utils/MathUtils.java b/common/src/main/java/org/vivecraft/common/utils/MathUtils.java index df505cc94..e4f707840 100644 --- a/common/src/main/java/org/vivecraft/common/utils/MathUtils.java +++ b/common/src/main/java/org/vivecraft/common/utils/MathUtils.java @@ -2,10 +2,9 @@ import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; -import org.joml.Quaternionf; -import org.joml.Quaternionfc; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.*; + +import java.lang.Math; public class MathUtils { @@ -183,6 +182,19 @@ public static Vector3f getEulerAnglesZYX(Quaternionfc rot, Vector3f eulerAngles) return eulerAngles; } + /** + * adds the give nvector to the translation component, without doing any Matrix multiplication + * + * @param matrix Matrix to alter + * @param translation Translation to add + * @return the supplied matrix, for chaining + */ + public static Matrix4f addTranslation(Matrix4f matrix, Vector3f translation) { + return matrix.m30(matrix.m30() + translation.x) + .m31(matrix.m31() + translation.y) + .m32(matrix.m32() + translation.z); + } + /** * calculates the body yaw based on the two controller positions and the head direction * diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java index ff57acd2a..dfef2b692 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java @@ -335,6 +335,8 @@ public abstract class GameRendererVRMixin RenderSystem.getModelViewStack().pushMatrix().identity(); RenderHelper.applyVRModelView(vivecraft$DATA_HOLDER.currentPass, RenderSystem.getModelViewStack()); + vivecraft$resetProjectionMatrix(partialTick); + VREffectsHelper.renderGuiLayer(partialTick, true); DebugRenderHelper.renderDebug(partialTick); From 747aa61e0cac412f1ef2c809f81fae7f0d372a4b Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 03:41:40 +0100 Subject: [PATCH 09/14] fix rain position when eyes are in different blocks --- .../WeatherEffectRendererVRMixin.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/WeatherEffectRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/WeatherEffectRendererVRMixin.java index dae7d347d..b590dfd4b 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/WeatherEffectRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/WeatherEffectRendererVRMixin.java @@ -1,10 +1,15 @@ package org.vivecraft.mixin.client_vr.renderer; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; import net.minecraft.client.renderer.WeatherEffectRenderer; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_xr.render_pass.RenderPassType; @@ -23,4 +28,25 @@ public class WeatherEffectRendererVRMixin { return cameraPos; } } + + @Inject(method = "renderInstances", at = @At("HEAD")) + private void vivecraft$centerPos(CallbackInfo ci, @Share("centerPos") LocalRef centerPos) { + if (!RenderPassType.isVanilla() && (ClientDataHolderVR.getInstance().currentPass == RenderPass.LEFT || + ClientDataHolderVR.getInstance().currentPass == RenderPass.RIGHT + )) + { + centerPos.set( + ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_render.getEye(RenderPass.CENTER).getPosition()); + } + } + + @ModifyArg(method = "renderInstances", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;floor(D)I", ordinal = 0)) + private double vivecraft$centerPosZ(double z, @Share("centerPos") LocalRef centerPos) { + return centerPos.get() != null ? centerPos.get().z : z; + } + + @ModifyArg(method = "renderInstances", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;floor(D)I", ordinal = 1)) + private double vivecraft$centerPosX(double x, @Share("centerPos") LocalRef centerPos) { + return centerPos.get() != null ? centerPos.get().x : x; + } } From 77027abc13f30d1cdbef5c3637077d5bf9630b61 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 04:08:32 +0100 Subject: [PATCH 10/14] fix crash when vr fabulous shader fails to compile --- .../client_vr/provider/VRRenderer.java | 10 ++++++ .../vivecraft/client_vr/render/VRShaders.java | 19 +++++++---- .../client/renderer/ShaderManagerMixin.java | 33 +++++++++++++++++++ .../renderer/LevelRendererVRMixin.java | 13 +------- .../assets/vivecraft/lang/de_de.json | 1 + .../assets/vivecraft/lang/en_us.json | 1 + .../main/resources/vivecraft.accesswidener | 4 +++ .../src/main/resources/vivecraft.mixins.json | 1 + 8 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/mixin/client/renderer/ShaderManagerMixin.java diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java index cc3df1c66..a32ea287f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java @@ -520,6 +520,16 @@ public void setupRenderConfiguration() throws RenderConfigException, IOException this.reinitFrameBuffers("gfx setting changed to: " + this.previousGraphics); } + if (minecraft.options.graphicsMode().get() == GraphicsStatus.FABULOUS && + minecraft.getShaderManager().getProgram(VRShaders.VR_TRANSPARENCY_SHADER) == null) + { + // fabulous shader didn't compile + minecraft.gui.getChat().addMessage(Component.translatable("vivecraft.messages.fabulousFailed")); + minecraft.options.graphicsMode().set(GraphicsStatus.FAST); + minecraft.levelRenderer.allChanged(); + this.reinitFrameBuffers("fabulous missing"); + } + if (this.resizeFrameBuffers && !this.reinitFrameBuffers) { Tuple tuple = this.getRenderTextureSizes(); int eyew = tuple.getA(); diff --git a/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java b/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java index 79cf11e3b..cd0faa845 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java @@ -10,14 +10,14 @@ public class VRShaders { // FSAA shader and its uniforms - public static ShaderProgram LANCZOS_SHADER = new ShaderProgram( + public static final ShaderProgram LANCZOS_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/lanczos_vr"), DefaultVertexFormat.POSITION_TEX, ShaderDefines.EMPTY); public static AbstractUniform LANCZOS_TEXEL_WIDTH_OFFSET_UNIFORM; public static AbstractUniform LANCZOS_TEXEL_HEIGHT_OFFSET_UNIFORM; // mixed reality shader and its uniforms - public static ShaderProgram MIXED_REALITY_SHADER = new ShaderProgram( + public static final ShaderProgram MIXED_REALITY_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/mixedreality_vr"), DefaultVertexFormat.POSITION_TEX, ShaderDefines.EMPTY); public static AbstractUniform MIXED_REALITY_HMD_VIEW_POSITION_UNIFORM; @@ -29,7 +29,7 @@ public class VRShaders { public static AbstractUniform MIXED_REALITY_ALPHA_MODE_UNIFORM; // vr post shader and its uniforms - public static ShaderProgram POST_PROCESSING_SHADER = new ShaderProgram( + public static final ShaderProgram POST_PROCESSING_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/postprocessing_vr"), DefaultVertexFormat.POSITION_TEX, ShaderDefines.EMPTY); public static AbstractUniform POST_PROCESSING_FOV_REDUCTION_RADIUS_UNIFORM; @@ -45,18 +45,25 @@ public class VRShaders { public static AbstractUniform POST_PROCESSING_OVERLAY_EYE_UNIFORM; // blit shader - public static ShaderProgram BLIT_VR_SHADER = new ShaderProgram( + public static final ShaderProgram BLIT_VR_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/blit_vr"), DefaultVertexFormat.POSITION_TEX, ShaderDefines.EMPTY); // end portal shaders - public static ShaderProgram RENDERTYPE_END_PORTAL_VR_SHADER = new ShaderProgram( + public static final ShaderProgram RENDERTYPE_END_PORTAL_VR_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/rendertype_end_portal_vr"), DefaultVertexFormat.POSITION, ShaderDefines.EMPTY); - public static ShaderProgram RENDERTYPE_END_GATEWAY_VR_SHADER = new ShaderProgram( + public static final ShaderProgram RENDERTYPE_END_GATEWAY_VR_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/rendertype_end_gateway_vr"), DefaultVertexFormat.POSITION, ShaderDefines.EMPTY); + // fabulous vr shader + public static final ResourceLocation VR_TRANSPARENCY_SHADER_ID = ResourceLocation.fromNamespaceAndPath("vivecraft", + "post/vrtransparency"); + public static final ShaderProgram VR_TRANSPARENCY_SHADER = new ShaderProgram( + VR_TRANSPARENCY_SHADER_ID, + DefaultVertexFormat.POSITION, ShaderDefines.EMPTY); + private VRShaders() {} public static void setupDepthMask() { diff --git a/common/src/main/java/org/vivecraft/mixin/client/renderer/ShaderManagerMixin.java b/common/src/main/java/org/vivecraft/mixin/client/renderer/ShaderManagerMixin.java new file mode 100644 index 000000000..c3a8f95a1 --- /dev/null +++ b/common/src/main/java/org/vivecraft/mixin/client/renderer/ShaderManagerMixin.java @@ -0,0 +1,33 @@ +package org.vivecraft.mixin.client.renderer; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.renderer.ShaderManager; +import net.minecraft.client.renderer.ShaderProgram; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.vivecraft.client_vr.render.VRShaders; +import org.vivecraft.client_vr.settings.VRSettings; + +import java.util.Map; +import java.util.Optional; + +@Mixin(ShaderManager.class) +public class ShaderManagerMixin { + @WrapOperation(method = "apply(Lnet/minecraft/client/renderer/ShaderManager$Configs;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 1)) + private Object vivecraft$letTransparencyFail( + Map instance, Object program, Object exception, Operation original, + @Local ShaderManager.CompilationCache compilationCache) + { + if (((ShaderProgram) program).configId().equals(VRShaders.VR_TRANSPARENCY_SHADER_ID)) { + // let vrtransparency fail, some gpus don't support the 18 samplers we need + VRSettings.LOGGER.error( + "Vivecraft: Failed to compile '{}' fabulous graphics will not be available in VR.", + VRShaders.VR_TRANSPARENCY_SHADER_ID, (ShaderManager.CompilationException) exception); + compilationCache.programs.put((ShaderProgram) program, Optional.empty()); + return null; + } + return original.call(instance, program, exception); + } +} diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java index 376628b48..f449308cc 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java @@ -9,7 +9,6 @@ import com.llamalad7.mixinextras.sugar.ref.LocalRef; import com.mojang.blaze3d.framegraph.FrameGraphBuilder; import com.mojang.blaze3d.framegraph.FramePass; -import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.resource.RenderTargetDescriptor; import com.mojang.blaze3d.systems.RenderSystem; @@ -50,7 +49,6 @@ import org.vivecraft.mod_compat_vr.optifine.OptifineHelper; import org.vivecraft.mod_compat_vr.shaders.ShadersHelper; -import javax.annotation.Nullable; import java.util.Set; // priority 999 to inject before iris, for the vrFast rendering @@ -61,15 +59,6 @@ public abstract class LevelRendererVRMixin implements ResourceManagerReloadListe private static final ResourceLocation vivecraft$VR_TRANSPARENCY_POST_CHAIN_ID = ResourceLocation.fromNamespaceAndPath( "vivecraft", "vrtransparency"); - @Unique - @Nullable - private RenderTarget vivecraft$alphaSortVROccludedFramebuffer; - @Unique - @Nullable - private RenderTarget vivecraft$alphaSortVRUnoccludedFramebuffer; - @Unique - @Nullable - private RenderTarget vivecraft$alphaSortVRHandsFramebuffer; @Unique private Entity vivecraft$renderedEntity; @@ -347,7 +336,7 @@ protected abstract void renderHitOutline( ShaderManager instance, ResourceLocation id, Set externalTargets, Operation original) { - if (VRState.VR_INITIALIZED) { + if (VRState.VR_RUNNING) { return original.call(instance, vivecraft$VR_TRANSPARENCY_POST_CHAIN_ID, LevelTargetBundleExtension.VR_TARGETS); } else { diff --git a/common/src/main/resources/assets/vivecraft/lang/de_de.json b/common/src/main/resources/assets/vivecraft/lang/de_de.json index d480b73b5..cd0391417 100644 --- a/common/src/main/resources/assets/vivecraft/lang/de_de.json +++ b/common/src/main/resources/assets/vivecraft/lang/de_de.json @@ -592,6 +592,7 @@ "vivecraft.messages.openSettings": "Klicken um die Einstellungen zu öffnen.", "vivecraft.messages.blocklist.title": "Server ist auf der Vivecraft Serverblockliste", "vivecraft.messages.blocklist": "Der ausgewählte Server '%s' ist auf der Vivecraft Serverblockliste.\nDas Fortsetzen wird Vivecraft komplett deaktivieren.", + "vivecraft.messages.fabulousFailed": "§a[Vivecraft]§r §cFabelhaft VR Shader konnte nicht kompiliert werden, prüfe den Log für den kompletten Fehler.", "vivecraft.message.kofi": "Unterstütze uns auf Ko-Fi", "vivecraft.message.overriddenbyserver": "§6Einstellung überschrieben vom Server.§r\n", "vivecraft.message.limitedbyserver": "§6Einstellungsbereich vom Server limitiert (%s - %s)§r\n", diff --git a/common/src/main/resources/assets/vivecraft/lang/en_us.json b/common/src/main/resources/assets/vivecraft/lang/en_us.json index 834a5b926..6b8f7b968 100644 --- a/common/src/main/resources/assets/vivecraft/lang/en_us.json +++ b/common/src/main/resources/assets/vivecraft/lang/en_us.json @@ -594,6 +594,7 @@ "vivecraft.messages.openSettings": "Click to open settings", "vivecraft.messages.blocklist.title": "Server is on the Vivecraft Server Blocklist", "vivecraft.messages.blocklist": "The selected Server '%s' is on the Vivecraft Server Blocklist.\nContinuing to join will completely disable Vivecraft.", + "vivecraft.messages.fabulousFailed": "§a[Vivecraft]§r §cFabulous VR shader failed to compile, check the log for the full error.", "vivecraft.message.kofi": "Support us on Ko-Fi", "vivecraft.message.overriddenbyserver": "§6Setting overridden by server.§r\n", "vivecraft.message.limitedbyserver": "§6Setting range limited by server (%s - %s)§r\n", diff --git a/common/src/main/resources/vivecraft.accesswidener b/common/src/main/resources/vivecraft.accesswidener index 0c18a385e..d6c412f9a 100644 --- a/common/src/main/resources/vivecraft.accesswidener +++ b/common/src/main/resources/vivecraft.accesswidener @@ -100,3 +100,7 @@ accessible field net/minecraft/server/network/ServerGamePacketListenerImpl above # to render the camera widget with dispaly accessible field net/minecraft/client/renderer/item/ItemStackRenderState layers [Lnet/minecraft/client/renderer/item/ItemStackRenderState$LayerRenderState; accessible field net/minecraft/client/renderer/item/ItemStackRenderState$LayerRenderState model Lnet/minecraft/client/resources/model/BakedModel; + +# to let the vr transparancy shader fail to compile +accessible class net/minecraft/client/renderer/ShaderManager$CompilationCache +accessible field net/minecraft/client/renderer/ShaderManager$CompilationCache programs Ljava/util/Map; diff --git a/common/src/main/resources/vivecraft.mixins.json b/common/src/main/resources/vivecraft.mixins.json index 6993820fd..cf5fedc51 100644 --- a/common/src/main/resources/vivecraft.mixins.json +++ b/common/src/main/resources/vivecraft.mixins.json @@ -20,6 +20,7 @@ "client.player.AbstractClientPlayerMixin", "client.renderer.ItemBlockRenderTypesMixin", "client.renderer.RenderStateShardAccessor", + "client.renderer.ShaderManagerMixin", "client.renderer.block.LiquidBlockRendererMixin", "client.renderer.entity.EntityRenderDispatcherMixin", "client.renderer.entity.ItemRendererVRMixin", From d2b891fb1bda6317341122f454cc2a0f5d3d8a83 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 17:20:36 +0100 Subject: [PATCH 11/14] fix black flickering with sodium, fixes #340 and also fixes #223 --- .../java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java index 756a7a5ad..1e8d505f0 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java @@ -338,6 +338,9 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { this.mainRenderTarget.clear(); this.mainRenderTarget.bindWrite(true); + // somehow without this it causes issues with the lightmap sometimes + this.mainRenderTarget.unbindRead(); + // draw screen/gui to buffer // push pose so we can pop it later RenderSystem.getModelViewStack().pushMatrix(); From 14a6a5f2a2563ea2ce2990033e9108c490a08685 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 17:21:33 +0100 Subject: [PATCH 12/14] fix gui being rendered twice with fabulous --- .../mixin/client_vr/renderer/LevelRendererVRMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java index f449308cc..4033b813e 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/LevelRendererVRMixin.java @@ -302,7 +302,7 @@ protected abstract void renderHitOutline( // if the gui didn't render yet, render it now. // or if shaders are on, and option AFTER_SHADER is selected - @Inject(method = "renderLevel", at = @At("RETURN")) + @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Ljava/util/List;clear()V")) private void vivecraft$renderVrStuffFinal( CallbackInfo ci, @Local(ordinal = 0) float partialTick, @Share("guiRendered") LocalBooleanRef guiRendered) { From 412187e44ecaf82d0508d8d16f7ea773e9506691 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 22:02:59 +0100 Subject: [PATCH 13/14] change pick to modify the entities position/view, instead, to fix mod compatibility issues fixes block placement with Valkyrie skies and a possible crash fixes crosshair getting stuck with create and cut through fixes #253 --- .../renderer/GameRendererVRMixin.java | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java index dfef2b692..1267668d6 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/renderer/GameRendererVRMixin.java @@ -3,6 +3,7 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; @@ -133,50 +134,45 @@ public abstract class GameRendererVRMixin return new XRCamera(); } - @Inject(method = "pick(F)V", at = @At("HEAD"), cancellable = true) - private void vivecraft$skipFirstPick(CallbackInfo ci) { - if (VRState.VR_RUNNING && vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render == null) { - ci.cancel(); - } - } + @WrapMethod(method = "pick(F)V") + private void vivecraft$vrPick(float partialTick, Operation original) { + if (VRState.VR_RUNNING) { + // skip when data not available yet + if (vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render == null || + this.minecraft.getCameraEntity() == null) + { + return; + } - @WrapOperation(method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;pick(DFZ)Lnet/minecraft/world/phys/HitResult;")) - private HitResult vivecraft$changeRaytrace( - Entity instance, double hitDistance, float partialTick, boolean hitFluids, Operation original) - { - if (!VRState.VR_RUNNING) { - return original.call(instance, hitDistance, partialTick, hitFluids); - } else { - this.vivecraft$crossVec = vivecraft$DATA_HOLDER.vrPlayer.AimedPointAtDistance( - vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render, 0, hitDistance); - return vivecraft$DATA_HOLDER.vrPlayer.rayTraceBlocksVR(vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render, - 0, hitDistance, hitFluids); + // set the entity position and view to the controller + this.vivecraft$cacheRVEPos(this.minecraft.getCameraEntity()); + this.vivecraft$setupRVEAtDevice(vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render.getController(0)); } - } - @WrapOperation(method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getEyePosition(F)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 vivecraft$changeRayStart(Entity instance, float partialTick, Operation original) { - if (!VRState.VR_RUNNING) { - return original.call(instance, partialTick); - } else { - return vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render.getController(0).getPosition(); + // call the vanilla method + original.call(partialTick); + + if (VRState.VR_RUNNING) { + // restore entity + this.vivecraft$restoreRVEPos(this.minecraft.getCameraEntity()); } } - @WrapOperation(method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getViewVector(F)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 vivecraft$changeRayDirection(Entity instance, float partialTick, Operation original) { - if (!VRState.VR_RUNNING) { - return original.call(instance, partialTick); - } else { - return new Vec3(vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render.getController(0).getDirection()); + @ModifyArg(method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;pick(DFZ)Lnet/minecraft/world/phys/HitResult;"), index = 0) + private double vivecraft$getCrossVec(double hitDistance) { + if (VRState.VR_RUNNING) { + // get the end of the reach point here, to have the correct reach distance + this.vivecraft$crossVec = vivecraft$DATA_HOLDER.vrPlayer.AimedPointAtDistance( + vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render, 0, hitDistance); } + return hitDistance; } @ModifyArg(method = "pick(Lnet/minecraft/world/entity/Entity;DDF)Lnet/minecraft/world/phys/HitResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ProjectileUtil;getEntityHitResult(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;D)Lnet/minecraft/world/phys/EntityHitResult;")) private Predicate vivecraft$dontHitRiddenEntity(Predicate filter) { // it is technically possible to hit the ridden entity when the distance is 0, we don't want that if (VRState.VR_RUNNING) { - return entity -> filter.test(entity) && entity != Minecraft.getInstance().getCameraEntity().getVehicle(); + return filter.and(entity -> entity != Minecraft.getInstance().getCameraEntity().getVehicle()); } else { return filter; } @@ -520,9 +516,13 @@ public abstract class GameRendererVRMixin @Override @Unique public void vivecraft$setupRVE() { + this.vivecraft$setupRVEAtDevice( + vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render.getEye(vivecraft$DATA_HOLDER.currentPass)); + } + + @Unique + private void vivecraft$setupRVEAtDevice(VRData.VRDevicePose eyePose) { if (this.vivecraft$cached) { - VRData.VRDevicePose eyePose = vivecraft$DATA_HOLDER.vrPlayer.vrdata_world_render - .getEye(vivecraft$DATA_HOLDER.currentPass); Vec3 eye = eyePose.getPosition(); Entity entity = this.minecraft.getCameraEntity(); entity.setPosRaw(eye.x, eye.y, eye.z); @@ -535,6 +535,7 @@ public abstract class GameRendererVRMixin entity.setXRot(-eyePose.getPitch()); entity.xRotO = entity.getXRot(); entity.setYRot(eyePose.getYaw()); + entity.yRotO = entity.getYRot(); if (entity instanceof LivingEntity livingEntity) { livingEntity.yHeadRot = entity.getYRot(); livingEntity.yHeadRotO = entity.getYRot(); From f5ba2416915659c2029cc29169974d51c3c1b97e Mon Sep 17 00:00:00 2001 From: fayer3 Date: Sun, 12 Jan 2025 22:14:54 +0100 Subject: [PATCH 14/14] bump to 1.2.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index febe1685b..751cef66a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.21.4 enabled_platforms=fabric,forge,neoforge archives_base_name=vivecraft -mod_version=1.2.1 +mod_version=1.2.2 maven_group=org.vivecraft lwjgl_version=3.3.3