From a98752f4efd34f9a454223cbffd33d384ba034a3 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 20 Aug 2023 22:54:43 -0400 Subject: [PATCH 01/33] Initial API --- .../java/org/vivecraft/api/VivecraftAPI.java | 35 +++ .../org/vivecraft/api/client/Tracker.java | 75 +++++++ .../api/client/VivecraftClientAPI.java | 212 ++++++++++++++++++ .../api/client/data/VRPoseHistory.java | 95 ++++++++ .../java/org/vivecraft/api/data/VRData.java | 63 ++++++ .../java/org/vivecraft/api/data/VRPose.java | 42 ++++ .../org/vivecraft/api_beta/VivecraftAPI.java | 16 -- .../api_beta/client/VivecraftClientAPI.java | 18 -- .../org/vivecraft/client/ClientAPIImpl.java | 27 --- .../org/vivecraft/client/ClientVRPlayers.java | 16 ++ .../client/api_impl/ClientAPIImpl.java | 180 +++++++++++++++ .../api_impl/data/VRPoseHistoryImpl.java | 104 +++++++++ .../client_vr/ClientDataHolderVR.java | 29 +++ .../java/org/vivecraft/client_vr/VRData.java | 27 +++ .../java/org/vivecraft/client_vr/VRState.java | 7 +- .../client_vr/gameplay/VRPlayer.java | 41 ++-- .../gameplay/trackers/BackpackTracker.java | 18 +- .../gameplay/trackers/BowTracker.java | 25 ++- .../gameplay/trackers/CameraTracker.java | 26 ++- .../gameplay/trackers/ClimbTracker.java | 38 +++- .../gameplay/trackers/CrawlTracker.java | 18 +- .../gameplay/trackers/EatingTracker.java | 19 +- .../gameplay/trackers/HorseTracker.java | 21 +- .../gameplay/trackers/InteractTracker.java | 27 ++- .../gameplay/trackers/JumpTracker.java | 24 +- .../gameplay/trackers/RowTracker.java | 38 ++-- .../gameplay/trackers/RunTracker.java | 18 +- .../gameplay/trackers/SneakTracker.java | 18 +- .../gameplay/trackers/SwimTracker.java | 16 +- .../gameplay/trackers/SwingTracker.java | 32 ++- .../gameplay/trackers/TeleportTracker.java | 13 +- .../gameplay/trackers/TelescopeTracker.java | 15 +- .../client_vr/gameplay/trackers/Tracker.java | 38 ---- .../gameplay/trackers/VehicleTracker.java | 21 +- .../java/org/vivecraft/common/APIImpl.java | 23 -- .../vivecraft/common/api_impl/APIImpl.java | 40 ++++ .../common/api_impl/data/VRDataImpl.java | 49 ++++ .../common/api_impl/data/VRPoseImpl.java | 55 +++++ .../mixin/client_vr/MinecraftVRMixin.java | 2 +- .../vivecraft/server/ServerVivePlayer.java | 49 ++++ 40 files changed, 1381 insertions(+), 249 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/api/VivecraftAPI.java create mode 100644 common/src/main/java/org/vivecraft/api/client/Tracker.java create mode 100644 common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java create mode 100644 common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java create mode 100644 common/src/main/java/org/vivecraft/api/data/VRData.java create mode 100644 common/src/main/java/org/vivecraft/api/data/VRPose.java delete mode 100644 common/src/main/java/org/vivecraft/api_beta/VivecraftAPI.java delete mode 100644 common/src/main/java/org/vivecraft/api_beta/client/VivecraftClientAPI.java delete mode 100644 common/src/main/java/org/vivecraft/client/ClientAPIImpl.java create mode 100644 common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java create mode 100644 common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java delete mode 100644 common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/Tracker.java delete mode 100644 common/src/main/java/org/vivecraft/common/APIImpl.java create mode 100644 common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java create mode 100644 common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java create mode 100644 common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java diff --git a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java new file mode 100644 index 000000000..7a24f6140 --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java @@ -0,0 +1,35 @@ +package org.vivecraft.api; + +import net.minecraft.world.entity.player.Player; +import org.vivecraft.api.data.VRData; +import org.vivecraft.common.api_impl.APIImpl; + +import javax.annotation.Nullable; + +public interface VivecraftAPI { + + /** + * @return The Vivecraft API instance for interacting with Vivecraft's API. + */ + static VivecraftAPI getInstance() { + return APIImpl.INSTANCE; + } + + /** + * Check whether a given player is currently in VR. + * + * @param player The player to check the VR status of. + * @return true if the player is in VR. + */ + boolean isVRPlayer(Player player); + + /** + * Returns the VR data for the given player. Will return null if the player isn't in VR, + * or if being called from the client, and the client has yet to receive any data for the player. + * + * @param player Player to get the VR data of. + * @return The VR data for a player, or null if the player isn't in VR or no data has been received for said player. + */ + @Nullable + VRData getVRData(Player player); +} diff --git a/common/src/main/java/org/vivecraft/api/client/Tracker.java b/common/src/main/java/org/vivecraft/api/client/Tracker.java new file mode 100644 index 000000000..eb54d2efe --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/client/Tracker.java @@ -0,0 +1,75 @@ +package org.vivecraft.api.client; + +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.player.Player; + +/** + * A tracker is an object that is run for the local player during the game tick or before rendering a frame only if + * they are in VR. Using trackers are one of the cleanest ways to interact with Vivecraft's data; it's how Vivecraft + * itself does. Trackers should generally use {@link VivecraftClientAPI#getPreTickWorldData()}, as this provides + * the most up-to-date data, and other methods such as {@link VivecraftClientAPI#getPostTickWorldData()} or + * {@link org.vivecraft.api.VivecraftAPI#getVRData(Player)} may not have data available when the tracker is run. + */ +public interface Tracker { + + /** + * Whether the tracker is active for the local player. + * + * @param player Player being checked if they are active for this tracker instances. + * @return true if the tracker is active for the specified player. + */ + boolean isActive(LocalPlayer player); + + /** + * Called for the client player if this tracker is active, which is when {@link #isActive(LocalPlayer)} returns true. + * + * @param player Player to run this tracker for, which is the local player. + */ + void doProcess(LocalPlayer player); + + /** + * The ticking type for this tracker. + * If this is PER_FRAME, the tracker is called once with the local player per frame before the frame is rendered. + * If this is PER_TICK, the tracker is called once with the local player per game tick during the tick. + * + * @return The ticking type this tracker should use. + */ + TrackerTickType tickType(); + + /** + * Called for the client player if this tracker is currently causing the item to be used to not release the use key. + * In other words, if you want the item currently being held to act as the use key being held, one should call + * the use item function, then return true from this method while the item should still remain used. + * @param player The local player which is running this tracker. + * @return Whether the item should remain in use. + */ + default boolean itemInUse(LocalPlayer player) { + return false; + } + + /** + * Called to reset data for the local player. This is called whenever {@link #isActive(LocalPlayer)} returns false. + * + * @param player The local player, which will have their data reset. + */ + default void reset(LocalPlayer player) { + + } + + /** + * Called for all players, whether the tracker is active or not for them. This runs before + * {@link #isActive(LocalPlayer)} or {@link #reset(LocalPlayer)}. + * + * @param player Player to do an idle tick for, which is the local player. + */ + default void idleTick(LocalPlayer player) { + + } + + /** + * The timing type used for ticking trackers. + */ + enum TrackerTickType { + PER_FRAME, PER_TICK + } +} diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java new file mode 100644 index 000000000..9958d2021 --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -0,0 +1,212 @@ +package org.vivecraft.api.client; + +import com.google.common.annotations.Beta; +import net.minecraft.world.InteractionHand; +import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.data.VRData; +import org.vivecraft.client.api_impl.ClientAPIImpl; +import org.vivecraft.client_vr.render.RenderPass; + +import javax.annotation.Nullable; + +public interface VivecraftClientAPI { + + static VivecraftClientAPI getInstance() { + return ClientAPIImpl.INSTANCE; + } + + /** + * Registers the tracker to the list of all trackers to be run for the local player. See the documentation for + * {@link Tracker} for more information on what a tracker is. + * + * @param tracker Tracker to register. + */ + void registerTracker(Tracker tracker); + + /** + * Gets data representing the devices as they exist in the room before the game tick. + * Note that this data is gathered BEFORE mod loaders' pre-tick events. + * + * @return Data representing the devices in the room pre-tick, or null if the local player isn't in VR. + */ + @Nullable + VRData getPreTickRoomData(); + + /** + * Gets data representing the devices as they exist in the room after the game tick. + * Note that this data is gathered AFTER mod loaders' post-tick events. + * + * @return Data representing the devices in the room post-tick, or null if the local player isn't in VR. + */ + @Nullable + VRData getPostTickRoomData(); + + /** + * Gets data representing the devices as they exist in Minecraft coordinates before the game tick. + * This is the same as {@link #getPreTickRoomData()} with translation to Minecraft's coordinates as of the last + * tick, and is the main data source used by Vivecraft. If you're unsure which {@link VRData} method to use, you + * likely want to use this one. + * Note that this data is gathered BEFORE mod loaders' pre-tick events. + * + * @return Data representing the devices in Minecraft space pre-tick, or null if the local player isn't in VR. + */ + @Nullable + VRData getPreTickWorldData(); + + /** + * Gets data representing the devices as they exist in Minecraft coordinates after the game tick. + * This is the data sent to the server, and also used to calculate the data in {@link #getWorldRenderData()}. + * Note that this data is gathered AFTER mod loaders' post-tick events. + * + * @return Data representing the devices in Minecraft space post-tick, or null if the local player isn't in VR. + */ + @Nullable + VRData getPostTickWorldData(); + + /** + * Gets data representing the devices as they exist in Minecraft coordinates after the game tick interpolated for + * rendering. + * This is the same data as {@link #getPostTickWorldData()}, however it is interpolated for rendering. + * + * @return Data representing the devices in Minecraft space post-tick interpolated for rendering, or null if the + * local player isn't in VR. + */ + @Nullable + VRData getWorldRenderData(); + + /** + * Causes a haptic pulse (vibration/rumble) for the specified controller. + * This function silently fails if called for players not in VR or players who are in seated mode. + * + * @param controllerNum The controller number to trigger a haptic pulse. 0 is the primary controller, while 1 is + * the secondary controller. + * @param duration The duration of the haptic pulse in seconds. Note that this number is passed to the + * underlying VR API used by Vivecraft, and may act with a shorter length than expected beyond + * very short pulses. + * @param frequency The frequency of the haptic pulse in Hz. 160 is a safe bet for this number, with Vivecraft's codebase + * using anywhere from 160F for actions such as a bite on a fishing line, to 1000F for things such + * as a chat notification. + * @param amplitude The amplitude of the haptic pulse. This should be kept between 0F and 1F. + * @param delay An amount of time to delay until creating the haptic pulse. The majority of the time, one should use 0F here. + */ + void triggerHapticPulse(int controllerNum, float duration, float frequency, float amplitude, float delay); + + /** + * Causes a haptic pulse (vibration/rumble) for the specified controller. + * This function silently fails if called for players not in VR or players who are in seated mode. + * + * @param controllerNum The controller number to trigger a haptic pulse. 0 is the primary controller, while 1 is + * the secondary controller. + * @param duration The duration of the haptic pulse in seconds. Note that this number is passed to the + * underlying VR API used by Vivecraft, and may act with a shorter length than expected beyond + * very short pulses. + */ + default void triggerHapticPulse(int controllerNum, float duration) { + triggerHapticPulse(controllerNum, duration, 160F, 1F, 0F); + } + + /** + * @return Whether the client player is currently in seated mode. + */ + boolean isSeated(); + + /** + * @return Whether the client player is using reversed hands. + */ + boolean usingReversedHands(); + + /** + * @return Whether VR support is initialized. + */ + boolean isVrInitialized(); + + /** + * @return Whether the client is actively in VR. + */ + boolean isVrActive(); + + /** + * @return The currently active world scale. + */ + float getWorldScale(); + + /** + * Returns the history of VR poses for the player for the HMD. Will return null if the player isn't + * in VR. + * + * @return The historical VR data for the player's HMD, or null if the player isn't in VR. + */ + @Nullable + VRPoseHistory getHistoricalVRHMDPoses(); + + /** + * Returns the history of VR poses for the player for a controller. Will return null if the player isn't + * in VR. + * + * @param controller The controller number to get, with 0 being the primary controller. + * @return The historical VR data for the player's controller, or null if the player isn't in VR. + */ + @Nullable + VRPoseHistory getHistoricalVRControllerPoses(int controller); + + /** + * Returns the history of VR poses for the player for a controller. Will return null if the player isn't + * in VR. + * + * @param hand The hand to get controller history for. + * @return The historical VR data for the player's controller, or null if the player isn't in VR. + */ + @Nullable + default VRPoseHistory getHistoricalVRControllerPoses(InteractionHand hand) { + return getHistoricalVRControllerPoses(hand.ordinal()); + } + + /** + * Returns the history of VR poses for the player for the primary controller. Will return null if the + * player isn't in VR. + * + * @return The historical VR data for the player's primary controller, or null if the player isn't in VR. + */ + @Nullable + default VRPoseHistory getHistoricalVRController0Poses() { + return getHistoricalVRControllerPoses(0); + } + + /** + * Returns the history of VR poses for the player for the secondary controller. Will return null if the + * player isn't in VR. + * + * @return The historical VR data for the player's secondary controller, or null if the player isn't in VR. + */ + @Nullable + default VRPoseHistory getHistoricalVRController1Poses() { + return getHistoricalVRControllerPoses(1); + } + + /** + * Opens or closes Vivecraft's keyboard. Will fail silently if the user isn't in VR or if the keyboard's new state + * is the same as the old. + * + * @param isNowOpen Whether the keyboard should now be open. If false, the keyboard will attempt to close. + * @return Whether the keyboard is currently showing after attempting to open/close it. + */ + boolean setKeyboardState(boolean isNowOpen); + + /** + * @return Whether the current render pass is a vanilla render pass. + */ + @Beta + boolean isVanillaRenderPass(); + + /** + * @return The current render pass Vivecraft is performing. + */ + @Beta + RenderPass getCurrentRenderPass(); + + /** + * @return Whether the current render pass is the first one it performed for this render cycle. + */ + @Beta + boolean isFirstRenderPass(); +} diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java new file mode 100644 index 000000000..b0a50549c --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -0,0 +1,95 @@ +package org.vivecraft.api.client.data; + +import net.minecraft.world.phys.Vec3; +import org.vivecraft.api.data.VRPose; + +import java.util.List; + +/** + * Represents historical VRData associated with a player. + */ +public interface VRPoseHistory { + + /** + * The maximum amount of ticks back data is held for. + * It is only guaranteed that historical data does not go beyond this number of ticks back. Functions do not + * guarantee that they will reference this many ticks, as, for example, this amount of ticks may not have gone + * by for the player this history represents. + * Passing a value larger than this number to any methods below in their maxTicksBack or ticksBack parameters + * will throw an {@link IllegalArgumentException}. + */ + int MAX_TICKS_BACK = 20; + + /** + * @return The amount of ticks worth of history being held. The number returned by this methodwill never be higher + * than {@link VRPoseHistory#MAX_TICKS_BACK}, however can be lower than it. + */ + int ticksOfHistory(); + + /** + * Gets a raw list of {@link VRPose} instances, with index 0 representing the least recent pose known. + * + * @return The aforementioned list of {@link VRPose} instances. + */ + List getAllHistoricalData() throws IllegalArgumentException; + + /** + * Gets the historical data ticksBack ticks back. This will throw an IllegalStateException if the data cannot + * be retrieved due to not having enough history. + * + * @param ticksBack Ticks back to retrieve data. + * @return A {@link VRPose} instance from index ticks ago. + * @throws IllegalStateException If ticksBack references a tick that there is not yet data for. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + */ + VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; + + /** + * Gets the net movement between the most recent data in this instance and the oldest position that can be + * retrieved, going no farther back than maxTicksBack. + * + * @param maxTicksBack The maximum amount of ticks back to compare the most recent data with. + * @return The aforementioned net movement. Note that this will return zero change on all axes if only zero ticks + * can be looked back. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + */ + Vec3 netMovement(int maxTicksBack) throws IllegalArgumentException; + + /** + * Gets the average velocity in blocks/tick between the most recent data in this instance and the oldest position + * that can be retrieved, going no farther back than maxTicksBack. + * + * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. + * @return The aforementioned average velocity on each axis. Note that this will return zero velocity on all axes + * if only zero ticks can be looked back. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + */ + Vec3 averageVelocity(int maxTicksBack) throws IllegalArgumentException; + + /** + * Gets the average speed in blocks/tick between the most recent data in this instance and the oldest position + * that can be retrieved, going no farther back than maxTicksBack. + * + * @param maxTicksBack The maximum amount of ticks back to calculate speed with. + * @return The aforementioned average speed on each axis. Note that this will return zero speed if only zero ticks + * can be looked back. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + */ + default double averageSpeed(int maxTicksBack) throws IllegalArgumentException { + Vec3 averageVelocity = averageVelocity(maxTicksBack); + return Math.sqrt(averageVelocity.x() * averageVelocity.x() + + averageVelocity.y() * averageVelocity.y() + + averageVelocity.z() * averageVelocity.z()); + } + + /** + * Gets the average position between the most recent data in this instance and the oldest position that can be + * retrieved, going no farther back than maxTicksBack. + * + * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. + * @return The aforementioned average position. Note that this will return the current position if only zero ticks + * can be looked back. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + */ + Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException; +} diff --git a/common/src/main/java/org/vivecraft/api/data/VRData.java b/common/src/main/java/org/vivecraft/api/data/VRData.java new file mode 100644 index 000000000..124eabb8e --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/data/VRData.java @@ -0,0 +1,63 @@ +package org.vivecraft.api.data; + +import com.google.common.annotations.Beta; +import net.minecraft.world.InteractionHand; + +/** + * Represents all VR data associated with a given player, mainly the pose of the HMD and both controllers + * of the player. If the player is in seated mode, controller 1 carries the HMD's data, and controller 0 is + * based on the direction being looked at via the mouse pointer. + */ +public interface VRData { + + /** + * @return Pose data for the HMD. + */ + VRPose getHMD(); + + /** + * Gets the pose data for a given controller. + * + * @param controller The controller number to get, with 0 being the primary controller. + * @return The specified controller's pose data. + */ + VRPose getController(int controller); + + /** + * @return Whether the player is currently in seated mode. + */ + boolean isSeated(); + + /** + * @return Whether the player is using reversed hands. + */ + boolean usingReversedHands(); + + /** + * Gets the pose for a given controller. + * + * @param hand The interaction hand to get controller data for. + * @return The specified controller's pose data. + */ + default VRPose getController(InteractionHand hand) { + return getController(hand.ordinal()); + } + + /** + * Gets the pose for the primary controller. + * + * @return The main controller's pose data. + */ + default VRPose getController0() { + return getController(0); + } + + /** + * Gets the pose for the secondary controller. + * + * @return The main controller's pose data. + */ + default VRPose getController1() { + return getController(1); + } +} diff --git a/common/src/main/java/org/vivecraft/api/data/VRPose.java b/common/src/main/java/org/vivecraft/api/data/VRPose.java new file mode 100644 index 000000000..176827aaa --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/data/VRPose.java @@ -0,0 +1,42 @@ +package org.vivecraft.api.data; + +import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionf; +import org.joml.Quaternionfc; + +/** + * Represents the pose data, such as position and rotation, for a given trackable object, such as the HMD or + * a controller. + */ +public interface VRPose { + + /** + * @return The position of the device in Minecraft world coordinates. + */ + Vec3 getPos(); + + /** + * @return The rotation of the device. + */ + Vec3 getRot(); + + /** + * @return The pitch of the device in radians. + */ + double getPitch(); + + /** + * @return The yaw of the device in radians. + */ + double getYaw(); + + /** + * @return The roll of the device in radians. + */ + double getRoll(); + + /** + * @return The quaternion representing the rotation of the device. + */ + Quaternionfc getQuaternion(); +} diff --git a/common/src/main/java/org/vivecraft/api_beta/VivecraftAPI.java b/common/src/main/java/org/vivecraft/api_beta/VivecraftAPI.java deleted file mode 100644 index a95a3b0b8..000000000 --- a/common/src/main/java/org/vivecraft/api_beta/VivecraftAPI.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.vivecraft.api_beta; - -import com.google.common.annotations.Beta; -import net.minecraft.world.entity.player.Player; -import org.vivecraft.common.APIImpl; - -@Beta -public interface VivecraftAPI { - - static VivecraftAPI getInstance() { - return APIImpl.INSTANCE; - } - - @Beta - boolean isVRPlayer(Player player); -} diff --git a/common/src/main/java/org/vivecraft/api_beta/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api_beta/client/VivecraftClientAPI.java deleted file mode 100644 index ff629beb4..000000000 --- a/common/src/main/java/org/vivecraft/api_beta/client/VivecraftClientAPI.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.vivecraft.api_beta.client; - -import com.google.common.annotations.Beta; -import org.vivecraft.client.ClientAPIImpl; - -public interface VivecraftClientAPI { - - static VivecraftClientAPI getInstance() { - return ClientAPIImpl.INSTANCE; - } - - boolean isVrInitialized(); - - boolean isVrActive(); - - @Beta - boolean isVanillaRenderPass(); -} diff --git a/common/src/main/java/org/vivecraft/client/ClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/ClientAPIImpl.java deleted file mode 100644 index 27fdbd721..000000000 --- a/common/src/main/java/org/vivecraft/client/ClientAPIImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vivecraft.client; - -import org.vivecraft.api_beta.client.VivecraftClientAPI; -import org.vivecraft.client_vr.VRState; -import org.vivecraft.client_xr.render_pass.RenderPassType; - -public final class ClientAPIImpl implements VivecraftClientAPI { - - public static final ClientAPIImpl INSTANCE = new ClientAPIImpl(); - - private ClientAPIImpl() {} - - @Override - public boolean isVrInitialized() { - return VRState.VR_INITIALIZED; - } - - @Override - public boolean isVrActive() { - return VRState.VR_RUNNING; - } - - @Override - public boolean isVanillaRenderPass() { - return RenderPassType.isVanilla(); - } -} diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index 7843215de..bb83bb7b6 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -25,6 +25,8 @@ import org.vivecraft.client_vr.settings.AutoCalibration; import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassType; +import org.vivecraft.common.api_impl.data.VRDataImpl; +import org.vivecraft.common.api_impl.data.VRPoseImpl; import org.vivecraft.common.network.FBTMode; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.common.utils.MathUtils; @@ -567,5 +569,19 @@ public float getBodyYawRad() { } return (float) Math.atan2(-dir.x, dir.z); } + + public org.vivecraft.api.data.VRData asVRData() { + return new VRDataImpl( + new VRPoseImpl(fromVector3fc(this.headPos), fromVector3fc(this.headRot), this.headQuat), + new VRPoseImpl(fromVector3fc(this.mainHandPos), fromVector3fc(this.mainHandRot), this.mainHandQuat), + new VRPoseImpl(fromVector3fc(this.offHandPos), fromVector3fc(this.offHandPos), this.offHandQuat), + this.seated, + this.leftHanded + ); + } + } + + private static Vec3 fromVector3fc(Vector3fc vec) { + return new Vec3(vec.x(), vec.y(), vec.z()); } } diff --git a/common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java new file mode 100644 index 000000000..98618a0a1 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java @@ -0,0 +1,180 @@ +package org.vivecraft.client.api_impl; + +import org.jetbrains.annotations.Nullable; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.client.VivecraftClientAPI; +import org.vivecraft.api.data.VRData; +import org.vivecraft.client.api_impl.data.VRPoseHistoryImpl; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; +import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; +import org.vivecraft.client_vr.provider.ControllerType; +import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.client_xr.render_pass.RenderPassType; + +public final class ClientAPIImpl implements VivecraftClientAPI { + + public static final ClientAPIImpl INSTANCE = new ClientAPIImpl(); + + private final VRPoseHistoryImpl hmdHistory = new VRPoseHistoryImpl(); + private VRPoseHistoryImpl c0History = new VRPoseHistoryImpl(); + private VRPoseHistoryImpl c1History = new VRPoseHistoryImpl(); + + private ClientAPIImpl() { + } + + public void clearHistories() { + this.hmdHistory.clear(); + this.c0History.clear(); + this.c1History.clear(); + } + + public void addPosesToHistory(VRData data) { + this.hmdHistory.addPose(data.getHMD()); + this.c0History.addPose(data.getController0()); + this.c1History.addPose(data.getController1()); + } + + @Nullable + @Override + public VRData getPreTickRoomData() { + if (!isVrActive()) { + return null; + } + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_pre.asVRData(); + } + + @Nullable + @Override + public VRData getPostTickRoomData() { + if (!isVrActive()) { + return null; + } + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_post.asVRData(); + } + + @Nullable + @Override + public VRData getPreTickWorldData() { + if (!isVrActive()) { + return null; + } + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_pre.asVRData(); + } + + @Nullable + @Override + public VRData getPostTickWorldData() { + if (!isVrActive()) { + return null; + } + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_post.asVRData(); + } + + @Nullable + @Override + public VRData getWorldRenderData() { + if (!isVrActive()) { + return null; + } + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_render.asVRData(); + } + + @Override + public void triggerHapticPulse(int controllerNum, float duration, float frequency, float amplitude, float delay) { + if (controllerNum != 0 && controllerNum != 1) { + throw new IllegalArgumentException("Can only trigger a haptic pulse for controllers 0 and 1."); + } + if (amplitude < 0F || amplitude > 1F) { + throw new IllegalArgumentException("The amplitude of a haptic pulse must be between 0 and 1."); + } + if (isVrActive() && !isSeated()) { + ClientDataHolderVR.getInstance().vr.triggerHapticPulse( + ControllerType.values()[controllerNum], + duration, + frequency, + amplitude, + delay + ); + } + } + + @Override + public boolean isSeated() { + return ClientDataHolderVR.getInstance().vrSettings.seated; + } + + @Override + public boolean usingReversedHands() { + return ClientDataHolderVR.getInstance().vrSettings.reverseHands; + } + + @Override + public boolean isVrInitialized() { + return VRState.VR_INITIALIZED; + } + + @Override + public boolean isVrActive() { + return VRState.VR_RUNNING; + } + + @Override + public float getWorldScale() { + if (isVrActive()) { + return ClientDataHolderVR.getInstance().vrPlayer.worldScale; + } else { + return 1f; + } + } + + @Override + public void registerTracker(Tracker tracker) { + ClientDataHolderVR.getInstance().registerTracker(tracker); + } + + @Nullable + @Override + public VRPoseHistory getHistoricalVRHMDPoses() { + if (!isVrActive()) { + return null; + } + return this.hmdHistory; + } + + @Nullable + @Override + public VRPoseHistory getHistoricalVRControllerPoses(int controller) { + if (controller != 0 && controller != 1) { + throw new IllegalArgumentException("Historical VR controller data only available for controllers 0 and 1."); + } else if (!isVrActive()) { + return null; + } + return controller == 0 ? this.c0History : this.c1History; + } + + @Override + public boolean setKeyboardState(boolean isNowOpen) { + if (isVrActive()) { + return KeyboardHandler.setOverlayShowing(isNowOpen); + } + return false; + } + + @Override + public boolean isVanillaRenderPass() { + return RenderPassType.isVanilla(); + } + + @Override + public RenderPass getCurrentRenderPass() { + return ClientDataHolderVR.getInstance().currentPass; + } + + @Override + public boolean isFirstRenderPass() { + return ClientDataHolderVR.getInstance().isFirstPass; + } +} diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java new file mode 100644 index 000000000..3058a06cd --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java @@ -0,0 +1,104 @@ +package org.vivecraft.client.api_impl.data; + +import net.minecraft.world.phys.Vec3; +import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.data.VRPose; + +import java.util.*; + +public class VRPoseHistoryImpl implements VRPoseHistory { + + private final LinkedList dataQueue = new LinkedList<>(); + + public VRPoseHistoryImpl() { + } + + public void addPose(VRPose pose) { + this.dataQueue.addFirst(pose); + if (this.dataQueue.size() > VRPoseHistory.MAX_TICKS_BACK) { + this.dataQueue.removeLast(); + } + } + + public void clear() { + this.dataQueue.clear(); + } + + @Override + public int ticksOfHistory() { + return this.dataQueue.size(); + } + + @Override + public List getAllHistoricalData() { + return new ArrayList<>(this.dataQueue); + } + + @Override + public VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException { + checkTicksBack(ticksBack); + if (this.dataQueue.size() <= ticksBack) { + throw new IllegalStateException("Cannot retrieve data from " + ticksBack + " ticks ago, when there is " + + "only data for up to " + (this.dataQueue.size() - 1) + " ticks ago."); + } + return this.dataQueue.get(ticksBack); + } + + @Override + public Vec3 netMovement(int maxTicksBack) throws IllegalArgumentException { + checkTicksBack(maxTicksBack); + Vec3 current = this.dataQueue.getLast().getPos(); + Vec3 old = getOldPose(maxTicksBack).getPos(); + return current.subtract(old); + } + + @Override + public Vec3 averageVelocity(int maxTicksBack) throws IllegalArgumentException { + checkTicksBack(maxTicksBack); + Vec3 current = this.dataQueue.getLast().getPos(); + Vec3 old = getOldPose(maxTicksBack).getPos(); + return current.subtract(old).scale(1d / getNumTicksBack(maxTicksBack)); + } + + @Override + public Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException { + checkTicksBack(maxTicksBack); + int iters = getNumTicksBack(maxTicksBack); + ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); + Vec3 avg = this.dataQueue.getLast().getPos(); + int i = iters; + while (i > 0) { + avg = avg.add(iterator.previous().getPos()); + i--; + } + return avg.scale(1d / (iters + 1)); + } + + private void checkTicksBack(int ticksBack) { + if (ticksBack < 0 || ticksBack > VRPoseHistory.MAX_TICKS_BACK) { + throw new IllegalArgumentException("Value must be between 0 and " + VRPoseHistory.MAX_TICKS_BACK + "."); + } + } + + private VRPose getOldPose(int maxTicksBack) { + if (this.dataQueue.size() <= maxTicksBack) { + return this.dataQueue.getFirst(); + } else { + return this.dataQueue.get(this.dataQueue.size() - maxTicksBack - 1); + } + } + + /** + * Converts maxTicksBack to the actual maximum number of ticks we can go back. + * + * @param maxTicksBack The maximum number of ticks to attempt to go back. + * @return The actual number of ticks to go back by. + */ + private int getNumTicksBack(int maxTicksBack) { + if (this.dataQueue.size() <= maxTicksBack) { + return this.dataQueue.size() - 1; + } else { + return maxTicksBack; + } + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java index 6bf9e57c7..b198ee192 100644 --- a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java @@ -1,8 +1,10 @@ package org.vivecraft.client_vr; import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.world.entity.HumanoidArm; +import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.gameplay.VRPlayer; import org.vivecraft.client_vr.gameplay.trackers.*; import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; @@ -86,6 +88,25 @@ public class ClientDataHolderVR { public boolean showedStencilMessage; public boolean showedFbtCalibrationNotification; + private ClientDataHolderVR() { + registerTracker(backpackTracker); + registerTracker(bowTracker); + registerTracker(swingTracker); + registerTracker(eatingTracker); + registerTracker(jumpTracker); + registerTracker(sneakTracker); + registerTracker(climbTracker); + registerTracker(runTracker); + registerTracker(rowTracker); + registerTracker(teleportTracker); + registerTracker(horseTracker); + registerTracker(vehicleTracker); + registerTracker(interactTracker); + registerTracker(crawlTracker); + registerTracker(cameraTracker); + registerTracker(telescopeTracker); + } + public static ClientDataHolderVR getInstance() { if (INSTANCE == null) { INSTANCE = new ClientDataHolderVR(); @@ -139,4 +160,12 @@ public void registerTracker(Tracker tracker) throws IllegalArgumentException { public List getTrackers() { return Collections.unmodifiableList(this.trackers); } + + /** + * @param player Current local player. + * @return Whether some tracker is currently using an item. + */ + public boolean isTrackerUsingItem(LocalPlayer player) { + return ClientDataHolderVR.getInstance().getTrackers().stream().anyMatch(tracker -> tracker.itemInUse(player)); + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/VRData.java b/common/src/main/java/org/vivecraft/client_vr/VRData.java index 12135538d..2a7950d24 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRData.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRData.java @@ -14,6 +14,10 @@ import javax.annotation.Nullable; import java.lang.Math; +import org.joml.Quaternionf; +import org.vivecraft.api.data.VRPose; +import org.vivecraft.common.api_impl.data.VRDataImpl; +import org.vivecraft.common.api_impl.data.VRPoseImpl; public class VRData { // headset center @@ -358,6 +362,19 @@ public VRDevicePose getEye(RenderPass pass) { }; } + /** + * @return this data in a manner better-suited for the API + */ + public org.vivecraft.api.data.VRData asVRData() { + return new VRDataImpl( + this.hmd.asVRPose(), + this.c0.asVRPose(), + this.c1.asVRPose(), + ClientDataHolderVR.getInstance().vrSettings.seated, + ClientDataHolderVR.getInstance().vrSettings.reverseHands + ); + } + @Override public String toString() { return """ @@ -502,6 +519,16 @@ public Matrix4f getMatrix() { return new Matrix4f().rotationY(VRData.this.rotation_radians).mul(this.matrix); } + public VRPose asVRPose() { + Quaternionf quat = new Quaternionf(); + quat.setFromUnnormalized(getMatrix()); + return new VRPoseImpl( + getPosition(), + new Vec3(getDirection()), + quat + ); + } + @Override public String toString() { return "Device: pos:" + this.getPosition() + ", dir: " + this.getDirection(); diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index c5fa9212a..3480737f8 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -3,12 +3,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import org.apache.commons.lang3.StringUtils; +import org.vivecraft.api.client.Tracker; import org.vivecraft.client.Xplat; import org.vivecraft.client.gui.screens.ErrorScreen; import org.vivecraft.client.gui.screens.GarbageCollectorScreen; import org.vivecraft.client.utils.TextUtils; import org.vivecraft.client_vr.gameplay.VRPlayer; -import org.vivecraft.client_vr.gameplay.trackers.Tracker; +import org.vivecraft.client.api_impl.ClientAPIImpl; import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; import org.vivecraft.client_vr.provider.nullvr.NullVR; import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; @@ -70,9 +71,6 @@ public static void initializeVR() { RenderPassManager.setVanillaRenderPass(); dh.vrPlayer = new VRPlayer(); - for (Tracker t : dh.getTrackers()) { - dh.vrPlayer.registerTracker(t); - } dh.menuWorldRenderer = new MenuWorldRenderer(); @@ -156,5 +154,6 @@ public static void destroyVR(boolean disableVRSetting) { // this reloads any PostChain, at least in vanilla Minecraft.getInstance().levelRenderer.onResourceManagerReload(Minecraft.getInstance().getResourceManager()); } + ClientAPIImpl.INSTANCE.clearHistories(); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 0df4478c2..0fe4dc3ba 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -23,11 +23,14 @@ import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; import org.joml.Vector3fc; +import org.vivecraft.api.client.Tracker; import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client.api_impl.ClientAPIImpl; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.common.VRServerPerms; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client.utils.ClientUtils; import org.vivecraft.client.utils.ScaleHelper; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.MethodHolder; import org.vivecraft.client_vr.VRData; import org.vivecraft.client_vr.extensions.GameRendererExtension; @@ -35,11 +38,9 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.GuiHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; -import org.vivecraft.client_vr.gameplay.trackers.Tracker; import org.vivecraft.client_vr.gameplay.trackers.VehicleTracker; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.common.VRServerPerms; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.ItemTags; @@ -62,8 +63,6 @@ public class VRPlayer { public VRData vrdata_world_post; // interpolate here between post and pre public VRData vrdata_world_render; - - private final ArrayList trackers = new ArrayList<>(); public float worldScale = this.dh.vrSettings.overrides.getSetting(VRSettings.VrOptions.WORLD_SCALE).getFloat(); private float rawWorldScale = this.dh.vrSettings.overrides.getSetting(VRSettings.VrOptions.WORLD_SCALE).getFloat(); private boolean teleportOverride = false; @@ -83,10 +82,6 @@ public class VRPlayer { private boolean initDone = false; public boolean onTick; - public void registerTracker(Tracker tracker) { - this.trackers.add(tracker); - } - public VRPlayer() { this.vrdata_room_pre = new VRData( Vec3.ZERO, @@ -243,6 +238,8 @@ public void preTick() { if (this.dh.vrSettings.seated && !MethodHolder.isInMenuRoom()) { this.dh.vrSettings.worldRotation = this.dh.vr.seatedRot; } + + ClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRData()); } public void postTick() { @@ -306,11 +303,11 @@ public void preRender(float partialTick) { interpolatedWorldScale, interpolatedWorldRotation_Radians); - // handle special items - for (Tracker tracker : this.trackers) { - if (tracker.getEntryPoint() == Tracker.EntryPoint.SPECIAL_ITEMS) { + for (Tracker tracker : ClientDataHolderVR.getInstance().getTrackers()) + { + if (tracker.tickType() == Tracker.TrackerTickType.PER_FRAME) + { tracker.idleTick(this.mc.player); - if (tracker.isActive(this.mc.player)) { tracker.doProcess(this.mc.player); } else { @@ -405,13 +402,13 @@ public void tick(LocalPlayer player) { } this.doPlayerMoveInRoom(player); - - for (Tracker tracker : this.trackers) { - if (tracker.getEntryPoint() == Tracker.EntryPoint.LIVING_UPDATE) { - tracker.idleTick(player); - - if (tracker.isActive(player)) { - tracker.doProcess(player); + for (Tracker tracker : dh.getTrackers()) + { + if (tracker.tickType() == Tracker.TrackerTickType.PER_TICK) + { + tracker.idleTick(mc.player); + if (tracker.isActive(mc.player)) { + tracker.doProcess(mc.player); } else { tracker.reset(player); } @@ -439,10 +436,6 @@ public void tick(LocalPlayer player) { } } - public boolean isTrackerUsingItem(LocalPlayer player) { - return this.trackers.stream().anyMatch(tracker -> tracker.itemInUse(player)); - } - public void doPlayerMoveInRoom(LocalPlayer player) { if (this.roomScaleMovementDelay > 0) { diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BackpackTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BackpackTracker.java index ef3abfdd7..f47f7fb42 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BackpackTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BackpackTracker.java @@ -1,5 +1,9 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.gameplay.VRPlayer; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -7,16 +11,17 @@ import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.gameplay.VRPlayer; import org.vivecraft.common.utils.MathUtils; -public class BackpackTracker extends Tracker { +public class BackpackTracker implements Tracker { public boolean[] wasIn = new boolean[2]; public int previousSlot = 0; + protected Minecraft mc; + protected ClientDataHolderVR dh; public BackpackTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -98,4 +103,9 @@ public void doProcess(LocalPlayer player) { } } } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java index 82479e71d..e07c85469 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java @@ -1,5 +1,12 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.extensions.PlayerExtension; +import org.vivecraft.client.network.ClientNetworking; +import org.vivecraft.client_vr.VRData; +import org.vivecraft.client_vr.settings.VRSettings; + import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -24,7 +31,7 @@ import org.vivecraft.common.network.packet.c2s.DrawPayloadC2S; import org.vivecraft.common.utils.MathUtils; -public class BowTracker extends Tracker { +public class BowTracker implements Tracker { private static final long MAX_DRAW_MILLIS = 1100L; private static final double NOTCH_DOT_THRESHOLD = 20F; @@ -43,8 +50,12 @@ public class BowTracker extends Tracker { private int hapCounter = 0; private int lastHapStep = 0; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public BowTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } public Vector3fc getAimVector() { @@ -110,11 +121,6 @@ public void reset(LocalPlayer player) { this.canDraw = false; } - @Override - public EntryPoint getEntryPoint() { - return EntryPoint.SPECIAL_ITEMS; - } - @Override public void doProcess(LocalPlayer player) { VRData vrData = this.dh.vrPlayer.getVRDataWorld(); @@ -286,4 +292,9 @@ public void doProcess(LocalPlayer player) { } } } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_FRAME; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CameraTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CameraTracker.java index 5ea91f5d5..58782d845 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CameraTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CameraTracker.java @@ -1,19 +1,21 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.joml.Matrix4f; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRData; +import org.vivecraft.client_vr.render.RenderPass; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.world.phys.Vec3; -import org.joml.Matrix4f; import org.joml.Matrix4fc; import org.joml.Quaternionf; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.VRData; -import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.common.utils.MathUtils; -public class CameraTracker extends Tracker { +public class CameraTracker implements Tracker { public static final ModelResourceLocation CAMERA_MODEL = new ModelResourceLocation("vivecraft", "camera", ""); public static final ModelResourceLocation CAMERA_DISPLAY_MODEL = new ModelResourceLocation("vivecraft", "camera_display", ""); @@ -27,9 +29,12 @@ public class CameraTracker extends Tracker { private Vec3 startPosition; private Quaternionf startRotation; private boolean quickMode; + protected Minecraft mc; + protected ClientDataHolderVR dh; public CameraTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -76,17 +81,16 @@ public void doProcess(LocalPlayer player) { } @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_FRAME; + } + public void reset(LocalPlayer player) { this.visible = false; this.quickMode = false; this.stopMoving(); } - @Override - public EntryPoint getEntryPoint() { - return EntryPoint.SPECIAL_ITEMS; // smoother camera movement - } - public boolean isVisible() { return this.visible; } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java index 87c35d345..38ff5e1bd 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/ClimbTracker.java @@ -1,11 +1,25 @@ package org.vivecraft.client_vr.gameplay.trackers; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; + +import net.minecraft.network.chat.contents.TranslatableContents; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.extensions.PlayerExtension; +import org.vivecraft.client.network.ClientNetworking; +import org.vivecraft.client_vr.gameplay.VRPlayer; +import org.vivecraft.client_vr.provider.ControllerType; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -17,23 +31,15 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; import org.joml.Vector3f; -import org.vivecraft.client.VivecraftVRMod; -import org.vivecraft.client.network.ClientNetworking; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.extensions.PlayerExtension; -import org.vivecraft.client_vr.gameplay.VRPlayer; -import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.common.network.packet.c2s.ClimbingPayloadC2S; import org.vivecraft.data.BlockTags; import org.vivecraft.server.config.ClimbeyBlockmode; import java.util.*; -public class ClimbTracker extends Tracker { +public class ClimbTracker implements Tracker { public static final ModelResourceLocation CLAWS_MODEL = new ModelResourceLocation("vivecraft", "climb_claws", - "inventory"); - - public Set blocklist = new HashSet<>(); + "inventory"); public Set blocklist = new HashSet<>(); public ClimbeyBlockmode serverBlockmode = ClimbeyBlockmode.DISABLED; public boolean forceActivate = false; public int latchStartController = -1; @@ -60,9 +66,12 @@ public class ClimbTracker extends Tracker { private final AABB fullBB = new AABB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D); private final Random rand = new Random(); private boolean unsetFlag; + protected Minecraft mc; + protected ClientDataHolderVR dh; public ClimbTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } public boolean isGrabbingLadder() { @@ -662,6 +671,11 @@ private boolean isClimbableTrapdoor(Level level, BlockPos blockPos, BlockState b return false; } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + private boolean allowed(BlockState bs) { return switch (this.serverBlockmode) { case DISABLED -> true; diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CrawlTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CrawlTracker.java index ffca80d4b..199d708dd 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CrawlTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/CrawlTracker.java @@ -1,21 +1,26 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client.network.ClientNetworking; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.Pose; -import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client.utils.ClientUtils; import org.vivecraft.client.utils.ScaleHelper; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.common.network.packet.c2s.CrawlPayloadC2S; -public class CrawlTracker extends Tracker { +public class CrawlTracker implements Tracker { private boolean wasCrawling; public boolean crawling; public boolean crawlsteresis; + protected Minecraft mc; + protected ClientDataHolderVR dh; public CrawlTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -53,6 +58,11 @@ public void doProcess(LocalPlayer player) { this.updateState(player); } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + private void updateState(LocalPlayer player) { if (this.crawling != this.wasCrawling) { if (this.crawling) { diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java index fd2f284ab..31accce51 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java @@ -1,5 +1,8 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; + import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -7,11 +10,10 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.UseAnim; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.VRData; import org.vivecraft.common.utils.MathUtils; +import org.vivecraft.client_vr.VRData; -public class EatingTracker extends Tracker { +public class EatingTracker implements Tracker { private static final float MOUTH_TO_EYE_DISTANCE = 0.0F; private static final float THRESHOLD = 0.25F; private static final long EAT_TIME = 2100L; @@ -19,8 +21,12 @@ public class EatingTracker extends Tracker { private final boolean[] eating = new boolean[2]; private long eatStart; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public EatingTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -121,4 +127,9 @@ public void doProcess(LocalPlayer player) { } } } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/HorseTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/HorseTracker.java index 7594a6cde..bea1b0416 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/HorseTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/HorseTracker.java @@ -1,17 +1,19 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.gameplay.VRPlayer; +import org.vivecraft.client_vr.settings.VRSettings; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.entity.animal.horse.Horse; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.gameplay.VRPlayer; -import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.common.utils.MathUtils; -public class HorseTracker extends Tracker { +public class HorseTracker implements Tracker { private static final double BOOST_TRIGGER = 1.4D; private static final double PULL_TRIGGER = 0.8D; private static final int MAX_SPEED_LEVEL = 3; @@ -25,8 +27,12 @@ public class HorseTracker extends Tracker { private Horse horse = null; private final ModelInfo info = new ModelInfo(); + protected Minecraft mc; + protected ClientDataHolderVR dh; + public HorseTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -123,6 +129,11 @@ public void doProcess(LocalPlayer player) { this.horse.setDeltaMovement(movement.x, this.horse.getDeltaMovement().y, movement.z); } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + private boolean doBoost() { if (this.speedLevel >= MAX_SPEED_LEVEL) { return false; diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/InteractTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/InteractTracker.java index 714de2b00..7bc691cc7 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/InteractTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/InteractTracker.java @@ -1,5 +1,19 @@ package org.vivecraft.client_vr.gameplay.trackers; +import java.util.HashSet; + +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client.Xplat; +import org.vivecraft.client_vr.extensions.PlayerExtension; +import org.vivecraft.client_vr.VRData; +import org.vivecraft.client_vr.provider.ControllerType; +import org.vivecraft.client_vr.settings.VRHotkeys; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_vr.render.VRFirstPersonArmSwing; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -35,7 +49,7 @@ import java.util.HashSet; -public class InteractTracker extends Tracker { +public class InteractTracker implements Tracker { // indicates when a hand has a bucket and is in a liquid public boolean[] bukkit = new boolean[2]; @@ -62,8 +76,12 @@ public class InteractTracker extends Tracker { // a set of blocks that can be interacted with private HashSet> rightClickable = null; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public InteractTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -274,6 +292,11 @@ private void addIfClassHasMethod(String name, Class oclass) { } } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + public boolean isInteractActive(int controller) { return this.active[controller]; } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java index c7de2baeb..b266aa296 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/JumpTracker.java @@ -1,8 +1,14 @@ package org.vivecraft.client_vr.gameplay.trackers; +import net.minecraft.network.chat.contents.TranslatableContents; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client.network.ClientNetworking; +import org.vivecraft.client_vr.settings.AutoCalibration; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Player; @@ -10,13 +16,9 @@ import net.minecraft.world.item.Items; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import org.vivecraft.client.VivecraftVRMod; -import org.vivecraft.client.network.ClientNetworking; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.settings.AutoCalibration; import org.vivecraft.client_vr.settings.VRSettings; -public class JumpTracker extends Tracker { +public class JumpTracker implements Tracker { // in room space public Vector3f[] latchStart = new Vector3f[]{new Vector3f(), new Vector3f()}; @@ -25,9 +27,12 @@ public class JumpTracker extends Tracker { public Vec3[] latchStartPlayer = new Vec3[]{Vec3.ZERO, Vec3.ZERO}; private boolean c0Latched = false; private boolean c1Latched = false; + protected Minecraft mc; + protected ClientDataHolderVR dh; public JumpTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } /** @@ -223,4 +228,9 @@ public void doProcess(LocalPlayer player) { player.jumpFromGround(); } } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java index bf42eafda..135130740 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java @@ -1,5 +1,8 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -8,10 +11,9 @@ import net.minecraft.world.phys.Vec3; import org.joml.Quaternionf; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.common.utils.MathUtils; -public class RowTracker extends Tracker { +public class RowTracker implements Tracker { private static final double TRANSMISSION_EFFICIENCY = 0.9D; public double[] forces = new double[]{0.0D, 0.0D}; @@ -21,24 +23,29 @@ public class RowTracker extends Tracker { private final Vec3[] lastUWPs = new Vec3[2]; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public RowTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } - @Override - public boolean isActive(LocalPlayer player) { + public boolean isActive(LocalPlayer p) { if (this.dh.vrSettings.seated) { return false; } else if (!this.dh.vrSettings.realisticRowEnabled) { return false; - } else if (player == null || !player.isAlive()) { - return false; - } else if (this.mc.gameMode == null) { - return false; - } else if (this.mc.options.keyUp.isDown()) { // important - return false; - } else if (!(player.getVehicle() instanceof Boat)) { - return false; + } else if (p != null && p.isAlive()) { + if (this.mc.gameMode == null) { + return false; + } else if (this.mc.options.keyUp.isDown()) { + return false; + } else if (!(p.getVehicle() instanceof Boat)) { + return false; + } else { + return !this.dh.bowTracker.isNotched(); + } } else { return !this.dh.bowTracker.isNotched(); } @@ -83,6 +90,11 @@ public void doProcess(LocalPlayer player) { // TODO: Backwards paddlin' } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + public void doProcessFinaltransmithastofixthis(LocalPlayer player) { Boat boat = (Boat) player.getVehicle(); Quaternionf boatRot = new Quaternionf().rotationYXZ( diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RunTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RunTracker.java index cae9ac70c..198bc5846 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RunTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RunTracker.java @@ -1,17 +1,22 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.settings.VRSettings; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.settings.VRSettings; -public class RunTracker extends Tracker { +public class RunTracker implements Tracker { private double direction = 0.0D; private float speed = 0.0F; + protected Minecraft mc; + protected ClientDataHolderVR dh; public RunTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -86,4 +91,9 @@ public void doProcess(LocalPlayer player) { this.speed = 1.3F; } } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SneakTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SneakTracker.java index 0822299b7..b3372f943 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SneakTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SneakTracker.java @@ -1,16 +1,21 @@ package org.vivecraft.client_vr.gameplay.trackers; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; +import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.settings.AutoCalibration; -public class SneakTracker extends Tracker { +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; + +public class SneakTracker implements Tracker { public boolean sneakOverride = false; public int sneakCounter = 0; + protected Minecraft mc; + protected ClientDataHolderVR dh; public SneakTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -44,4 +49,9 @@ public void doProcess(LocalPlayer player) { this.sneakOverride = AutoCalibration.getPlayerHeight() - this.dh.vr.hmdPivotHistory.latest().y() > this.dh.vrSettings.sneakThreshold; } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwimTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwimTracker.java index 3df513d1c..5f09e698f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwimTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwimTracker.java @@ -1,22 +1,27 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.common.utils.MathUtils; -public class SwimTracker extends Tracker { +public class SwimTracker implements Tracker { private static final float FRICTION = 0.9F; private static final float RISE_SPEED = 0.005F; private static final float SWIM_SPEED = 1.3F; private Vector3f motion = new Vector3f(); private double lastDist; + protected Minecraft mc; + protected ClientDataHolderVR dh; public SwimTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -73,4 +78,9 @@ public void doProcess(LocalPlayer player) { player.push(this.motion.x, this.motion.y, this.motion.z); this.motion = this.motion.mul(FRICTION); } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java index 6fdb213b2..2741b8fba 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java @@ -1,5 +1,15 @@ package org.vivecraft.client_vr.gameplay.trackers; +import java.util.List; + +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.block.*; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.provider.ControllerType; +import org.vivecraft.client_vr.settings.VRSettings; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -12,9 +22,7 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.*; -import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.ClipContext; -import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.phys.AABB; @@ -22,7 +30,6 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import org.vivecraft.client.VivecraftVRMod; import org.vivecraft.client.Xplat; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -38,9 +45,7 @@ import org.vivecraft.mod_compat_vr.bettercombat.BetterCombatHelper; import org.vivecraft.mod_compat_vr.epicfight.EpicFightHelper; -import java.util.List; - -public class SwingTracker extends Tracker { +public class SwingTracker implements Tracker { private static final int[] CONTROLLER_AND_FEET = new int[]{MCVR.MAIN_CONTROLLER, MCVR.OFFHAND_CONTROLLER, MCVR.RIGHT_FOOT_TRACKER, MCVR.LEFT_FOOT_TRACKER}; private static final float SPEED_THRESH = 3.0F; @@ -52,8 +57,12 @@ public class SwingTracker extends Tracker { public boolean[] canAct = new boolean[4]; public int disableSwing = 3; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public SwingTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -399,14 +408,19 @@ else if (blockstate.getBlock() instanceof NoteBlock || this.mc.getProfiler().pop(); } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + private boolean getIsHittingBlock() { return this.mc.gameMode.isDestroying(); } private void clearBlockHitDelay() { // TODO set destroyTicks to 1 to cancel multiple sound events per hit - // MCReflection.PlayerController_blockHitDelay.set(Minecraft.getInstance().gameMode, 0); - // Minecraft.getInstance().gameMode.blockBreakingCooldown = 1; + // MCReflection.PlayerController_blockHitDelay.set(this.mc.gameMode, 0); + // this.mc.gameMode.blockBreakingCooldown = 1; } /** diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TeleportTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TeleportTracker.java index 6bd8930fe..c443420ad 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TeleportTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TeleportTracker.java @@ -15,6 +15,7 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; +import org.vivecraft.api.client.Tracker; import org.vivecraft.client.VivecraftVRMod; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -27,7 +28,7 @@ import java.util.Random; -public class TeleportTracker extends Tracker { +public class TeleportTracker implements Tracker { private float teleportEnergy; private Vec3 movementTeleportDestination = Vec3.ZERO; private Direction movementTeleportDestinationSideHit; @@ -38,9 +39,12 @@ public class TeleportTracker extends Tracker { public int movementTeleportArcSteps = 0; public double lastTeleportArcDisplayOffset = 0.0D; public VRMovementStyle vrMovementStyle; + protected Minecraft mc; + protected ClientDataHolderVR dh; public TeleportTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; this.vrMovementStyle = new VRMovementStyle(); } @@ -499,4 +503,9 @@ public Vec3 getInterpolatedArcPosition(float progress) { this.movementTeleportArc[step].z + deltaZ * stepProgress); } } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java index 1d0c17080..292766730 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java @@ -8,13 +8,15 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.joml.Vector3f; +import org.vivecraft.common.utils.MathUtils; +import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRData; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.ItemTags; -public class TelescopeTracker extends Tracker { +public class TelescopeTracker implements Tracker { public static final ModelResourceLocation SCOPE_MODEL = new ModelResourceLocation("vivecraft", "spyglass_in_hand", "inventory"); private static final float LENS_DIST_MAX = 0.05F; @@ -24,8 +26,12 @@ public class TelescopeTracker extends Tracker { private final boolean[] viewing = new boolean[2]; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public TelescopeTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -64,6 +70,11 @@ public void doProcess(LocalPlayer player) { } } + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } + /** * @param itemStack ItemStack to check * @return if the given {@code itemStack} is a telescope diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/Tracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/Tracker.java deleted file mode 100644 index d081c158d..000000000 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/Tracker.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.vivecraft.client_vr.gameplay.trackers; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import org.vivecraft.client_vr.ClientDataHolderVR; - -import javax.annotation.Nullable; - -public abstract class Tracker { - public Minecraft mc; - public ClientDataHolderVR dh; - - public Tracker(Minecraft mc, ClientDataHolderVR dh) { - this.mc = mc; - this.dh = dh; - } - - public abstract boolean isActive(@Nullable LocalPlayer player); - - public abstract void doProcess(@Nullable LocalPlayer player); - - public boolean itemInUse(@Nullable LocalPlayer player) { - return false; - } - - public void reset(@Nullable LocalPlayer player) {} - - public void idleTick(@Nullable LocalPlayer player) {} - - public EntryPoint getEntryPoint() { - return EntryPoint.LIVING_UPDATE; - } - - public enum EntryPoint { - LIVING_UPDATE, - SPECIAL_ITEMS - } -} diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/VehicleTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/VehicleTracker.java index 3b8c43cfe..f9e7a6563 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/VehicleTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/VehicleTracker.java @@ -1,5 +1,10 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.Tracker; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRData; +import org.vivecraft.client_vr.settings.VRSettings; + import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.Entity; @@ -10,13 +15,10 @@ import net.minecraft.world.item.FoodOnAStickItem; import net.minecraft.world.phys.Vec3; import org.joml.Vector3f; -import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.client_vr.VRData; -import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.ItemTags; -public class VehicleTracker extends Tracker { +public class VehicleTracker implements Tracker { private float PreMount_World_Rotation; public Vec3 Premount_Pos_Room = Vec3.ZERO; public float vehicleInitialRotation = 0.0F; @@ -27,8 +29,12 @@ public class VehicleTracker extends Tracker { private int minecartStupidityCounter; private boolean isRiding = false; + protected Minecraft mc; + protected ClientDataHolderVR dh; + public VehicleTracker(Minecraft mc, ClientDataHolderVR dh) { - super(mc, dh); + this.mc = mc; + this.dh = dh; } @Override @@ -271,4 +277,9 @@ public boolean canRoomscaleDismount(LocalPlayer player) { player.isPassenger() && player.getVehicle().onGround() && this.dismountCooldown == 0; } + + @Override + public TrackerTickType tickType() { + return TrackerTickType.PER_TICK; + } } diff --git a/common/src/main/java/org/vivecraft/common/APIImpl.java b/common/src/main/java/org/vivecraft/common/APIImpl.java deleted file mode 100644 index 37a413512..000000000 --- a/common/src/main/java/org/vivecraft/common/APIImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.vivecraft.common; - -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import org.vivecraft.api_beta.VivecraftAPI; -import org.vivecraft.client.ClientVRPlayers; -import org.vivecraft.server.ServerVRPlayers; - -public final class APIImpl implements VivecraftAPI { - - public static final APIImpl INSTANCE = new APIImpl(); - - private APIImpl() {} - - @Override - public boolean isVRPlayer(Player player) { - if (player instanceof ServerPlayer serverPlayer) { - return ServerVRPlayers.isVRPlayer(serverPlayer); - } - - return ClientVRPlayers.getInstance().isVRPlayer(player); - } -} diff --git a/common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java new file mode 100644 index 000000000..4577619a7 --- /dev/null +++ b/common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java @@ -0,0 +1,40 @@ +package org.vivecraft.common.api_impl; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import org.vivecraft.api.VivecraftAPI; +import org.vivecraft.client.ClientVRPlayers; +import org.jetbrains.annotations.Nullable; +import org.vivecraft.api.data.VRData; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.server.ServerVRPlayers; + +public final class APIImpl implements VivecraftAPI { + + public static final APIImpl INSTANCE = new APIImpl(); + + private APIImpl() { + } + + @Override + public boolean isVRPlayer(Player player) { + if (player instanceof ServerPlayer serverPlayer) { + return ServerVRPlayers.isVRPlayer(serverPlayer); + } + + return ClientVRPlayers.getInstance().isVRPlayer(player); + } + + @Nullable + @Override + public VRData getVRData(Player player) { + if (!isVRPlayer(player)) { + return null; + } + if (player instanceof ServerPlayer serverPlayer) { + return ServerVRPlayers.getVivePlayer(serverPlayer).asVRData(); + } + + return ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()).asVRData(); + } +} diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java new file mode 100644 index 000000000..64b7c8f1c --- /dev/null +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java @@ -0,0 +1,49 @@ +package org.vivecraft.common.api_impl.data; + +import org.vivecraft.api.data.VRData; +import org.vivecraft.api.data.VRPose; + +public class VRDataImpl implements VRData { + + private final VRPose hmd; + private final VRPose c0; + private final VRPose c1; + private final boolean isSeated; + private final boolean usingReversedHands; + + public VRDataImpl(VRPose hmd, VRPose c0, VRPose c1, boolean isSeated, boolean usingReversedHands) { + this.hmd = hmd; + this.c0 = c0; + this.c1 = c1; + this.isSeated = isSeated; + this.usingReversedHands = usingReversedHands; + } + + @Override + public VRPose getHMD() { + return this.hmd; + } + + @Override + public VRPose getController(int controller) { + if (controller != 0 && controller != 1) { + throw new IllegalArgumentException("Controller number must be controller 0 or controller 1."); + } + return controller == 0 ? this.c0 : this.c1; + } + + @Override + public boolean isSeated() { + return this.isSeated; + } + + @Override + public boolean usingReversedHands() { + return this.usingReversedHands; + } + + @Override + public String toString() { + return "HMD: " + getHMD() + "\nController 0: " + getController0() + "\nController 1: " + getController1(); + } +} diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java new file mode 100644 index 000000000..db371a765 --- /dev/null +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java @@ -0,0 +1,55 @@ +package org.vivecraft.common.api_impl.data; + +import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionf; +import org.joml.Quaternionfc; +import org.vivecraft.api.data.VRPose; + +public class VRPoseImpl implements VRPose { + + private final Vec3 pos; + private final Vec3 rot; + private final Quaternionfc quaternion; + + public VRPoseImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) { + this.pos = pos; + this.rot = rot; + this.quaternion = quaternion; + } + + @Override + public Vec3 getPos() { + return this.pos; + } + + @Override + public Vec3 getRot() { + return this.rot; + } + + @Override + public double getPitch() { + return Math.asin(this.rot.y / this.rot.length()); + } + + @Override + public double getYaw() { + return Math.atan2(-this.rot.x, this.rot.z); + } + + @Override + public double getRoll() { + return -Math.atan2(2.0F * (quaternion.x() * quaternion.y() + quaternion.w() * quaternion.z()), + quaternion.w() * quaternion.w() - quaternion.x() * quaternion.x() + quaternion.y() * quaternion.y() - quaternion.z() * quaternion.z()); + } + + @Override + public Quaternionfc getQuaternion() { + return this.quaternion; + } + + @Override + public String toString() { + return "Position: " + getPos() + "\tRotation: " + getRot(); + } +} 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 03af1fd03..57909ea5d 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 @@ -714,7 +714,7 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { if (!VRState.VR_RUNNING || ClientDataHolderVR.getInstance().vrSettings.seated) { return useKeyDown; } else { - return useKeyDown || ClientDataHolderVR.getInstance().vrPlayer.isTrackerUsingItem(this.player); + return useKeyDown || ClientDataHolderVR.getInstance().isTrackerUsingItem(this.player); } } diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index 262d207ef..c7d812a21 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -3,10 +3,17 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionfc; import org.joml.Vector3f; import org.joml.Vector3fc; import org.vivecraft.common.network.*; import org.vivecraft.common.utils.MathUtils; +import org.vivecraft.api.data.VRData; +import org.vivecraft.common.api_impl.data.VRDataImpl; +import org.vivecraft.common.api_impl.data.VRPoseImpl; +import org.vivecraft.common.network.CommonNetworkHelper; +import org.vivecraft.common.network.Pose; +import org.vivecraft.common.network.VrPlayerState; import javax.annotation.Nullable; @@ -142,6 +149,19 @@ public Vec3 getBodyPartPos(BodyPart bodyPart) { return getBodyPartPos(bodyPart, false); } + /** + * + * @param c controller to get the rotation for + * @return controller rotation as a quaternion + */ + public Quaternionfc getControllerQuaternion(int c) { + if (this.vrPlayerState != null) { + Pose controllerPose = c == 0 ? this.vrPlayerState.mainHand() : this.vrPlayerState.offHand(); + return controllerPose.orientation(); + } + return null; // Should only return null if player isn't in VR. + } + /** * @return if the player has VR active */ @@ -162,4 +182,33 @@ public void setVR(boolean vr) { public boolean isSeated() { return this.vrPlayerState != null && this.vrPlayerState.seated(); } + + public boolean usingReversedHands() { + if (this.vrPlayerState == null) { + return false; + } + return this.vrPlayerState.leftHanded(); + } + + public VRData asVRData() { + if (this.vrPlayerState == null) { + return null; + } + return new VRDataImpl( + new VRPoseImpl(this.getHMDPos(), this.getHMDDir(), this.vrPlayerState.hmd().orientation()), + new VRPoseImpl(getPos(this.vrPlayerState.mainHand()), getDir(this.vrPlayerState.mainHand()), this.vrPlayerState.mainHand().orientation()), + new VRPoseImpl(getPos(this.vrPlayerState.offHand()), getDir(this.vrPlayerState.offHand()), this.vrPlayerState.mainHand().orientation()), + this.isSeated(), + this.usingReversedHands() + ); + } + + private Vec3 getPos(Pose pose) { + Vector3fc pos = pose.position(); + return new Vec3(pos.x(), pos.y(), pos.z()); + } + + private Vec3 getDir(Pose pose) { + return new Vec3(pose.orientation().transform(MathUtils.BACK, new Vector3f())); + } } From 106fbcdf8cca2779d2f2bd34cf685b197673563d Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 12 Jan 2025 18:02:10 -0500 Subject: [PATCH 02/33] Fix Rebase Double-Tracker-Register Bug --- .../vivecraft/client_vr/ClientDataHolderVR.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java index b198ee192..7d2299a53 100644 --- a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java @@ -89,22 +89,6 @@ public class ClientDataHolderVR { public boolean showedFbtCalibrationNotification; private ClientDataHolderVR() { - registerTracker(backpackTracker); - registerTracker(bowTracker); - registerTracker(swingTracker); - registerTracker(eatingTracker); - registerTracker(jumpTracker); - registerTracker(sneakTracker); - registerTracker(climbTracker); - registerTracker(runTracker); - registerTracker(rowTracker); - registerTracker(teleportTracker); - registerTracker(horseTracker); - registerTracker(vehicleTracker); - registerTracker(interactTracker); - registerTracker(crawlTracker); - registerTracker(cameraTracker); - registerTracker(telescopeTracker); } public static ClientDataHolderVR getInstance() { From 306dbf57811ecd1f73dc2e3a26065fa9816a4612 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 12 Jan 2025 19:44:47 -0500 Subject: [PATCH 03/33] Left-Handed API Rename --- .../src/main/java/org/vivecraft/api/data/VRData.java | 5 ++--- .../org/vivecraft/common/api_impl/data/VRDataImpl.java | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/data/VRData.java b/common/src/main/java/org/vivecraft/api/data/VRData.java index 124eabb8e..70770c627 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRData.java +++ b/common/src/main/java/org/vivecraft/api/data/VRData.java @@ -1,6 +1,5 @@ package org.vivecraft.api.data; -import com.google.common.annotations.Beta; import net.minecraft.world.InteractionHand; /** @@ -29,9 +28,9 @@ public interface VRData { boolean isSeated(); /** - * @return Whether the player is using reversed hands. + * @return Whether the player is playing with left-handed controls. */ - boolean usingReversedHands(); + boolean isLeftHanded(); /** * Gets the pose for a given controller. diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java index 64b7c8f1c..fc248c49f 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java @@ -9,14 +9,14 @@ public class VRDataImpl implements VRData { private final VRPose c0; private final VRPose c1; private final boolean isSeated; - private final boolean usingReversedHands; + private final boolean isLeftHanded; - public VRDataImpl(VRPose hmd, VRPose c0, VRPose c1, boolean isSeated, boolean usingReversedHands) { + public VRDataImpl(VRPose hmd, VRPose c0, VRPose c1, boolean isSeated, boolean isLeftHanded) { this.hmd = hmd; this.c0 = c0; this.c1 = c1; this.isSeated = isSeated; - this.usingReversedHands = usingReversedHands; + this.isLeftHanded = isLeftHanded; } @Override @@ -38,8 +38,8 @@ public boolean isSeated() { } @Override - public boolean usingReversedHands() { - return this.usingReversedHands; + public boolean isLeftHanded() { + return this.isLeftHanded; } @Override From 2803ff163231029d7a2e1d38c41589c9bdc988d1 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 12 Jan 2025 19:45:42 -0500 Subject: [PATCH 04/33] Rename API Impl Classes to Match API Classes --- common/src/main/java/org/vivecraft/api/VivecraftAPI.java | 4 ++-- .../java/org/vivecraft/api/client/VivecraftClientAPI.java | 4 ++-- .../{ClientAPIImpl.java => VivecraftClientAPIImpl.java} | 7 +++---- common/src/main/java/org/vivecraft/client_vr/VRState.java | 5 ++--- .../java/org/vivecraft/client_vr/gameplay/VRPlayer.java | 6 ++---- .../api_impl/{APIImpl.java => VivecraftAPIImpl.java} | 7 +++---- 6 files changed, 14 insertions(+), 19 deletions(-) rename common/src/main/java/org/vivecraft/client/api_impl/{ClientAPIImpl.java => VivecraftClientAPIImpl.java} (95%) rename common/src/main/java/org/vivecraft/common/api_impl/{APIImpl.java => VivecraftAPIImpl.java} (84%) diff --git a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java index 7a24f6140..dfdac485e 100644 --- a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java +++ b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java @@ -2,7 +2,7 @@ import net.minecraft.world.entity.player.Player; import org.vivecraft.api.data.VRData; -import org.vivecraft.common.api_impl.APIImpl; +import org.vivecraft.common.api_impl.VivecraftAPIImpl; import javax.annotation.Nullable; @@ -12,7 +12,7 @@ public interface VivecraftAPI { * @return The Vivecraft API instance for interacting with Vivecraft's API. */ static VivecraftAPI getInstance() { - return APIImpl.INSTANCE; + return VivecraftAPIImpl.INSTANCE; } /** diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 9958d2021..76f1536fa 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -4,7 +4,7 @@ import net.minecraft.world.InteractionHand; import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.VRData; -import org.vivecraft.client.api_impl.ClientAPIImpl; +import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; import org.vivecraft.client_vr.render.RenderPass; import javax.annotation.Nullable; @@ -12,7 +12,7 @@ public interface VivecraftClientAPI { static VivecraftClientAPI getInstance() { - return ClientAPIImpl.INSTANCE; + return VivecraftClientAPIImpl.INSTANCE; } /** diff --git a/common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java similarity index 95% rename from common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java rename to common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java index 98618a0a1..55ec77497 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/ClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java @@ -11,18 +11,17 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.render.RenderPass; -import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassType; -public final class ClientAPIImpl implements VivecraftClientAPI { +public final class VivecraftClientAPIImpl implements VivecraftClientAPI { - public static final ClientAPIImpl INSTANCE = new ClientAPIImpl(); + public static final VivecraftClientAPIImpl INSTANCE = new VivecraftClientAPIImpl(); private final VRPoseHistoryImpl hmdHistory = new VRPoseHistoryImpl(); private VRPoseHistoryImpl c0History = new VRPoseHistoryImpl(); private VRPoseHistoryImpl c1History = new VRPoseHistoryImpl(); - private ClientAPIImpl() { + private VivecraftClientAPIImpl() { } public void clearHistories() { diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index 3480737f8..6e1fb8f41 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -3,13 +3,12 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import org.apache.commons.lang3.StringUtils; -import org.vivecraft.api.client.Tracker; import org.vivecraft.client.Xplat; import org.vivecraft.client.gui.screens.ErrorScreen; import org.vivecraft.client.gui.screens.GarbageCollectorScreen; import org.vivecraft.client.utils.TextUtils; import org.vivecraft.client_vr.gameplay.VRPlayer; -import org.vivecraft.client.api_impl.ClientAPIImpl; +import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; import org.vivecraft.client_vr.provider.nullvr.NullVR; import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; @@ -154,6 +153,6 @@ public static void destroyVR(boolean disableVRSetting) { // this reloads any PostChain, at least in vanilla Minecraft.getInstance().levelRenderer.onResourceManagerReload(Minecraft.getInstance().getResourceManager()); } - ClientAPIImpl.INSTANCE.clearHistories(); + VivecraftClientAPIImpl.INSTANCE.clearHistories(); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 0fe4dc3ba..80b97de78 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -25,7 +25,7 @@ import org.joml.Vector3fc; import org.vivecraft.api.client.Tracker; import org.vivecraft.client.VivecraftVRMod; -import org.vivecraft.client.api_impl.ClientAPIImpl; +import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.common.VRServerPerms; import org.vivecraft.client.network.ClientNetworking; @@ -44,8 +44,6 @@ import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.ItemTags; -import java.util.ArrayList; - public class VRPlayer { private final Minecraft mc = Minecraft.getInstance(); private final ClientDataHolderVR dh = ClientDataHolderVR.getInstance(); @@ -239,7 +237,7 @@ public void preTick() { this.dh.vrSettings.worldRotation = this.dh.vr.seatedRot; } - ClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRData()); + VivecraftClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRData()); } public void postTick() { diff --git a/common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java similarity index 84% rename from common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java rename to common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java index 4577619a7..824780ab1 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/APIImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java @@ -6,14 +6,13 @@ import org.vivecraft.client.ClientVRPlayers; import org.jetbrains.annotations.Nullable; import org.vivecraft.api.data.VRData; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.server.ServerVRPlayers; -public final class APIImpl implements VivecraftAPI { +public final class VivecraftAPIImpl implements VivecraftAPI { - public static final APIImpl INSTANCE = new APIImpl(); + public static final VivecraftAPIImpl INSTANCE = new VivecraftAPIImpl(); - private APIImpl() { + private VivecraftAPIImpl() { } @Override From 848297b67b07cd3f2377428782090bd173b4410d Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 12 Jan 2025 19:55:30 -0500 Subject: [PATCH 05/33] VRPose and VRBodyPart Rename --- .../java/org/vivecraft/api/VivecraftAPI.java | 12 ++-- .../org/vivecraft/api/client/Tracker.java | 6 +- .../api/client/VivecraftClientAPI.java | 70 +++++++++---------- ...oseHistory.java => VRBodyPartHistory.java} | 18 ++--- .../org/vivecraft/api/data/VRBodyPart.java | 41 +++++++++++ .../java/org/vivecraft/api/data/VRData.java | 62 ---------------- .../java/org/vivecraft/api/data/VRPose.java | 53 +++++++++----- .../org/vivecraft/client/ClientVRPlayers.java | 13 ++-- .../api_impl/VivecraftClientAPIImpl.java | 40 +++++------ ...ryImpl.java => VRBodyPartHistoryImpl.java} | 26 +++---- .../java/org/vivecraft/client_vr/VRData.java | 19 ++--- .../client_vr/gameplay/VRPlayer.java | 2 +- .../common/api_impl/VivecraftAPIImpl.java | 8 +-- .../common/api_impl/data/VRBodyPartImpl.java | 54 ++++++++++++++ .../common/api_impl/data/VRDataImpl.java | 49 ------------- .../common/api_impl/data/VRPoseImpl.java | 54 +++++++------- .../vivecraft/server/ServerVivePlayer.java | 14 ++-- 17 files changed, 270 insertions(+), 271 deletions(-) rename common/src/main/java/org/vivecraft/api/client/data/{VRPoseHistory.java => VRBodyPartHistory.java} (86%) create mode 100644 common/src/main/java/org/vivecraft/api/data/VRBodyPart.java delete mode 100644 common/src/main/java/org/vivecraft/api/data/VRData.java rename common/src/main/java/org/vivecraft/client/api_impl/data/{VRPoseHistoryImpl.java => VRBodyPartHistoryImpl.java} (75%) create mode 100644 common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java delete mode 100644 common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java diff --git a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java index dfdac485e..eafa86d21 100644 --- a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java +++ b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java @@ -1,7 +1,7 @@ package org.vivecraft.api; import net.minecraft.world.entity.player.Player; -import org.vivecraft.api.data.VRData; +import org.vivecraft.api.data.VRPose; import org.vivecraft.common.api_impl.VivecraftAPIImpl; import javax.annotation.Nullable; @@ -24,12 +24,12 @@ static VivecraftAPI getInstance() { boolean isVRPlayer(Player player); /** - * Returns the VR data for the given player. Will return null if the player isn't in VR, - * or if being called from the client, and the client has yet to receive any data for the player. + * Returns the VR pose for the given player. Will return null if the player isn't in VR, + * or if being called from the client and the client has yet to receive any data for the player. * - * @param player Player to get the VR data of. - * @return The VR data for a player, or null if the player isn't in VR or no data has been received for said player. + * @param player Player to get the VR pose of. + * @return The VR pose for a player, or null if the player isn't in VR or no data has been received for said player. */ @Nullable - VRData getVRData(Player player); + VRPose getVRPose(Player player); } diff --git a/common/src/main/java/org/vivecraft/api/client/Tracker.java b/common/src/main/java/org/vivecraft/api/client/Tracker.java index eb54d2efe..af7996a67 100644 --- a/common/src/main/java/org/vivecraft/api/client/Tracker.java +++ b/common/src/main/java/org/vivecraft/api/client/Tracker.java @@ -6,9 +6,9 @@ /** * A tracker is an object that is run for the local player during the game tick or before rendering a frame only if * they are in VR. Using trackers are one of the cleanest ways to interact with Vivecraft's data; it's how Vivecraft - * itself does. Trackers should generally use {@link VivecraftClientAPI#getPreTickWorldData()}, as this provides - * the most up-to-date data, and other methods such as {@link VivecraftClientAPI#getPostTickWorldData()} or - * {@link org.vivecraft.api.VivecraftAPI#getVRData(Player)} may not have data available when the tracker is run. + * itself does. Trackers should generally use {@link VivecraftClientAPI#getPreTickWorldPose()}, as this provides + * the most up-to-date data, and other methods such as {@link VivecraftClientAPI#getPostTickWorldPose()} or + * {@link org.vivecraft.api.VivecraftAPI#getVRPose(Player)} may not have data available when the tracker is run. */ public interface Tracker { diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 76f1536fa..3465a0722 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -2,8 +2,8 @@ import com.google.common.annotations.Beta; import net.minecraft.world.InteractionHand; -import org.vivecraft.api.client.data.VRPoseHistory; -import org.vivecraft.api.data.VRData; +import org.vivecraft.api.client.data.VRBodyPartHistory; +import org.vivecraft.api.data.VRPose; import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; import org.vivecraft.client_vr.render.RenderPass; @@ -24,55 +24,55 @@ static VivecraftClientAPI getInstance() { void registerTracker(Tracker tracker); /** - * Gets data representing the devices as they exist in the room before the game tick. - * Note that this data is gathered BEFORE mod loaders' pre-tick events. + * Gets the VR pose representing the player in the room before the game tick. + * Note that this pose is gathered BEFORE mod loaders' pre-tick events. * - * @return Data representing the devices in the room pre-tick, or null if the local player isn't in VR. + * @return The VR pose representing the player in the room pre-tick, or null if the local player isn't in VR. */ @Nullable - VRData getPreTickRoomData(); + VRPose getPreTickRoomPose(); /** - * Gets data representing the devices as they exist in the room after the game tick. - * Note that this data is gathered AFTER mod loaders' post-tick events. + * Gets the VR pose representing the player in the room after the game tick. + * Note that this pose is gathered AFTER mod loaders' post-tick events. * - * @return Data representing the devices in the room post-tick, or null if the local player isn't in VR. + * @return The VR pose representing the player in the room post-tick, or null if the local player isn't in VR. */ @Nullable - VRData getPostTickRoomData(); + VRPose getPostTickRoomPose(); /** - * Gets data representing the devices as they exist in Minecraft coordinates before the game tick. - * This is the same as {@link #getPreTickRoomData()} with translation to Minecraft's coordinates as of the last - * tick, and is the main data source used by Vivecraft. If you're unsure which {@link VRData} method to use, you - * likely want to use this one. - * Note that this data is gathered BEFORE mod loaders' pre-tick events. + * Gets the VR pose representing the player in Minecraft world coordinates before the game tick. + * This is the same as {@link #getPreTickRoomPose()} with translation to in-game world coordinates as of the last + * tick, and is the main pose source used by Vivecraft for gameplay. If you're unsure which {@link VRPose} method + * to use, you likely want to use this one. + * Note that this pose is gathered BEFORE mod loaders' pre-tick events. * - * @return Data representing the devices in Minecraft space pre-tick, or null if the local player isn't in VR. + * @return The VR pose representing the player in world space pre-tick, or null if the local player isn't in VR. */ @Nullable - VRData getPreTickWorldData(); + VRPose getPreTickWorldPose(); /** - * Gets data representing the devices as they exist in Minecraft coordinates after the game tick. - * This is the data sent to the server, and also used to calculate the data in {@link #getWorldRenderData()}. - * Note that this data is gathered AFTER mod loaders' post-tick events. + * Gets the VR pose representing the player in Minecraft world coordinates after the game tick. + * This is the pose sent to the server, and also used to calculate the pose in {@link #getWorldRenderPose()}. + * Note that this pose is gathered AFTER mod loaders' post-tick events. * - * @return Data representing the devices in Minecraft space post-tick, or null if the local player isn't in VR. + * @return The VR pose representing the player in Minecraft space post-tick, or null if the local player isn't in VR. */ @Nullable - VRData getPostTickWorldData(); + VRPose getPostTickWorldPose(); /** - * Gets data representing the devices as they exist in Minecraft coordinates after the game tick interpolated for + * Gets the VR pose representing the player in Minecraft world coordinates after the game tick interpolated for * rendering. - * This is the same data as {@link #getPostTickWorldData()}, however it is interpolated for rendering. + * This is the same pose as {@link #getPostTickWorldPose()}, however it is interpolated for rendering. * - * @return Data representing the devices in Minecraft space post-tick interpolated for rendering, or null if the - * local player isn't in VR. + * @return The VR pose representing the player in Minecraft space post-tick interpolated for rendering, or null if + * the local player isn't in VR. */ @Nullable - VRData getWorldRenderData(); + VRPose getWorldRenderPose(); /** * Causes a haptic pulse (vibration/rumble) for the specified controller. @@ -106,14 +106,14 @@ default void triggerHapticPulse(int controllerNum, float duration) { } /** - * @return Whether the client player is currently in seated mode. + * @return Whether the local player is currently in seated mode. */ boolean isSeated(); /** - * @return Whether the client player is using reversed hands. + * @return Whether the local player is playing with left-handed controls. */ - boolean usingReversedHands(); + boolean isLeftHanded(); /** * @return Whether VR support is initialized. @@ -137,7 +137,7 @@ default void triggerHapticPulse(int controllerNum, float duration) { * @return The historical VR data for the player's HMD, or null if the player isn't in VR. */ @Nullable - VRPoseHistory getHistoricalVRHMDPoses(); + VRBodyPartHistory getHistoricalVRHMDPoses(); /** * Returns the history of VR poses for the player for a controller. Will return null if the player isn't @@ -147,7 +147,7 @@ default void triggerHapticPulse(int controllerNum, float duration) { * @return The historical VR data for the player's controller, or null if the player isn't in VR. */ @Nullable - VRPoseHistory getHistoricalVRControllerPoses(int controller); + VRBodyPartHistory getHistoricalVRControllerPoses(int controller); /** * Returns the history of VR poses for the player for a controller. Will return null if the player isn't @@ -157,7 +157,7 @@ default void triggerHapticPulse(int controllerNum, float duration) { * @return The historical VR data for the player's controller, or null if the player isn't in VR. */ @Nullable - default VRPoseHistory getHistoricalVRControllerPoses(InteractionHand hand) { + default VRBodyPartHistory getHistoricalVRControllerPoses(InteractionHand hand) { return getHistoricalVRControllerPoses(hand.ordinal()); } @@ -168,7 +168,7 @@ default VRPoseHistory getHistoricalVRControllerPoses(InteractionHand hand) { * @return The historical VR data for the player's primary controller, or null if the player isn't in VR. */ @Nullable - default VRPoseHistory getHistoricalVRController0Poses() { + default VRBodyPartHistory getHistoricalVRController0Poses() { return getHistoricalVRControllerPoses(0); } @@ -179,7 +179,7 @@ default VRPoseHistory getHistoricalVRController0Poses() { * @return The historical VR data for the player's secondary controller, or null if the player isn't in VR. */ @Nullable - default VRPoseHistory getHistoricalVRController1Poses() { + default VRBodyPartHistory getHistoricalVRController1Poses() { return getHistoricalVRControllerPoses(1); } diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRBodyPartHistory.java similarity index 86% rename from common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java rename to common/src/main/java/org/vivecraft/api/client/data/VRBodyPartHistory.java index b0a50549c..60d681693 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRBodyPartHistory.java @@ -1,14 +1,14 @@ package org.vivecraft.api.client.data; import net.minecraft.world.phys.Vec3; -import org.vivecraft.api.data.VRPose; +import org.vivecraft.api.data.VRBodyPart; import java.util.List; /** - * Represents historical VRData associated with a player. + * Represents historical {@link VRBodyPart}s associated with a player. */ -public interface VRPoseHistory { +public interface VRBodyPartHistory { /** * The maximum amount of ticks back data is held for. @@ -22,27 +22,27 @@ public interface VRPoseHistory { /** * @return The amount of ticks worth of history being held. The number returned by this methodwill never be higher - * than {@link VRPoseHistory#MAX_TICKS_BACK}, however can be lower than it. + * than {@link VRBodyPartHistory#MAX_TICKS_BACK}, however can be lower than it. */ int ticksOfHistory(); /** - * Gets a raw list of {@link VRPose} instances, with index 0 representing the least recent pose known. + * Gets a raw list of {@link VRBodyPart} instances, with index 0 representing the least recent pose known. * - * @return The aforementioned list of {@link VRPose} instances. + * @return The aforementioned list of {@link VRBodyPart} instances. */ - List getAllHistoricalData() throws IllegalArgumentException; + List getAllHistoricalData() throws IllegalArgumentException; /** * Gets the historical data ticksBack ticks back. This will throw an IllegalStateException if the data cannot * be retrieved due to not having enough history. * * @param ticksBack Ticks back to retrieve data. - * @return A {@link VRPose} instance from index ticks ago. + * @return A {@link VRBodyPart} instance from index ticks ago. * @throws IllegalStateException If ticksBack references a tick that there is not yet data for. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; + VRBodyPart getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; /** * Gets the net movement between the most recent data in this instance and the oldest position that can be diff --git a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java new file mode 100644 index 000000000..ee71a2ee3 --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java @@ -0,0 +1,41 @@ +package org.vivecraft.api.data; + +import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionfc; + +/** + * Represents the data for a body part, or a device usually tied to a body part in VR, such as the HMD or a + * controller. + */ +public interface VRBodyPart { + + /** + * @return The position of the body part in Minecraft world coordinates. + */ + Vec3 getPos(); + + /** + * @return The rotation of the body part. + */ + Vec3 getRot(); + + /** + * @return The pitch of the body part in radians. + */ + double getPitch(); + + /** + * @return The yaw of the body part in radians. + */ + double getYaw(); + + /** + * @return The roll of the body part in radians. + */ + double getRoll(); + + /** + * @return The quaternion representing the rotation of the body part. + */ + Quaternionfc getQuaternion(); +} diff --git a/common/src/main/java/org/vivecraft/api/data/VRData.java b/common/src/main/java/org/vivecraft/api/data/VRData.java deleted file mode 100644 index 70770c627..000000000 --- a/common/src/main/java/org/vivecraft/api/data/VRData.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.vivecraft.api.data; - -import net.minecraft.world.InteractionHand; - -/** - * Represents all VR data associated with a given player, mainly the pose of the HMD and both controllers - * of the player. If the player is in seated mode, controller 1 carries the HMD's data, and controller 0 is - * based on the direction being looked at via the mouse pointer. - */ -public interface VRData { - - /** - * @return Pose data for the HMD. - */ - VRPose getHMD(); - - /** - * Gets the pose data for a given controller. - * - * @param controller The controller number to get, with 0 being the primary controller. - * @return The specified controller's pose data. - */ - VRPose getController(int controller); - - /** - * @return Whether the player is currently in seated mode. - */ - boolean isSeated(); - - /** - * @return Whether the player is playing with left-handed controls. - */ - boolean isLeftHanded(); - - /** - * Gets the pose for a given controller. - * - * @param hand The interaction hand to get controller data for. - * @return The specified controller's pose data. - */ - default VRPose getController(InteractionHand hand) { - return getController(hand.ordinal()); - } - - /** - * Gets the pose for the primary controller. - * - * @return The main controller's pose data. - */ - default VRPose getController0() { - return getController(0); - } - - /** - * Gets the pose for the secondary controller. - * - * @return The main controller's pose data. - */ - default VRPose getController1() { - return getController(1); - } -} diff --git a/common/src/main/java/org/vivecraft/api/data/VRPose.java b/common/src/main/java/org/vivecraft/api/data/VRPose.java index 176827aaa..5b0f21ae7 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRPose.java +++ b/common/src/main/java/org/vivecraft/api/data/VRPose.java @@ -1,42 +1,61 @@ package org.vivecraft.api.data; -import net.minecraft.world.phys.Vec3; -import org.joml.Quaternionf; -import org.joml.Quaternionfc; +import net.minecraft.world.InteractionHand; /** - * Represents the pose data, such as position and rotation, for a given trackable object, such as the HMD or - * a controller. + * Represents the pose of the VR player. In other words, the position and rotation data of all tracked body parts of + * the VR player. */ public interface VRPose { /** - * @return The position of the device in Minecraft world coordinates. + * @return Pose data for the HMD. */ - Vec3 getPos(); + VRBodyPart getHMD(); /** - * @return The rotation of the device. + * Gets the pose data for a given controller. + * + * @param controller The controller number to get, with 0 being the primary controller. + * @return The specified controller's pose data. */ - Vec3 getRot(); + VRBodyPart getController(int controller); /** - * @return The pitch of the device in radians. + * @return Whether the player is currently in seated mode. */ - double getPitch(); + boolean isSeated(); /** - * @return The yaw of the device in radians. + * @return Whether the player is playing with left-handed controls. */ - double getYaw(); + boolean isLeftHanded(); /** - * @return The roll of the device in radians. + * Gets the pose for a given controller. + * + * @param hand The interaction hand to get controller data for. + * @return The specified controller's pose data. */ - double getRoll(); + default VRBodyPart getController(InteractionHand hand) { + return getController(hand.ordinal()); + } /** - * @return The quaternion representing the rotation of the device. + * Gets the pose for the primary controller. + * + * @return The main controller's pose data. */ - Quaternionfc getQuaternion(); + default VRBodyPart getController0() { + return getController(0); + } + + /** + * Gets the pose for the secondary controller. + * + * @return The main controller's pose data. + */ + default VRBodyPart getController1() { + return getController(1); + } } diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index bb83bb7b6..38a0a595b 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -13,6 +13,7 @@ import org.joml.Quaternionfc; import org.joml.Vector3f; import org.joml.Vector3fc; +import org.vivecraft.api.data.VRPose; import org.vivecraft.client.extensions.SparkParticleExtension; import org.vivecraft.client.utils.ClientUtils; import org.vivecraft.client.utils.ModelUtils; @@ -25,8 +26,8 @@ import org.vivecraft.client_vr.settings.AutoCalibration; import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassType; -import org.vivecraft.common.api_impl.data.VRDataImpl; import org.vivecraft.common.api_impl.data.VRPoseImpl; +import org.vivecraft.common.api_impl.data.VRBodyPartImpl; import org.vivecraft.common.network.FBTMode; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.common.utils.MathUtils; @@ -570,11 +571,11 @@ public float getBodyYawRad() { return (float) Math.atan2(-dir.x, dir.z); } - public org.vivecraft.api.data.VRData asVRData() { - return new VRDataImpl( - new VRPoseImpl(fromVector3fc(this.headPos), fromVector3fc(this.headRot), this.headQuat), - new VRPoseImpl(fromVector3fc(this.mainHandPos), fromVector3fc(this.mainHandRot), this.mainHandQuat), - new VRPoseImpl(fromVector3fc(this.offHandPos), fromVector3fc(this.offHandPos), this.offHandQuat), + public VRPose asVRPose() { + return new VRPoseImpl( + new VRBodyPartImpl(fromVector3fc(this.headPos), fromVector3fc(this.headRot), this.headQuat), + new VRBodyPartImpl(fromVector3fc(this.mainHandPos), fromVector3fc(this.mainHandRot), this.mainHandQuat), + new VRBodyPartImpl(fromVector3fc(this.offHandPos), fromVector3fc(this.offHandPos), this.offHandQuat), this.seated, this.leftHanded ); diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java index 55ec77497..938b89ce1 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java @@ -2,10 +2,10 @@ import org.jetbrains.annotations.Nullable; import org.vivecraft.api.client.Tracker; -import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.client.data.VRBodyPartHistory; import org.vivecraft.api.client.VivecraftClientAPI; -import org.vivecraft.api.data.VRData; -import org.vivecraft.client.api_impl.data.VRPoseHistoryImpl; +import org.vivecraft.api.data.VRPose; +import org.vivecraft.client.api_impl.data.VRBodyPartHistoryImpl; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; @@ -17,9 +17,9 @@ public final class VivecraftClientAPIImpl implements VivecraftClientAPI { public static final VivecraftClientAPIImpl INSTANCE = new VivecraftClientAPIImpl(); - private final VRPoseHistoryImpl hmdHistory = new VRPoseHistoryImpl(); - private VRPoseHistoryImpl c0History = new VRPoseHistoryImpl(); - private VRPoseHistoryImpl c1History = new VRPoseHistoryImpl(); + private final VRBodyPartHistoryImpl hmdHistory = new VRBodyPartHistoryImpl(); + private VRBodyPartHistoryImpl c0History = new VRBodyPartHistoryImpl(); + private VRBodyPartHistoryImpl c1History = new VRBodyPartHistoryImpl(); private VivecraftClientAPIImpl() { } @@ -30,7 +30,7 @@ public void clearHistories() { this.c1History.clear(); } - public void addPosesToHistory(VRData data) { + public void addPosesToHistory(VRPose data) { this.hmdHistory.addPose(data.getHMD()); this.c0History.addPose(data.getController0()); this.c1History.addPose(data.getController1()); @@ -38,47 +38,47 @@ public void addPosesToHistory(VRData data) { @Nullable @Override - public VRData getPreTickRoomData() { + public VRPose getPreTickRoomPose() { if (!isVrActive()) { return null; } - return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_pre.asVRData(); + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_pre.asVRPose(); } @Nullable @Override - public VRData getPostTickRoomData() { + public VRPose getPostTickRoomPose() { if (!isVrActive()) { return null; } - return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_post.asVRData(); + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_post.asVRPose(); } @Nullable @Override - public VRData getPreTickWorldData() { + public VRPose getPreTickWorldPose() { if (!isVrActive()) { return null; } - return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_pre.asVRData(); + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_pre.asVRPose(); } @Nullable @Override - public VRData getPostTickWorldData() { + public VRPose getPostTickWorldPose() { if (!isVrActive()) { return null; } - return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_post.asVRData(); + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_post.asVRPose(); } @Nullable @Override - public VRData getWorldRenderData() { + public VRPose getWorldRenderPose() { if (!isVrActive()) { return null; } - return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_render.asVRData(); + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_render.asVRPose(); } @Override @@ -106,7 +106,7 @@ public boolean isSeated() { } @Override - public boolean usingReversedHands() { + public boolean isLeftHanded() { return ClientDataHolderVR.getInstance().vrSettings.reverseHands; } @@ -136,7 +136,7 @@ public void registerTracker(Tracker tracker) { @Nullable @Override - public VRPoseHistory getHistoricalVRHMDPoses() { + public VRBodyPartHistory getHistoricalVRHMDPoses() { if (!isVrActive()) { return null; } @@ -145,7 +145,7 @@ public VRPoseHistory getHistoricalVRHMDPoses() { @Nullable @Override - public VRPoseHistory getHistoricalVRControllerPoses(int controller) { + public VRBodyPartHistory getHistoricalVRControllerPoses(int controller) { if (controller != 0 && controller != 1) { throw new IllegalArgumentException("Historical VR controller data only available for controllers 0 and 1."); } else if (!isVrActive()) { diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java similarity index 75% rename from common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java rename to common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java index 3058a06cd..79f722e62 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java @@ -1,21 +1,21 @@ package org.vivecraft.client.api_impl.data; import net.minecraft.world.phys.Vec3; -import org.vivecraft.api.client.data.VRPoseHistory; -import org.vivecraft.api.data.VRPose; +import org.vivecraft.api.client.data.VRBodyPartHistory; +import org.vivecraft.api.data.VRBodyPart; import java.util.*; -public class VRPoseHistoryImpl implements VRPoseHistory { +public class VRBodyPartHistoryImpl implements VRBodyPartHistory { - private final LinkedList dataQueue = new LinkedList<>(); + private final LinkedList dataQueue = new LinkedList<>(); - public VRPoseHistoryImpl() { + public VRBodyPartHistoryImpl() { } - public void addPose(VRPose pose) { + public void addPose(VRBodyPart pose) { this.dataQueue.addFirst(pose); - if (this.dataQueue.size() > VRPoseHistory.MAX_TICKS_BACK) { + if (this.dataQueue.size() > VRBodyPartHistory.MAX_TICKS_BACK) { this.dataQueue.removeLast(); } } @@ -30,12 +30,12 @@ public int ticksOfHistory() { } @Override - public List getAllHistoricalData() { + public List getAllHistoricalData() { return new ArrayList<>(this.dataQueue); } @Override - public VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException { + public VRBodyPart getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException { checkTicksBack(ticksBack); if (this.dataQueue.size() <= ticksBack) { throw new IllegalStateException("Cannot retrieve data from " + ticksBack + " ticks ago, when there is " + @@ -64,7 +64,7 @@ public Vec3 averageVelocity(int maxTicksBack) throws IllegalArgumentException { public Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException { checkTicksBack(maxTicksBack); int iters = getNumTicksBack(maxTicksBack); - ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); + ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); Vec3 avg = this.dataQueue.getLast().getPos(); int i = iters; while (i > 0) { @@ -75,12 +75,12 @@ public Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException { } private void checkTicksBack(int ticksBack) { - if (ticksBack < 0 || ticksBack > VRPoseHistory.MAX_TICKS_BACK) { - throw new IllegalArgumentException("Value must be between 0 and " + VRPoseHistory.MAX_TICKS_BACK + "."); + if (ticksBack < 0 || ticksBack > VRBodyPartHistory.MAX_TICKS_BACK) { + throw new IllegalArgumentException("Value must be between 0 and " + VRBodyPartHistory.MAX_TICKS_BACK + "."); } } - private VRPose getOldPose(int maxTicksBack) { + private VRBodyPart getOldPose(int maxTicksBack) { if (this.dataQueue.size() <= maxTicksBack) { return this.dataQueue.getFirst(); } else { diff --git a/common/src/main/java/org/vivecraft/client_vr/VRData.java b/common/src/main/java/org/vivecraft/client_vr/VRData.java index 2a7950d24..5e07f0547 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRData.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRData.java @@ -4,6 +4,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; import org.joml.*; +import org.vivecraft.api.data.VRPose; import org.vivecraft.client.ClientVRPlayers; import org.vivecraft.client.gui.screens.FBTCalibrationScreen; import org.vivecraft.client_vr.provider.MCVR; @@ -15,9 +16,9 @@ import javax.annotation.Nullable; import java.lang.Math; import org.joml.Quaternionf; -import org.vivecraft.api.data.VRPose; -import org.vivecraft.common.api_impl.data.VRDataImpl; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.api_impl.data.VRPoseImpl; +import org.vivecraft.common.api_impl.data.VRBodyPartImpl; public class VRData { // headset center @@ -365,11 +366,11 @@ public VRDevicePose getEye(RenderPass pass) { /** * @return this data in a manner better-suited for the API */ - public org.vivecraft.api.data.VRData asVRData() { - return new VRDataImpl( - this.hmd.asVRPose(), - this.c0.asVRPose(), - this.c1.asVRPose(), + public VRPose asVRPose() { + return new VRPoseImpl( + this.hmd.asVRBodyPart(), + this.c0.asVRBodyPart(), + this.c1.asVRBodyPart(), ClientDataHolderVR.getInstance().vrSettings.seated, ClientDataHolderVR.getInstance().vrSettings.reverseHands ); @@ -519,10 +520,10 @@ public Matrix4f getMatrix() { return new Matrix4f().rotationY(VRData.this.rotation_radians).mul(this.matrix); } - public VRPose asVRPose() { + public VRBodyPart asVRBodyPart() { Quaternionf quat = new Quaternionf(); quat.setFromUnnormalized(getMatrix()); - return new VRPoseImpl( + return new VRBodyPartImpl( getPosition(), new Vec3(getDirection()), quat diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 80b97de78..f8e58c31f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -237,7 +237,7 @@ public void preTick() { this.dh.vrSettings.worldRotation = this.dh.vr.seatedRot; } - VivecraftClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRData()); + VivecraftClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRPose()); } public void postTick() { diff --git a/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java index 824780ab1..e23614bb5 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java @@ -5,7 +5,7 @@ import org.vivecraft.api.VivecraftAPI; import org.vivecraft.client.ClientVRPlayers; import org.jetbrains.annotations.Nullable; -import org.vivecraft.api.data.VRData; +import org.vivecraft.api.data.VRPose; import org.vivecraft.server.ServerVRPlayers; public final class VivecraftAPIImpl implements VivecraftAPI { @@ -26,14 +26,14 @@ public boolean isVRPlayer(Player player) { @Nullable @Override - public VRData getVRData(Player player) { + public VRPose getVRPose(Player player) { if (!isVRPlayer(player)) { return null; } if (player instanceof ServerPlayer serverPlayer) { - return ServerVRPlayers.getVivePlayer(serverPlayer).asVRData(); + return ServerVRPlayers.getVivePlayer(serverPlayer).asVRPose(); } - return ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()).asVRData(); + return ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()).asVRPose(); } } diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java new file mode 100644 index 000000000..fcdda5760 --- /dev/null +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java @@ -0,0 +1,54 @@ +package org.vivecraft.common.api_impl.data; + +import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionfc; +import org.vivecraft.api.data.VRBodyPart; + +public class VRBodyPartImpl implements VRBodyPart { + + private final Vec3 pos; + private final Vec3 rot; + private final Quaternionfc quaternion; + + public VRBodyPartImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) { + this.pos = pos; + this.rot = rot; + this.quaternion = quaternion; + } + + @Override + public Vec3 getPos() { + return this.pos; + } + + @Override + public Vec3 getRot() { + return this.rot; + } + + @Override + public double getPitch() { + return Math.asin(this.rot.y / this.rot.length()); + } + + @Override + public double getYaw() { + return Math.atan2(-this.rot.x, this.rot.z); + } + + @Override + public double getRoll() { + return -Math.atan2(2.0F * (quaternion.x() * quaternion.y() + quaternion.w() * quaternion.z()), + quaternion.w() * quaternion.w() - quaternion.x() * quaternion.x() + quaternion.y() * quaternion.y() - quaternion.z() * quaternion.z()); + } + + @Override + public Quaternionfc getQuaternion() { + return this.quaternion; + } + + @Override + public String toString() { + return "Position: " + getPos() + "\tRotation: " + getRot(); + } +} diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java deleted file mode 100644 index fc248c49f..000000000 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRDataImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.vivecraft.common.api_impl.data; - -import org.vivecraft.api.data.VRData; -import org.vivecraft.api.data.VRPose; - -public class VRDataImpl implements VRData { - - private final VRPose hmd; - private final VRPose c0; - private final VRPose c1; - private final boolean isSeated; - private final boolean isLeftHanded; - - public VRDataImpl(VRPose hmd, VRPose c0, VRPose c1, boolean isSeated, boolean isLeftHanded) { - this.hmd = hmd; - this.c0 = c0; - this.c1 = c1; - this.isSeated = isSeated; - this.isLeftHanded = isLeftHanded; - } - - @Override - public VRPose getHMD() { - return this.hmd; - } - - @Override - public VRPose getController(int controller) { - if (controller != 0 && controller != 1) { - throw new IllegalArgumentException("Controller number must be controller 0 or controller 1."); - } - return controller == 0 ? this.c0 : this.c1; - } - - @Override - public boolean isSeated() { - return this.isSeated; - } - - @Override - public boolean isLeftHanded() { - return this.isLeftHanded; - } - - @Override - public String toString() { - return "HMD: " + getHMD() + "\nController 0: " + getController0() + "\nController 1: " + getController1(); - } -} diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java index db371a765..71b402461 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java @@ -1,55 +1,49 @@ package org.vivecraft.common.api_impl.data; -import net.minecraft.world.phys.Vec3; -import org.joml.Quaternionf; -import org.joml.Quaternionfc; import org.vivecraft.api.data.VRPose; +import org.vivecraft.api.data.VRBodyPart; public class VRPoseImpl implements VRPose { - private final Vec3 pos; - private final Vec3 rot; - private final Quaternionfc quaternion; + private final VRBodyPart hmd; + private final VRBodyPart c0; + private final VRBodyPart c1; + private final boolean isSeated; + private final boolean isLeftHanded; - public VRPoseImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) { - this.pos = pos; - this.rot = rot; - this.quaternion = quaternion; + public VRPoseImpl(VRBodyPart hmd, VRBodyPart c0, VRBodyPart c1, boolean isSeated, boolean isLeftHanded) { + this.hmd = hmd; + this.c0 = c0; + this.c1 = c1; + this.isSeated = isSeated; + this.isLeftHanded = isLeftHanded; } @Override - public Vec3 getPos() { - return this.pos; + public VRBodyPart getHMD() { + return this.hmd; } @Override - public Vec3 getRot() { - return this.rot; + public VRBodyPart getController(int controller) { + if (controller != 0 && controller != 1) { + throw new IllegalArgumentException("Controller number must be controller 0 or controller 1."); + } + return controller == 0 ? this.c0 : this.c1; } @Override - public double getPitch() { - return Math.asin(this.rot.y / this.rot.length()); + public boolean isSeated() { + return this.isSeated; } @Override - public double getYaw() { - return Math.atan2(-this.rot.x, this.rot.z); - } - - @Override - public double getRoll() { - return -Math.atan2(2.0F * (quaternion.x() * quaternion.y() + quaternion.w() * quaternion.z()), - quaternion.w() * quaternion.w() - quaternion.x() * quaternion.x() + quaternion.y() * quaternion.y() - quaternion.z() * quaternion.z()); - } - - @Override - public Quaternionfc getQuaternion() { - return this.quaternion; + public boolean isLeftHanded() { + return this.isLeftHanded; } @Override public String toString() { - return "Position: " + getPos() + "\tRotation: " + getRot(); + return "HMD: " + getHMD() + "\nController 0: " + getController0() + "\nController 1: " + getController1(); } } diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index c7d812a21..c957c226b 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -8,9 +8,9 @@ import org.joml.Vector3fc; import org.vivecraft.common.network.*; import org.vivecraft.common.utils.MathUtils; -import org.vivecraft.api.data.VRData; -import org.vivecraft.common.api_impl.data.VRDataImpl; +import org.vivecraft.api.data.VRPose; import org.vivecraft.common.api_impl.data.VRPoseImpl; +import org.vivecraft.common.api_impl.data.VRBodyPartImpl; import org.vivecraft.common.network.CommonNetworkHelper; import org.vivecraft.common.network.Pose; import org.vivecraft.common.network.VrPlayerState; @@ -190,14 +190,14 @@ public boolean usingReversedHands() { return this.vrPlayerState.leftHanded(); } - public VRData asVRData() { + public VRPose asVRPose() { if (this.vrPlayerState == null) { return null; } - return new VRDataImpl( - new VRPoseImpl(this.getHMDPos(), this.getHMDDir(), this.vrPlayerState.hmd().orientation()), - new VRPoseImpl(getPos(this.vrPlayerState.mainHand()), getDir(this.vrPlayerState.mainHand()), this.vrPlayerState.mainHand().orientation()), - new VRPoseImpl(getPos(this.vrPlayerState.offHand()), getDir(this.vrPlayerState.offHand()), this.vrPlayerState.mainHand().orientation()), + return new VRPoseImpl( + new VRBodyPartImpl(this.getHMDPos(), this.getHMDDir(), this.vrPlayerState.hmd().orientation()), + new VRBodyPartImpl(getPos(this.vrPlayerState.mainHand()), getDir(this.vrPlayerState.mainHand()), this.vrPlayerState.mainHand().orientation()), + new VRBodyPartImpl(getPos(this.vrPlayerState.offHand()), getDir(this.vrPlayerState.offHand()), this.vrPlayerState.mainHand().orientation()), this.isSeated(), this.usingReversedHands() ); From e0ab6deed5b82df93fe7a3f6ea54a37a738f6781 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 12 Jan 2025 20:42:09 -0500 Subject: [PATCH 06/33] Separate Vivecraft Rendering API Interface --- .../java/org/vivecraft/api/VivecraftAPI.java | 3 ++ .../api/client/VivecraftClientAPI.java | 22 +++----------- .../api/client/VivecraftRenderingAPI.java | 30 +++++++++++++++++++ .../api_impl/VivecraftClientAPIImpl.java | 15 ---------- .../api_impl/VivecraftRenderingAPIImpl.java | 29 ++++++++++++++++++ 5 files changed, 66 insertions(+), 33 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java create mode 100644 common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java diff --git a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java index eafa86d21..6d44f86c4 100644 --- a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java +++ b/common/src/main/java/org/vivecraft/api/VivecraftAPI.java @@ -6,6 +6,9 @@ import javax.annotation.Nullable; +/** + * The main interface for interacting with Vivecraft from common code. + */ public interface VivecraftAPI { /** diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 3465a0722..2174d1e55 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -9,6 +9,10 @@ import javax.annotation.Nullable; +/** + * The main interface for interacting with Vivecraft from client code. For rendering, one should use + * {@link VivecraftRenderingAPI}. + */ public interface VivecraftClientAPI { static VivecraftClientAPI getInstance() { @@ -191,22 +195,4 @@ default VRBodyPartHistory getHistoricalVRController1Poses() { * @return Whether the keyboard is currently showing after attempting to open/close it. */ boolean setKeyboardState(boolean isNowOpen); - - /** - * @return Whether the current render pass is a vanilla render pass. - */ - @Beta - boolean isVanillaRenderPass(); - - /** - * @return The current render pass Vivecraft is performing. - */ - @Beta - RenderPass getCurrentRenderPass(); - - /** - * @return Whether the current render pass is the first one it performed for this render cycle. - */ - @Beta - boolean isFirstRenderPass(); } diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java new file mode 100644 index 000000000..75cd7e232 --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java @@ -0,0 +1,30 @@ +package org.vivecraft.api.client; + +import org.vivecraft.client.api_impl.VivecraftRenderingAPIImpl; +import org.vivecraft.client_vr.render.RenderPass; + +/** + * The main interface for interacting with Vivecraft from rendering code. For other client-side code, one should use + * {@link VivecraftClientAPI}. + */ +public interface VivecraftRenderingAPI { + + static VivecraftRenderingAPI getInstance() { + return VivecraftRenderingAPIImpl.INSTANCE; + } + + /** + * @return Whether the current render pass is a vanilla render pass. + */ + boolean isVanillaRenderPass(); + + /** + * @return The current render pass Vivecraft is performing. + */ + RenderPass getCurrentRenderPass(); + + /** + * @return Whether the current render pass is the first one it performed for this render cycle. + */ + boolean isFirstRenderPass(); +} diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java index 938b89ce1..7039a6dce 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java @@ -161,19 +161,4 @@ public boolean setKeyboardState(boolean isNowOpen) { } return false; } - - @Override - public boolean isVanillaRenderPass() { - return RenderPassType.isVanilla(); - } - - @Override - public RenderPass getCurrentRenderPass() { - return ClientDataHolderVR.getInstance().currentPass; - } - - @Override - public boolean isFirstRenderPass() { - return ClientDataHolderVR.getInstance().isFirstPass; - } } diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java new file mode 100644 index 000000000..aaebb0f47 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java @@ -0,0 +1,29 @@ +package org.vivecraft.client.api_impl; + +import org.vivecraft.api.client.VivecraftRenderingAPI; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_xr.render_pass.RenderPassType; + +public class VivecraftRenderingAPIImpl implements VivecraftRenderingAPI { + + public static final VivecraftRenderingAPIImpl INSTANCE = new VivecraftRenderingAPIImpl(); + + private VivecraftRenderingAPIImpl() { + } + + @Override + public boolean isVanillaRenderPass() { + return RenderPassType.isVanilla(); + } + + @Override + public RenderPass getCurrentRenderPass() { + return ClientDataHolderVR.getInstance().currentPass; + } + + @Override + public boolean isFirstRenderPass() { + return ClientDataHolderVR.getInstance().isFirstPass; + } +} From a5429134953e3669c917f1aacc981eea89b16147 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 12 Jan 2025 20:51:58 -0500 Subject: [PATCH 07/33] VR Capitalization Consistency --- .../api/client/VivecraftClientAPI.java | 6 ++--- .../api_impl/VivecraftClientAPIImpl.java | 26 +++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 2174d1e55..01ebd100a 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -1,11 +1,9 @@ package org.vivecraft.api.client; -import com.google.common.annotations.Beta; import net.minecraft.world.InteractionHand; import org.vivecraft.api.client.data.VRBodyPartHistory; import org.vivecraft.api.data.VRPose; import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; -import org.vivecraft.client_vr.render.RenderPass; import javax.annotation.Nullable; @@ -122,12 +120,12 @@ default void triggerHapticPulse(int controllerNum, float duration) { /** * @return Whether VR support is initialized. */ - boolean isVrInitialized(); + boolean isVRInitialized(); /** * @return Whether the client is actively in VR. */ - boolean isVrActive(); + boolean isVRActive(); /** * @return The currently active world scale. diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java index 7039a6dce..c23263540 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java @@ -10,8 +10,6 @@ import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.provider.ControllerType; -import org.vivecraft.client_vr.render.RenderPass; -import org.vivecraft.client_xr.render_pass.RenderPassType; public final class VivecraftClientAPIImpl implements VivecraftClientAPI { @@ -39,7 +37,7 @@ public void addPosesToHistory(VRPose data) { @Nullable @Override public VRPose getPreTickRoomPose() { - if (!isVrActive()) { + if (!isVRActive()) { return null; } return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_pre.asVRPose(); @@ -48,7 +46,7 @@ public VRPose getPreTickRoomPose() { @Nullable @Override public VRPose getPostTickRoomPose() { - if (!isVrActive()) { + if (!isVRActive()) { return null; } return ClientDataHolderVR.getInstance().vrPlayer.vrdata_room_post.asVRPose(); @@ -57,7 +55,7 @@ public VRPose getPostTickRoomPose() { @Nullable @Override public VRPose getPreTickWorldPose() { - if (!isVrActive()) { + if (!isVRActive()) { return null; } return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_pre.asVRPose(); @@ -66,7 +64,7 @@ public VRPose getPreTickWorldPose() { @Nullable @Override public VRPose getPostTickWorldPose() { - if (!isVrActive()) { + if (!isVRActive()) { return null; } return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_post.asVRPose(); @@ -75,7 +73,7 @@ public VRPose getPostTickWorldPose() { @Nullable @Override public VRPose getWorldRenderPose() { - if (!isVrActive()) { + if (!isVRActive()) { return null; } return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_render.asVRPose(); @@ -89,7 +87,7 @@ public void triggerHapticPulse(int controllerNum, float duration, float frequenc if (amplitude < 0F || amplitude > 1F) { throw new IllegalArgumentException("The amplitude of a haptic pulse must be between 0 and 1."); } - if (isVrActive() && !isSeated()) { + if (isVRActive() && !isSeated()) { ClientDataHolderVR.getInstance().vr.triggerHapticPulse( ControllerType.values()[controllerNum], duration, @@ -111,18 +109,18 @@ public boolean isLeftHanded() { } @Override - public boolean isVrInitialized() { + public boolean isVRInitialized() { return VRState.VR_INITIALIZED; } @Override - public boolean isVrActive() { + public boolean isVRActive() { return VRState.VR_RUNNING; } @Override public float getWorldScale() { - if (isVrActive()) { + if (isVRActive()) { return ClientDataHolderVR.getInstance().vrPlayer.worldScale; } else { return 1f; @@ -137,7 +135,7 @@ public void registerTracker(Tracker tracker) { @Nullable @Override public VRBodyPartHistory getHistoricalVRHMDPoses() { - if (!isVrActive()) { + if (!isVRActive()) { return null; } return this.hmdHistory; @@ -148,7 +146,7 @@ public VRBodyPartHistory getHistoricalVRHMDPoses() { public VRBodyPartHistory getHistoricalVRControllerPoses(int controller) { if (controller != 0 && controller != 1) { throw new IllegalArgumentException("Historical VR controller data only available for controllers 0 and 1."); - } else if (!isVrActive()) { + } else if (!isVRActive()) { return null; } return controller == 0 ? this.c0History : this.c1History; @@ -156,7 +154,7 @@ public VRBodyPartHistory getHistoricalVRControllerPoses(int controller) { @Override public boolean setKeyboardState(boolean isNowOpen) { - if (isVrActive()) { + if (isVRActive()) { return KeyboardHandler.setOverlayShowing(isNowOpen); } return false; From 562a193121229b92c81a115b55d84c14bb4c8d33 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Mon, 13 Jan 2025 10:51:41 -0500 Subject: [PATCH 08/33] Migrate History to VRPoseHistory --- .../api/client/VivecraftClientAPI.java | 54 +-------- ...odyPartHistory.java => VRPoseHistory.java} | 58 +++++----- .../api_impl/VivecraftClientAPIImpl.java | 37 ++---- .../api_impl/data/VRBodyPartHistoryImpl.java | 104 ----------------- .../api_impl/data/VRPoseHistoryImpl.java | 109 ++++++++++++++++++ 5 files changed, 153 insertions(+), 209 deletions(-) rename common/src/main/java/org/vivecraft/api/client/data/{VRBodyPartHistory.java => VRPoseHistory.java} (55%) delete mode 100644 common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java create mode 100644 common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 01ebd100a..30a36d224 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -1,7 +1,6 @@ package org.vivecraft.api.client; -import net.minecraft.world.InteractionHand; -import org.vivecraft.api.client.data.VRBodyPartHistory; +import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.VRPose; import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; @@ -133,57 +132,12 @@ default void triggerHapticPulse(int controllerNum, float duration) { float getWorldScale(); /** - * Returns the history of VR poses for the player for the HMD. Will return null if the player isn't - * in VR. + * Returns the history of VR poses for the player. Will return null if the player isn't in VR. * - * @return The historical VR data for the player's HMD, or null if the player isn't in VR. + * @return The history of VR poses for the player, or null if the player isn't in VR. */ @Nullable - VRBodyPartHistory getHistoricalVRHMDPoses(); - - /** - * Returns the history of VR poses for the player for a controller. Will return null if the player isn't - * in VR. - * - * @param controller The controller number to get, with 0 being the primary controller. - * @return The historical VR data for the player's controller, or null if the player isn't in VR. - */ - @Nullable - VRBodyPartHistory getHistoricalVRControllerPoses(int controller); - - /** - * Returns the history of VR poses for the player for a controller. Will return null if the player isn't - * in VR. - * - * @param hand The hand to get controller history for. - * @return The historical VR data for the player's controller, or null if the player isn't in VR. - */ - @Nullable - default VRBodyPartHistory getHistoricalVRControllerPoses(InteractionHand hand) { - return getHistoricalVRControllerPoses(hand.ordinal()); - } - - /** - * Returns the history of VR poses for the player for the primary controller. Will return null if the - * player isn't in VR. - * - * @return The historical VR data for the player's primary controller, or null if the player isn't in VR. - */ - @Nullable - default VRBodyPartHistory getHistoricalVRController0Poses() { - return getHistoricalVRControllerPoses(0); - } - - /** - * Returns the history of VR poses for the player for the secondary controller. Will return null if the - * player isn't in VR. - * - * @return The historical VR data for the player's secondary controller, or null if the player isn't in VR. - */ - @Nullable - default VRBodyPartHistory getHistoricalVRController1Poses() { - return getHistoricalVRControllerPoses(1); - } + VRPoseHistory getHistoricalVRPoses(); /** * Opens or closes Vivecraft's keyboard. Will fail silently if the user isn't in VR or if the keyboard's new state diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRBodyPartHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java similarity index 55% rename from common/src/main/java/org/vivecraft/api/client/data/VRBodyPartHistory.java rename to common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java index 60d681693..3a48202a3 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRBodyPartHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -1,18 +1,15 @@ package org.vivecraft.api.client.data; import net.minecraft.world.phys.Vec3; -import org.vivecraft.api.data.VRBodyPart; +import org.vivecraft.api.data.VRPose; import java.util.List; -/** - * Represents historical {@link VRBodyPart}s associated with a player. - */ -public interface VRBodyPartHistory { +public interface VRPoseHistory { /** - * The maximum amount of ticks back data is held for. - * It is only guaranteed that historical data does not go beyond this number of ticks back. Functions do not + * The maximum amount of ticks back poses are held for. + * It is only guaranteed that the pose history does not go beyond this number of ticks back. Functions do not * guarantee that they will reference this many ticks, as, for example, this amount of ticks may not have gone * by for the player this history represents. * Passing a value larger than this number to any methods below in their maxTicksBack or ticksBack parameters @@ -21,75 +18,80 @@ public interface VRBodyPartHistory { int MAX_TICKS_BACK = 20; /** - * @return The amount of ticks worth of history being held. The number returned by this methodwill never be higher - * than {@link VRBodyPartHistory#MAX_TICKS_BACK}, however can be lower than it. + * @return The amount of ticks worth of history being held. The number returned by this method will never be higher + * than {@link VRPoseHistory#MAX_TICKS_BACK}, however can be lower than it. */ int ticksOfHistory(); /** - * Gets a raw list of {@link VRBodyPart} instances, with index 0 representing the least recent pose known. + * Gets a raw list of {@link VRPose} instances, with index 0 representing the least recent pose known. * - * @return The aforementioned list of {@link VRBodyPart} instances. + * @return The aforementioned list of {@link VRPose} instances. */ - List getAllHistoricalData() throws IllegalArgumentException; + List getAllHistoricalData() throws IllegalArgumentException; /** - * Gets the historical data ticksBack ticks back. This will throw an IllegalStateException if the data cannot + * Gets the pose history {@code ticksBack} ticks back. This will throw an IllegalStateException if the data cannot * be retrieved due to not having enough history. * * @param ticksBack Ticks back to retrieve data. - * @return A {@link VRBodyPart} instance from index ticks ago. - * @throws IllegalStateException If ticksBack references a tick that there is not yet data for. + * @return A {@link VRPose} instance from index ticks ago. + * @throws IllegalStateException If ticksBack references a tick that there is not yet data for. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - VRBodyPart getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; + VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; /** - * Gets the net movement between the most recent data in this instance and the oldest position that can be - * retrieved, going no farther back than maxTicksBack. + * Gets the net movement between the most recent pose in this instance and the oldest position that can be + * retrieved, going no farther back than {@code maxTicksBack}. * + * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. * @param maxTicksBack The maximum amount of ticks back to compare the most recent data with. * @return The aforementioned net movement. Note that this will return zero change on all axes if only zero ticks * can be looked back. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - Vec3 netMovement(int maxTicksBack) throws IllegalArgumentException; + Vec3 netMovement(int deviceNum, int maxTicksBack) throws IllegalArgumentException; /** - * Gets the average velocity in blocks/tick between the most recent data in this instance and the oldest position - * that can be retrieved, going no farther back than maxTicksBack. + * Gets the average velocity in blocks/tick between the most recent pose in this instance and the oldest position + * that can be retrieved, going no farther back than {@code maxTicksBack}. * + * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. * @return The aforementioned average velocity on each axis. Note that this will return zero velocity on all axes * if only zero ticks can be looked back. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - Vec3 averageVelocity(int maxTicksBack) throws IllegalArgumentException; + Vec3 averageVelocity(int deviceNum, int maxTicksBack) throws IllegalArgumentException; /** - * Gets the average speed in blocks/tick between the most recent data in this instance and the oldest position - * that can be retrieved, going no farther back than maxTicksBack. + * Gets the average speed in blocks/tick between the most recent pose in this instance and the oldest position + * that can be retrieved, going no farther back than {@code maxTicksBack}. * + * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. * @param maxTicksBack The maximum amount of ticks back to calculate speed with. * @return The aforementioned average speed on each axis. Note that this will return zero speed if only zero ticks * can be looked back. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - default double averageSpeed(int maxTicksBack) throws IllegalArgumentException { - Vec3 averageVelocity = averageVelocity(maxTicksBack); + default double averageSpeed(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + Vec3 averageVelocity = averageVelocity(deviceNum, maxTicksBack); return Math.sqrt(averageVelocity.x() * averageVelocity.x() + averageVelocity.y() * averageVelocity.y() + averageVelocity.z() * averageVelocity.z()); } /** - * Gets the average position between the most recent data in this instance and the oldest position that can be + * Gets the average position between the most recent pose in this instance and the oldest position that can be * retrieved, going no farther back than maxTicksBack. * + * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. * @return The aforementioned average position. Note that this will return the current position if only zero ticks * can be looked back. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException; + Vec3 averagePosition(int deviceNum, int maxTicksBack) throws IllegalArgumentException; + } diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java index c23263540..478d0c763 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java @@ -2,10 +2,10 @@ import org.jetbrains.annotations.Nullable; import org.vivecraft.api.client.Tracker; -import org.vivecraft.api.client.data.VRBodyPartHistory; import org.vivecraft.api.client.VivecraftClientAPI; +import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.VRPose; -import org.vivecraft.client.api_impl.data.VRBodyPartHistoryImpl; +import org.vivecraft.client.api_impl.data.VRPoseHistoryImpl; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; @@ -15,23 +15,17 @@ public final class VivecraftClientAPIImpl implements VivecraftClientAPI { public static final VivecraftClientAPIImpl INSTANCE = new VivecraftClientAPIImpl(); - private final VRBodyPartHistoryImpl hmdHistory = new VRBodyPartHistoryImpl(); - private VRBodyPartHistoryImpl c0History = new VRBodyPartHistoryImpl(); - private VRBodyPartHistoryImpl c1History = new VRBodyPartHistoryImpl(); + private final VRPoseHistoryImpl poseHistory = new VRPoseHistoryImpl(); private VivecraftClientAPIImpl() { } public void clearHistories() { - this.hmdHistory.clear(); - this.c0History.clear(); - this.c1History.clear(); + this.poseHistory.clear(); } - public void addPosesToHistory(VRPose data) { - this.hmdHistory.addPose(data.getHMD()); - this.c0History.addPose(data.getController0()); - this.c1History.addPose(data.getController1()); + public void addPosesToHistory(VRPose pose) { + this.poseHistory.addPose(pose); } @Nullable @@ -128,28 +122,17 @@ public float getWorldScale() { } @Override - public void registerTracker(Tracker tracker) { - ClientDataHolderVR.getInstance().registerTracker(tracker); - } - @Nullable - @Override - public VRBodyPartHistory getHistoricalVRHMDPoses() { + public VRPoseHistory getHistoricalVRPoses() { if (!isVRActive()) { return null; } - return this.hmdHistory; + return this.poseHistory; } - @Nullable @Override - public VRBodyPartHistory getHistoricalVRControllerPoses(int controller) { - if (controller != 0 && controller != 1) { - throw new IllegalArgumentException("Historical VR controller data only available for controllers 0 and 1."); - } else if (!isVRActive()) { - return null; - } - return controller == 0 ? this.c0History : this.c1History; + public void registerTracker(Tracker tracker) { + ClientDataHolderVR.getInstance().registerTracker(tracker); } @Override diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java deleted file mode 100644 index 79f722e62..000000000 --- a/common/src/main/java/org/vivecraft/client/api_impl/data/VRBodyPartHistoryImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.vivecraft.client.api_impl.data; - -import net.minecraft.world.phys.Vec3; -import org.vivecraft.api.client.data.VRBodyPartHistory; -import org.vivecraft.api.data.VRBodyPart; - -import java.util.*; - -public class VRBodyPartHistoryImpl implements VRBodyPartHistory { - - private final LinkedList dataQueue = new LinkedList<>(); - - public VRBodyPartHistoryImpl() { - } - - public void addPose(VRBodyPart pose) { - this.dataQueue.addFirst(pose); - if (this.dataQueue.size() > VRBodyPartHistory.MAX_TICKS_BACK) { - this.dataQueue.removeLast(); - } - } - - public void clear() { - this.dataQueue.clear(); - } - - @Override - public int ticksOfHistory() { - return this.dataQueue.size(); - } - - @Override - public List getAllHistoricalData() { - return new ArrayList<>(this.dataQueue); - } - - @Override - public VRBodyPart getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException { - checkTicksBack(ticksBack); - if (this.dataQueue.size() <= ticksBack) { - throw new IllegalStateException("Cannot retrieve data from " + ticksBack + " ticks ago, when there is " + - "only data for up to " + (this.dataQueue.size() - 1) + " ticks ago."); - } - return this.dataQueue.get(ticksBack); - } - - @Override - public Vec3 netMovement(int maxTicksBack) throws IllegalArgumentException { - checkTicksBack(maxTicksBack); - Vec3 current = this.dataQueue.getLast().getPos(); - Vec3 old = getOldPose(maxTicksBack).getPos(); - return current.subtract(old); - } - - @Override - public Vec3 averageVelocity(int maxTicksBack) throws IllegalArgumentException { - checkTicksBack(maxTicksBack); - Vec3 current = this.dataQueue.getLast().getPos(); - Vec3 old = getOldPose(maxTicksBack).getPos(); - return current.subtract(old).scale(1d / getNumTicksBack(maxTicksBack)); - } - - @Override - public Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException { - checkTicksBack(maxTicksBack); - int iters = getNumTicksBack(maxTicksBack); - ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); - Vec3 avg = this.dataQueue.getLast().getPos(); - int i = iters; - while (i > 0) { - avg = avg.add(iterator.previous().getPos()); - i--; - } - return avg.scale(1d / (iters + 1)); - } - - private void checkTicksBack(int ticksBack) { - if (ticksBack < 0 || ticksBack > VRBodyPartHistory.MAX_TICKS_BACK) { - throw new IllegalArgumentException("Value must be between 0 and " + VRBodyPartHistory.MAX_TICKS_BACK + "."); - } - } - - private VRBodyPart getOldPose(int maxTicksBack) { - if (this.dataQueue.size() <= maxTicksBack) { - return this.dataQueue.getFirst(); - } else { - return this.dataQueue.get(this.dataQueue.size() - maxTicksBack - 1); - } - } - - /** - * Converts maxTicksBack to the actual maximum number of ticks we can go back. - * - * @param maxTicksBack The maximum number of ticks to attempt to go back. - * @return The actual number of ticks to go back by. - */ - private int getNumTicksBack(int maxTicksBack) { - if (this.dataQueue.size() <= maxTicksBack) { - return this.dataQueue.size() - 1; - } else { - return maxTicksBack; - } - } -} diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java new file mode 100644 index 000000000..dbb65d96b --- /dev/null +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java @@ -0,0 +1,109 @@ +package org.vivecraft.client.api_impl.data; + +import net.minecraft.world.phys.Vec3; +import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.data.VRBodyPart; +import org.vivecraft.api.data.VRPose; + +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +public class VRPoseHistoryImpl implements VRPoseHistory { + + private final LinkedList dataQueue = new LinkedList<>(); + + public VRPoseHistoryImpl() { + } + + public void addPose(VRPose pose) { + this.dataQueue.addFirst(pose); + if (this.dataQueue.size() > VRPoseHistory.MAX_TICKS_BACK) { + this.dataQueue.removeLast(); + } + } + + public void clear() { + this.dataQueue.clear(); + } + + @Override + public int ticksOfHistory() { + return this.dataQueue.size(); + } + + @Override + public List getAllHistoricalData() throws IllegalArgumentException { + return List.copyOf(this.dataQueue); + } + + @Override + public VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException { + checkTicksBack(ticksBack); + if (this.dataQueue.size() <= ticksBack) { + throw new IllegalStateException("Cannot retrieve data from " + ticksBack + " ticks ago, when there is " + + "only data for up to " + (this.dataQueue.size() - 1) + " ticks ago."); + } + return this.dataQueue.get(ticksBack); + } + + @Override + public Vec3 netMovement(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + checkTicksBack(maxTicksBack); + Vec3 current = getPart(this.dataQueue.getLast(), deviceNum).getPos(); + Vec3 old = getPart(getOldPose(maxTicksBack), deviceNum).getPos(); + return current.subtract(old); + } + + @Override + public Vec3 averageVelocity(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + checkTicksBack(maxTicksBack); + Vec3 current = getPart(this.dataQueue.getLast(), deviceNum).getPos(); + Vec3 old = getPart(getOldPose(maxTicksBack), deviceNum).getPos(); + return current.subtract(old).scale(1d / getNumTicksBack(maxTicksBack)); + } + + @Override + public Vec3 averagePosition(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + checkTicksBack(maxTicksBack); + int iters = getNumTicksBack(maxTicksBack); + ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); + Vec3 avg = getPart(this.dataQueue.getLast(), deviceNum).getPos(); + int i = iters; + while (i > 0) { + avg = avg.add(getPart(iterator.previous(), deviceNum).getPos()); + i--; + } + return avg.scale(1d / (iters + 1)); + } + + private void checkTicksBack(int ticksBack) { + if (ticksBack < 0 || ticksBack > VRPoseHistory.MAX_TICKS_BACK) { + throw new IllegalArgumentException("Value must be between 0 and " + VRPoseHistory.MAX_TICKS_BACK + "."); + } + } + + private VRPose getOldPose(int maxTicksBack) { + if (this.dataQueue.size() <= maxTicksBack) { + return this.dataQueue.getFirst(); + } else { + return this.dataQueue.get(this.dataQueue.size() - maxTicksBack - 1); + } + } + + private VRBodyPart getPart(VRPose pose, int deviceNum) { + return switch (deviceNum) { + case -1 -> pose.getHMD(); + case 0, 1 -> pose.getController(deviceNum); + default -> throw new IllegalStateException("Invalid deviceNum: " + deviceNum); + }; + } + + private int getNumTicksBack(int maxTicksBack) { + if (this.dataQueue.size() <= maxTicksBack) { + return this.dataQueue.size() - 1; + } else { + return maxTicksBack; + } + } +} From 4a5d9fc98c96c587f187db548fd3995945d4799d Mon Sep 17 00:00:00 2001 From: hammy275 Date: Mon, 13 Jan 2025 13:11:29 -0500 Subject: [PATCH 09/33] FBT Additions (untested) --- .../api/client/VivecraftClientAPI.java | 6 ++ .../api/client/data/VRPoseHistory.java | 34 ++++++---- .../java/org/vivecraft/api/data/FBTMode.java | 28 ++++++++ .../org/vivecraft/api/data/VRBodyPart.java | 66 ++++++++++--------- .../vivecraft/api/data/VRBodyPartData.java | 41 ++++++++++++ .../java/org/vivecraft/api/data/VRPose.java | 37 +++++++++-- .../org/vivecraft/client/ClientVRPlayers.java | 31 +++++++-- .../api_impl/VivecraftClientAPIImpl.java | 10 +++ .../api_impl/data/VRPoseHistoryImpl.java | 60 ++++++++++++----- .../client/render/VRPlayerModel.java | 2 +- .../render/VRPlayerModel_WithArmsLegs.java | 2 +- .../java/org/vivecraft/client_vr/VRData.java | 26 ++++++-- .../gameplay/trackers/SwingTracker.java | 5 +- .../client_vr/provider/nullvr/NullVR.java | 2 +- .../render/helpers/DebugRenderHelper.java | 2 +- ...yPartImpl.java => VRBodyPartDataImpl.java} | 6 +- .../common/api_impl/data/VRPoseImpl.java | 59 ++++++++--------- .../vivecraft/common/network/BodyPart.java | 2 + .../org/vivecraft/common/network/FBTMode.java | 16 ----- .../org/vivecraft/common/network/Pose.java | 16 +++++ .../common/network/VrPlayerState.java | 30 +++++++++ .../packet/c2s/ActiveBodyPartPayloadC2S.java | 2 +- .../vivecraft/server/ServerNetworking.java | 2 +- .../vivecraft/server/ServerVivePlayer.java | 24 ++----- 24 files changed, 351 insertions(+), 158 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/api/data/FBTMode.java create mode 100644 common/src/main/java/org/vivecraft/api/data/VRBodyPartData.java rename common/src/main/java/org/vivecraft/common/api_impl/data/{VRBodyPartImpl.java => VRBodyPartDataImpl.java} (86%) delete mode 100644 common/src/main/java/org/vivecraft/common/network/FBTMode.java diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 30a36d224..88a45a9fe 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -1,6 +1,7 @@ package org.vivecraft.api.client; import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.api.data.VRPose; import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; @@ -116,6 +117,11 @@ default void triggerHapticPulse(int controllerNum, float duration) { */ boolean isLeftHanded(); + /** + * @return The full-body tracking mode currently in-use or some default value if the local player is not in VR. + */ + FBTMode getFBTMode(); + /** * @return Whether VR support is initialized. */ diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java index 3a48202a3..d6fc640c2 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -1,8 +1,10 @@ package org.vivecraft.api.client.data; import net.minecraft.world.phys.Vec3; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.api.data.VRPose; +import javax.annotation.Nullable; import java.util.List; public interface VRPoseHistory { @@ -45,38 +47,43 @@ public interface VRPoseHistory { * Gets the net movement between the most recent pose in this instance and the oldest position that can be * retrieved, going no farther back than {@code maxTicksBack}. * - * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. + * @param bodyPart The body part to get the net movement for. * @param maxTicksBack The maximum amount of ticks back to compare the most recent data with. * @return The aforementioned net movement. Note that this will return zero change on all axes if only zero ticks - * can be looked back. + * can be looked back. Will be null if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - Vec3 netMovement(int deviceNum, int maxTicksBack) throws IllegalArgumentException; + @Nullable + Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; /** * Gets the average velocity in blocks/tick between the most recent pose in this instance and the oldest position * that can be retrieved, going no farther back than {@code maxTicksBack}. * - * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. + * @param bodyPart The body part to get the average velocity for. * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. * @return The aforementioned average velocity on each axis. Note that this will return zero velocity on all axes - * if only zero ticks can be looked back. + * if only zero ticks can be looked back. Will be null if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - Vec3 averageVelocity(int deviceNum, int maxTicksBack) throws IllegalArgumentException; + @Nullable + Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; /** * Gets the average speed in blocks/tick between the most recent pose in this instance and the oldest position * that can be retrieved, going no farther back than {@code maxTicksBack}. * - * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. + * @param bodyPart The body part to get the average speed for. * @param maxTicksBack The maximum amount of ticks back to calculate speed with. * @return The aforementioned average speed on each axis. Note that this will return zero speed if only zero ticks - * can be looked back. + * can be looked back. Will be 0 if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - default double averageSpeed(int deviceNum, int maxTicksBack) throws IllegalArgumentException { - Vec3 averageVelocity = averageVelocity(deviceNum, maxTicksBack); + default double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { + Vec3 averageVelocity = averageVelocity(bodyPart, maxTicksBack); + if (averageVelocity == null) { + return 0; + } return Math.sqrt(averageVelocity.x() * averageVelocity.x() + averageVelocity.y() * averageVelocity.y() + averageVelocity.z() * averageVelocity.z()); @@ -86,12 +93,13 @@ default double averageSpeed(int deviceNum, int maxTicksBack) throws IllegalArgum * Gets the average position between the most recent pose in this instance and the oldest position that can be * retrieved, going no farther back than maxTicksBack. * - * @param deviceNum The controller number, or -1 for the HMD, to get the net movement for. + * @param bodyPart The body part to get the average position for. * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. * @return The aforementioned average position. Note that this will return the current position if only zero ticks - * can be looked back. + * can be looked back. Will be null if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - Vec3 averagePosition(int deviceNum, int maxTicksBack) throws IllegalArgumentException; + @Nullable + Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; } diff --git a/common/src/main/java/org/vivecraft/api/data/FBTMode.java b/common/src/main/java/org/vivecraft/api/data/FBTMode.java new file mode 100644 index 000000000..4cad642fe --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/data/FBTMode.java @@ -0,0 +1,28 @@ +package org.vivecraft.api.data; + +/** + * The mode used for full-body tracking, denoting which body parts are being tracked. + */ +public enum FBTMode { + /** + * Only controllers are available. + */ + ARMS_ONLY, + /** + * Controller, waist and feet trackers are available. + */ + ARMS_LEGS, + /** + * Controller, waist, feet, elbow and knee trackers are available. + */ + WITH_JOINTS; + + /** + * Whether the provided body part is available in this full-body tracking mode. + * @param bodyPart The body part to see if data is available for in this mode. + * @return Whether the provided body part is available in this mode. + */ + public boolean bodyPartAvailable(VRBodyPart bodyPart) { + return bodyPart.availableInMode(this); + } +} diff --git a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java index ee71a2ee3..8ad9e3456 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java +++ b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java @@ -1,41 +1,47 @@ package org.vivecraft.api.data; -import net.minecraft.world.phys.Vec3; -import org.joml.Quaternionfc; - /** - * Represents the data for a body part, or a device usually tied to a body part in VR, such as the HMD or a - * controller. + * The device tracking a specific body part. */ -public interface VRBodyPart { - - /** - * @return The position of the body part in Minecraft world coordinates. - */ - Vec3 getPos(); - - /** - * @return The rotation of the body part. - */ - Vec3 getRot(); - - /** - * @return The pitch of the body part in radians. - */ - double getPitch(); - - /** - * @return The yaw of the body part in radians. - */ - double getYaw(); +public enum VRBodyPart { + HEAD, + MAIN_HAND, + OFF_HAND, + RIGHT_FOOT, + LEFT_FOOT, + WAIST, + RIGHT_KNEE, + LEFT_KNEE, + RIGHT_ELBOW, + LEFT_ELBOW; /** - * @return The roll of the body part in radians. + * @return The opposite body part to this one, or the same body part if it has no opposite. */ - double getRoll(); + public VRBodyPart opposite() { + return switch (this) { + case MAIN_HAND -> OFF_HAND; + case OFF_HAND -> MAIN_HAND; + case RIGHT_FOOT -> LEFT_FOOT; + case LEFT_FOOT -> RIGHT_FOOT; + case RIGHT_KNEE -> LEFT_KNEE; + case LEFT_KNEE -> RIGHT_KNEE; + case RIGHT_ELBOW -> LEFT_ELBOW; + case LEFT_ELBOW -> RIGHT_ELBOW; + default -> this; + }; + } /** - * @return The quaternion representing the rotation of the body part. + * Whether this body part type is available in the provided full-body tracking mode. + * @param mode The full-body tracking mode to check. + * @return Whether this body part has available data in the provided mode. */ - Quaternionfc getQuaternion(); + public boolean availableInMode(FBTMode mode) { + return switch (this) { + case HEAD, MAIN_HAND, OFF_HAND -> true; + case RIGHT_FOOT, LEFT_FOOT, WAIST -> mode != FBTMode.ARMS_ONLY; + case RIGHT_KNEE, LEFT_KNEE, RIGHT_ELBOW, LEFT_ELBOW -> mode == FBTMode.WITH_JOINTS; + }; + } } diff --git a/common/src/main/java/org/vivecraft/api/data/VRBodyPartData.java b/common/src/main/java/org/vivecraft/api/data/VRBodyPartData.java new file mode 100644 index 000000000..db45bd815 --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/data/VRBodyPartData.java @@ -0,0 +1,41 @@ +package org.vivecraft.api.data; + +import net.minecraft.world.phys.Vec3; +import org.joml.Quaternionfc; + +/** + * Represents the data for a body part, or a device usually tied to a body part in VR, such as the HMD or a + * controller. + */ +public interface VRBodyPartData { + + /** + * @return The position of the body part in Minecraft world coordinates. + */ + Vec3 getPos(); + + /** + * @return The rotation of the body part. + */ + Vec3 getRot(); + + /** + * @return The pitch of the body part in radians. + */ + double getPitch(); + + /** + * @return The yaw of the body part in radians. + */ + double getYaw(); + + /** + * @return The roll of the body part in radians. + */ + double getRoll(); + + /** + * @return The quaternion representing the rotation of the body part. + */ + Quaternionfc getQuaternion(); +} diff --git a/common/src/main/java/org/vivecraft/api/data/VRPose.java b/common/src/main/java/org/vivecraft/api/data/VRPose.java index 5b0f21ae7..6047fcd0d 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRPose.java +++ b/common/src/main/java/org/vivecraft/api/data/VRPose.java @@ -2,6 +2,8 @@ import net.minecraft.world.InteractionHand; +import javax.annotation.Nullable; + /** * Represents the pose of the VR player. In other words, the position and rotation data of all tracked body parts of * the VR player. @@ -9,17 +11,33 @@ public interface VRPose { /** - * @return Pose data for the HMD. + * Gets the pose data for a body part. + * + * @param vrBodyPart The body part to get the pose data for. + * @return The specified body part's pose data, or null if that body part is not being tracked. + */ + @Nullable + VRBodyPartData getBodyPartData(VRBodyPart vrBodyPart); + + /** + * @return Body part pose data for the HMD. */ - VRBodyPart getHMD(); + default VRBodyPartData getHMD() { + return getBodyPartData(VRBodyPart.HEAD); + } /** - * Gets the pose data for a given controller. + * Gets the body part data for a given controller. * * @param controller The controller number to get, with 0 being the primary controller. * @return The specified controller's pose data. */ - VRBodyPart getController(int controller); + default VRBodyPartData getController(int controller) { + if (controller != 0 && controller != 1) { + throw new IllegalArgumentException("Controller number must be controller 0 or controller 1."); + } + return controller == 0 ? getBodyPartData(VRBodyPart.MAIN_HAND) : getBodyPartData(VRBodyPart.OFF_HAND); + } /** * @return Whether the player is currently in seated mode. @@ -31,13 +49,18 @@ public interface VRPose { */ boolean isLeftHanded(); + /** + * @return The full-body tracking mode currently in-use. + */ + FBTMode getFBTMode(); + /** * Gets the pose for a given controller. * * @param hand The interaction hand to get controller data for. * @return The specified controller's pose data. */ - default VRBodyPart getController(InteractionHand hand) { + default VRBodyPartData getController(InteractionHand hand) { return getController(hand.ordinal()); } @@ -46,7 +69,7 @@ default VRBodyPart getController(InteractionHand hand) { * * @return The main controller's pose data. */ - default VRBodyPart getController0() { + default VRBodyPartData getController0() { return getController(0); } @@ -55,7 +78,7 @@ default VRBodyPart getController0() { * * @return The main controller's pose data. */ - default VRBodyPart getController1() { + default VRBodyPartData getController1() { return getController(1); } } diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index 38a0a595b..4b7047310 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -13,6 +13,7 @@ import org.joml.Quaternionfc; import org.joml.Vector3f; import org.joml.Vector3fc; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.api.data.VRPose; import org.vivecraft.client.extensions.SparkParticleExtension; import org.vivecraft.client.utils.ClientUtils; @@ -27,8 +28,8 @@ import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassType; import org.vivecraft.common.api_impl.data.VRPoseImpl; -import org.vivecraft.common.api_impl.data.VRBodyPartImpl; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.common.api_impl.data.VRBodyPartDataImpl; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.common.utils.MathUtils; @@ -573,15 +574,33 @@ public float getBodyYawRad() { public VRPose asVRPose() { return new VRPoseImpl( - new VRBodyPartImpl(fromVector3fc(this.headPos), fromVector3fc(this.headRot), this.headQuat), - new VRBodyPartImpl(fromVector3fc(this.mainHandPos), fromVector3fc(this.mainHandRot), this.mainHandQuat), - new VRBodyPartImpl(fromVector3fc(this.offHandPos), fromVector3fc(this.offHandPos), this.offHandQuat), + makeBodyPartData(this.headPos, this.headRot, this.headQuat), + makeBodyPartData(this.mainHandPos, this.mainHandRot, this.mainHandQuat), + makeBodyPartData(this.offHandPos, this.offHandRot, this.offHandQuat), + makeBodyPartData(this.rightFootPos, this.rightFootQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), + makeBodyPartData(this.leftFootPos, this.leftFootQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), + makeBodyPartData(this.waistPos, this.waistQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), + makeBodyPartData(this.rightKneePos, this.rightKneeQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), + makeBodyPartData(this.leftKneePos, this.leftKneeQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), + makeBodyPartData(this.rightElbowPos, this.rightElbowQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), + makeBodyPartData(this.leftElbowPos, this.leftElbowQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), this.seated, - this.leftHanded + this.leftHanded, + this.fbtMode ); } } + private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Vector3fc rot, Quaternionfc quat) { + return new VRBodyPartDataImpl(fromVector3fc(pos), fromVector3fc(rot), quat); + } + + private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Quaternionfc quat, boolean partAvailable) { + return partAvailable + ? new VRBodyPartDataImpl(fromVector3fc(pos), fromVector3fc(quat.transform(MathUtils.BACK, new Vector3f())), quat) + : null; + } + private static Vec3 fromVector3fc(Vector3fc vec) { return new Vec3(vec.x(), vec.y(), vec.z()); } diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java index 478d0c763..a8ef7881b 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java @@ -4,6 +4,7 @@ import org.vivecraft.api.client.Tracker; import org.vivecraft.api.client.VivecraftClientAPI; import org.vivecraft.api.client.data.VRPoseHistory; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.api.data.VRPose; import org.vivecraft.client.api_impl.data.VRPoseHistoryImpl; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -102,6 +103,15 @@ public boolean isLeftHanded() { return ClientDataHolderVR.getInstance().vrSettings.reverseHands; } + @Override + public FBTMode getFBTMode() { + // Need to check if VR is running, not just initialized, since the VR player is set after initialization + if (isVRActive()) { + return FBTMode.ARMS_ONLY; + } + return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_pre.fbtMode; + } + @Override public boolean isVRInitialized() { return VRState.VR_INITIALIZED; diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java index dbb65d96b..a02a66979 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java @@ -3,6 +3,7 @@ import net.minecraft.world.phys.Vec3; import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.VRBodyPart; +import org.vivecraft.api.data.VRBodyPartData; import org.vivecraft.api.data.VRPose; import java.util.LinkedList; @@ -48,30 +49,57 @@ public VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, } @Override - public Vec3 netMovement(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + public Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { + checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); - Vec3 current = getPart(this.dataQueue.getLast(), deviceNum).getPos(); - Vec3 old = getPart(getOldPose(maxTicksBack), deviceNum).getPos(); + VRBodyPartData currentData = this.dataQueue.getLast().getBodyPartData(bodyPart); + if (currentData == null) { + return null; + } + Vec3 current = currentData.getPos(); + VRBodyPartData oldData = getOldPose(maxTicksBack).getBodyPartData(bodyPart); + if (oldData == null) { + return null; + } + Vec3 old = oldData.getPos(); return current.subtract(old); } @Override - public Vec3 averageVelocity(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + public Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { + checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); - Vec3 current = getPart(this.dataQueue.getLast(), deviceNum).getPos(); - Vec3 old = getPart(getOldPose(maxTicksBack), deviceNum).getPos(); + VRBodyPartData currentData = this.dataQueue.getLast().getBodyPartData(bodyPart); + if (currentData == null) { + return null; + } + Vec3 current = currentData.getPos(); + VRBodyPartData oldData = getOldPose(maxTicksBack).getBodyPartData(bodyPart); + if (oldData == null) { + return null; + } + Vec3 old = oldData.getPos(); return current.subtract(old).scale(1d / getNumTicksBack(maxTicksBack)); } @Override - public Vec3 averagePosition(int deviceNum, int maxTicksBack) throws IllegalArgumentException { + public Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { + checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); int iters = getNumTicksBack(maxTicksBack); + VRBodyPartData currentData = this.dataQueue.getLast().getBodyPartData(bodyPart); + if (currentData == null) { + return null; + } ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); - Vec3 avg = getPart(this.dataQueue.getLast(), deviceNum).getPos(); + Vec3 avg = currentData.getPos(); int i = iters; while (i > 0) { - avg = avg.add(getPart(iterator.previous(), deviceNum).getPos()); + VRBodyPartData oldData = iterator.previous().getBodyPartData(bodyPart); + if (oldData == null) { + break; + } + avg = avg.add(oldData.getPos()); i--; } return avg.scale(1d / (iters + 1)); @@ -83,6 +111,12 @@ private void checkTicksBack(int ticksBack) { } } + private void checkPartNonNull(VRBodyPart bodyPart) { + if (bodyPart == null) { + throw new IllegalArgumentException("Cannot get data for a null body part!"); + } + } + private VRPose getOldPose(int maxTicksBack) { if (this.dataQueue.size() <= maxTicksBack) { return this.dataQueue.getFirst(); @@ -91,14 +125,6 @@ private VRPose getOldPose(int maxTicksBack) { } } - private VRBodyPart getPart(VRPose pose, int deviceNum) { - return switch (deviceNum) { - case -1 -> pose.getHMD(); - case 0, 1 -> pose.getController(deviceNum); - default -> throw new IllegalStateException("Invalid deviceNum: " + deviceNum); - }; - } - private int getNumTicksBack(int maxTicksBack) { if (this.dataQueue.size() <= maxTicksBack) { return this.dataQueue.size() - 1; diff --git a/common/src/main/java/org/vivecraft/client/render/VRPlayerModel.java b/common/src/main/java/org/vivecraft/client/render/VRPlayerModel.java index 5714657a6..16a62d4fe 100644 --- a/common/src/main/java/org/vivecraft/client/render/VRPlayerModel.java +++ b/common/src/main/java/org/vivecraft/client/render/VRPlayerModel.java @@ -27,7 +27,7 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.GuiHandler; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.mod_compat_vr.immersiveportals.ImmersivePortalsHelper; import org.vivecraft.mod_compat_vr.mca.MCAHelper; diff --git a/common/src/main/java/org/vivecraft/client/render/VRPlayerModel_WithArmsLegs.java b/common/src/main/java/org/vivecraft/client/render/VRPlayerModel_WithArmsLegs.java index 078a2faeb..3d557e9ef 100644 --- a/common/src/main/java/org/vivecraft/client/render/VRPlayerModel_WithArmsLegs.java +++ b/common/src/main/java/org/vivecraft/client/render/VRPlayerModel_WithArmsLegs.java @@ -17,7 +17,7 @@ import org.vivecraft.client.render.models.FeetModel; import org.vivecraft.client.utils.ModelUtils; import org.vivecraft.client_vr.ClientDataHolderVR; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.utils.MathUtils; public class VRPlayerModel_WithArmsLegs extends VRPlayerModel_WithArms implements FeetModel { diff --git a/common/src/main/java/org/vivecraft/client_vr/VRData.java b/common/src/main/java/org/vivecraft/client_vr/VRData.java index 5e07f0547..af0990949 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRData.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRData.java @@ -4,21 +4,22 @@ import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; import org.joml.*; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.api.data.VRPose; import org.vivecraft.client.ClientVRPlayers; import org.vivecraft.client.gui.screens.FBTCalibrationScreen; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.utils.MathUtils; import javax.annotation.Nullable; import java.lang.Math; import org.joml.Quaternionf; -import org.vivecraft.api.data.VRBodyPart; +import org.vivecraft.api.data.VRBodyPartData; import org.vivecraft.common.api_impl.data.VRPoseImpl; -import org.vivecraft.common.api_impl.data.VRBodyPartImpl; +import org.vivecraft.common.api_impl.data.VRBodyPartDataImpl; public class VRData { // headset center @@ -371,11 +372,24 @@ public VRPose asVRPose() { this.hmd.asVRBodyPart(), this.c0.asVRBodyPart(), this.c1.asVRBodyPart(), + getDataIfAvailable(this.foot_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), + getDataIfAvailable(this.foot_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), + getDataIfAvailable(this.waist, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), + getDataIfAvailable(this.knee_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), + getDataIfAvailable(this.knee_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), + getDataIfAvailable(this.elbow_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), + getDataIfAvailable(this.elbow_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), ClientDataHolderVR.getInstance().vrSettings.seated, - ClientDataHolderVR.getInstance().vrSettings.reverseHands + ClientDataHolderVR.getInstance().vrSettings.reverseHands, + this.fbtMode ); } + @Nullable + private static VRBodyPartData getDataIfAvailable(VRDevicePose pose, boolean partAvailable) { + return partAvailable ? pose.asVRBodyPart() : null; + } + @Override public String toString() { return """ @@ -520,10 +534,10 @@ public Matrix4f getMatrix() { return new Matrix4f().rotationY(VRData.this.rotation_radians).mul(this.matrix); } - public VRBodyPart asVRBodyPart() { + public VRBodyPartData asVRBodyPart() { Quaternionf quat = new Quaternionf(); quat.setFromUnnormalized(getMatrix()); - return new VRBodyPartImpl( + return new VRBodyPartDataImpl( getPosition(), new Vec3(getDirection()), quat diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java index 2741b8fba..75479e563 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java @@ -32,12 +32,9 @@ import org.joml.Vector3f; import org.vivecraft.client.Xplat; import org.vivecraft.client.network.ClientNetworking; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.Vector3fHistory; -import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.network.BodyPart; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.BlockTags; 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 50d92301e..e6c4aa3cf 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 @@ -18,7 +18,7 @@ import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; import org.vivecraft.client_vr.render.MirrorNotification; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.utils.MathUtils; import java.lang.Math; diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/DebugRenderHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/DebugRenderHelper.java index 41efe7173..e3163f969 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/DebugRenderHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/DebugRenderHelper.java @@ -23,7 +23,7 @@ import org.vivecraft.client_vr.provider.DeviceSource; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.render.RenderPass; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.utils.MathUtils; import java.util.ArrayList; diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java similarity index 86% rename from common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java rename to common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java index fcdda5760..3d824ae1b 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java @@ -2,15 +2,15 @@ import net.minecraft.world.phys.Vec3; import org.joml.Quaternionfc; -import org.vivecraft.api.data.VRBodyPart; +import org.vivecraft.api.data.VRBodyPartData; -public class VRBodyPartImpl implements VRBodyPart { +public class VRBodyPartDataImpl implements VRBodyPartData { private final Vec3 pos; private final Vec3 rot; private final Quaternionfc quaternion; - public VRBodyPartImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) { + public VRBodyPartDataImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) { this.pos = pos; this.rot = rot; this.quaternion = quaternion; diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java index 71b402461..6ff26ab2e 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java @@ -1,45 +1,42 @@ package org.vivecraft.common.api_impl.data; -import org.vivecraft.api.data.VRPose; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.api.data.VRBodyPart; +import org.vivecraft.api.data.VRPose; +import org.vivecraft.api.data.VRBodyPartData; -public class VRPoseImpl implements VRPose { - - private final VRBodyPart hmd; - private final VRBodyPart c0; - private final VRBodyPart c1; - private final boolean isSeated; - private final boolean isLeftHanded; - - public VRPoseImpl(VRBodyPart hmd, VRBodyPart c0, VRBodyPart c1, boolean isSeated, boolean isLeftHanded) { - this.hmd = hmd; - this.c0 = c0; - this.c1 = c1; - this.isSeated = isSeated; - this.isLeftHanded = isLeftHanded; - } +import javax.annotation.Nullable; - @Override - public VRBodyPart getHMD() { - return this.hmd; - } +public record VRPoseImpl(VRBodyPartData hmd, VRBodyPartData c0, VRBodyPartData c1, + VRBodyPartData rightFoot, VRBodyPartData leftFoot, + VRBodyPartData waist, + VRBodyPartData rightKnee, VRBodyPartData leftKnee, + VRBodyPartData rightElbow, VRBodyPartData leftElbow, + boolean isSeated, boolean isLeftHanded, FBTMode fbtMode) implements VRPose { @Override - public VRBodyPart getController(int controller) { - if (controller != 0 && controller != 1) { - throw new IllegalArgumentException("Controller number must be controller 0 or controller 1."); + @Nullable + public VRBodyPartData getBodyPartData(VRBodyPart vrBodyPart) { + if (vrBodyPart == null) { + throw new IllegalArgumentException("Cannot get a null body part's data!"); } - return controller == 0 ? this.c0 : this.c1; - } - - @Override - public boolean isSeated() { - return this.isSeated; + return switch (vrBodyPart) { + case HEAD -> this.hmd; + case MAIN_HAND -> this.c0; + case OFF_HAND -> this.c1; + case RIGHT_FOOT -> this.rightFoot; + case LEFT_FOOT -> this.leftFoot; + case WAIST -> this.waist; + case RIGHT_KNEE -> this.rightKnee; + case LEFT_KNEE -> this.leftKnee; + case RIGHT_ELBOW -> this.rightElbow; + case LEFT_ELBOW -> this.leftElbow; + }; } @Override - public boolean isLeftHanded() { - return this.isLeftHanded; + public FBTMode getFBTMode() { + return this.fbtMode; } @Override 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 87f23f695..86670f413 100644 --- a/common/src/main/java/org/vivecraft/common/network/BodyPart.java +++ b/common/src/main/java/org/vivecraft/common/network/BodyPart.java @@ -1,5 +1,7 @@ package org.vivecraft.common.network; +import org.vivecraft.api.data.FBTMode; + public enum BodyPart { MAIN_HAND, OFF_HAND, diff --git a/common/src/main/java/org/vivecraft/common/network/FBTMode.java b/common/src/main/java/org/vivecraft/common/network/FBTMode.java deleted file mode 100644 index 52eb4259a..000000000 --- a/common/src/main/java/org/vivecraft/common/network/FBTMode.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.vivecraft.common.network; - -public enum FBTMode { - /** - * only controllers are available - */ - ARMS_ONLY, - /** - * controller, waist and feet trackers are available - */ - ARMS_LEGS, - /** - * controller, waist, feet, elbow and knee trackers are available - */ - WITH_JOINTS -} diff --git a/common/src/main/java/org/vivecraft/common/network/Pose.java b/common/src/main/java/org/vivecraft/common/network/Pose.java index ca036d9fd..7e5eb4da0 100644 --- a/common/src/main/java/org/vivecraft/common/network/Pose.java +++ b/common/src/main/java/org/vivecraft/common/network/Pose.java @@ -1,8 +1,13 @@ package org.vivecraft.common.network; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.phys.Vec3; import org.joml.Quaternionfc; +import org.joml.Vector3f; import org.joml.Vector3fc; +import org.vivecraft.api.data.VRBodyPartData; +import org.vivecraft.common.api_impl.data.VRBodyPartDataImpl; +import org.vivecraft.common.utils.MathUtils; /** * holds a device Pose @@ -32,4 +37,15 @@ public void serialize(FriendlyByteBuf buffer) { CommonNetworkHelper.serializeF(buffer, this.position); CommonNetworkHelper.serialize(buffer, this.orientation); } + + /** + * @return This Pose as VRBodyPartData for use with the API. + */ + public VRBodyPartData asBodyPartData() { + return new VRBodyPartDataImpl(fromVector3fc(this.position), fromVector3fc(this.orientation.transform(MathUtils.BACK, new Vector3f())), this.orientation); + } + + private static Vec3 fromVector3fc(Vector3fc vec) { + return new Vec3(vec.x(), vec.y(), vec.z()); + } } diff --git a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java index d81876ef9..deede66ef 100644 --- a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java +++ b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java @@ -4,11 +4,14 @@ import net.minecraft.network.FriendlyByteBuf; import org.joml.Quaternionf; import org.joml.Vector3f; +import org.vivecraft.api.data.FBTMode; +import org.vivecraft.api.data.VRBodyPartData; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.gameplay.VRPlayer; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.common.api_impl.data.VRPoseImpl; import org.vivecraft.common.utils.MathUtils; import javax.annotation.Nullable; @@ -232,4 +235,31 @@ public void serialize(FriendlyByteBuf buffer) { } } } + + /** + * @return This object as a pose for use with the API. + */ + public VRPoseImpl asPose() { + return new VRPoseImpl( + this.hmd.asBodyPartData(), + this.mainHand.asBodyPartData(), + this.offHand.asBodyPartData(), + getDataOrNull(this.rightFoot), + getDataOrNull(this.leftFoot), + getDataOrNull(this.waist), + getDataOrNull(this.rightKnee), + getDataOrNull(this.leftKnee), + getDataOrNull(this.rightElbow), + getDataOrNull(this.leftElbow), + this.seated, + this.leftHanded, + this.fbtMode + ); + } + + @Nullable + private static VRBodyPartData getDataOrNull(Pose pose) { + return pose == null ? null : pose.asBodyPartData(); + } + } diff --git a/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java b/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java index ba516ecf2..15bd9eb50 100644 --- a/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java +++ b/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java @@ -4,7 +4,7 @@ import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.common.network.CommonNetworkHelper; import org.vivecraft.common.network.BodyPart; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.network.packet.PayloadIdentifier; /** diff --git a/common/src/main/java/org/vivecraft/server/ServerNetworking.java b/common/src/main/java/org/vivecraft/server/ServerNetworking.java index c0caa209b..fcc337efe 100644 --- a/common/src/main/java/org/vivecraft/server/ServerNetworking.java +++ b/common/src/main/java/org/vivecraft/server/ServerNetworking.java @@ -18,7 +18,7 @@ import org.vivecraft.client.Xplat; import org.vivecraft.common.CommonDataHolder; import org.vivecraft.common.network.CommonNetworkHelper; -import org.vivecraft.common.network.FBTMode; +import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.network.BodyPart; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.common.network.packet.PayloadIdentifier; diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index c957c226b..a411769b7 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -9,8 +9,6 @@ import org.vivecraft.common.network.*; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.api.data.VRPose; -import org.vivecraft.common.api_impl.data.VRPoseImpl; -import org.vivecraft.common.api_impl.data.VRBodyPartImpl; import org.vivecraft.common.network.CommonNetworkHelper; import org.vivecraft.common.network.Pose; import org.vivecraft.common.network.VrPlayerState; @@ -183,7 +181,10 @@ public boolean isSeated() { return this.vrPlayerState != null && this.vrPlayerState.seated(); } - public boolean usingReversedHands() { + /** + * @return if the player is using left-handed mode + */ + public boolean isLeftHanded() { if (this.vrPlayerState == null) { return false; } @@ -194,21 +195,6 @@ public VRPose asVRPose() { if (this.vrPlayerState == null) { return null; } - return new VRPoseImpl( - new VRBodyPartImpl(this.getHMDPos(), this.getHMDDir(), this.vrPlayerState.hmd().orientation()), - new VRBodyPartImpl(getPos(this.vrPlayerState.mainHand()), getDir(this.vrPlayerState.mainHand()), this.vrPlayerState.mainHand().orientation()), - new VRBodyPartImpl(getPos(this.vrPlayerState.offHand()), getDir(this.vrPlayerState.offHand()), this.vrPlayerState.mainHand().orientation()), - this.isSeated(), - this.usingReversedHands() - ); - } - - private Vec3 getPos(Pose pose) { - Vector3fc pos = pose.position(); - return new Vec3(pos.x(), pos.y(), pos.z()); - } - - private Vec3 getDir(Pose pose) { - return new Vec3(pose.orientation().transform(MathUtils.BACK, new Vector3f())); + return this.vrPlayerState.asPose(); } } From c4d707e157f9a80ff1bb291b8444b2fe69c1bded Mon Sep 17 00:00:00 2001 From: hammy275 Date: Mon, 13 Jan 2025 13:21:37 -0500 Subject: [PATCH 10/33] Move averageSpeed() to Impl Class --- .../org/vivecraft/api/client/data/VRPoseHistory.java | 10 +--------- .../client/api_impl/data/VRPoseHistoryImpl.java | 11 +++++++++++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java index d6fc640c2..96c7d9760 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -79,15 +79,7 @@ public interface VRPoseHistory { * can be looked back. Will be 0 if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. */ - default double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { - Vec3 averageVelocity = averageVelocity(bodyPart, maxTicksBack); - if (averageVelocity == null) { - return 0; - } - return Math.sqrt(averageVelocity.x() * averageVelocity.x() + - averageVelocity.y() * averageVelocity.y() + - averageVelocity.z() * averageVelocity.z()); - } + double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; /** * Gets the average position between the most recent pose in this instance and the oldest position that can be diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java index a02a66979..e8e63fb75 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java @@ -82,6 +82,17 @@ public Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws Illega return current.subtract(old).scale(1d / getNumTicksBack(maxTicksBack)); } + @Override + public double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { + Vec3 averageVelocity = averageVelocity(bodyPart, maxTicksBack); + if (averageVelocity == null) { + return 0; + } + return Math.sqrt(averageVelocity.x() * averageVelocity.x() + + averageVelocity.y() * averageVelocity.y() + + averageVelocity.z() * averageVelocity.z()); + } + @Override public Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); From 1524c4e216c3f047c1df1e5acc474142d0e19ab7 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Mon, 13 Jan 2025 18:42:30 -0500 Subject: [PATCH 11/33] Hand Renaming and Docstring Changes --- .../api/client/VivecraftClientAPI.java | 8 ++-- .../java/org/vivecraft/api/data/FBTMode.java | 6 +-- .../org/vivecraft/api/data/VRBodyPart.java | 4 +- .../java/org/vivecraft/api/data/VRPose.java | 42 +++++++++---------- .../common/api_impl/data/VRPoseImpl.java | 4 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java index 88a45a9fe..a4ec8de7c 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java @@ -80,8 +80,8 @@ static VivecraftClientAPI getInstance() { * Causes a haptic pulse (vibration/rumble) for the specified controller. * This function silently fails if called for players not in VR or players who are in seated mode. * - * @param controllerNum The controller number to trigger a haptic pulse. 0 is the primary controller, while 1 is - * the secondary controller. + * @param controllerNum The controller number to trigger a haptic pulse. 0 is the main-hand's controller, while 1 is + * the off-hand's controller. * @param duration The duration of the haptic pulse in seconds. Note that this number is passed to the * underlying VR API used by Vivecraft, and may act with a shorter length than expected beyond * very short pulses. @@ -97,8 +97,8 @@ static VivecraftClientAPI getInstance() { * Causes a haptic pulse (vibration/rumble) for the specified controller. * This function silently fails if called for players not in VR or players who are in seated mode. * - * @param controllerNum The controller number to trigger a haptic pulse. 0 is the primary controller, while 1 is - * the secondary controller. + * @param controllerNum The controller number to trigger a haptic pulse. 0 is the main-hand's controller, while 1 is + * the off-hand's controller. * @param duration The duration of the haptic pulse in seconds. Note that this number is passed to the * underlying VR API used by Vivecraft, and may act with a shorter length than expected beyond * very short pulses. diff --git a/common/src/main/java/org/vivecraft/api/data/FBTMode.java b/common/src/main/java/org/vivecraft/api/data/FBTMode.java index 4cad642fe..6c37a54e6 100644 --- a/common/src/main/java/org/vivecraft/api/data/FBTMode.java +++ b/common/src/main/java/org/vivecraft/api/data/FBTMode.java @@ -5,15 +5,15 @@ */ public enum FBTMode { /** - * Only controllers are available. + * Only HMD and hands are available. */ ARMS_ONLY, /** - * Controller, waist and feet trackers are available. + * HMD, hands, waist, and feet trackers are available. */ ARMS_LEGS, /** - * Controller, waist, feet, elbow and knee trackers are available. + * HMD, hands, waist, feet, elbow, and knee trackers are available. */ WITH_JOINTS; diff --git a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java index 8ad9e3456..06a269f4e 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java +++ b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java @@ -4,7 +4,7 @@ * The device tracking a specific body part. */ public enum VRBodyPart { - HEAD, + HMD, MAIN_HAND, OFF_HAND, RIGHT_FOOT, @@ -39,7 +39,7 @@ public VRBodyPart opposite() { */ public boolean availableInMode(FBTMode mode) { return switch (this) { - case HEAD, MAIN_HAND, OFF_HAND -> true; + case HMD, MAIN_HAND, OFF_HAND -> true; case RIGHT_FOOT, LEFT_FOOT, WAIST -> mode != FBTMode.ARMS_ONLY; case RIGHT_KNEE, LEFT_KNEE, RIGHT_ELBOW, LEFT_ELBOW -> mode == FBTMode.WITH_JOINTS; }; diff --git a/common/src/main/java/org/vivecraft/api/data/VRPose.java b/common/src/main/java/org/vivecraft/api/data/VRPose.java index 6047fcd0d..1fa9ad10c 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRPose.java +++ b/common/src/main/java/org/vivecraft/api/data/VRPose.java @@ -23,20 +23,20 @@ public interface VRPose { * @return Body part pose data for the HMD. */ default VRBodyPartData getHMD() { - return getBodyPartData(VRBodyPart.HEAD); + return getBodyPartData(VRBodyPart.HMD); } /** - * Gets the body part data for a given controller. + * Gets the body part data for a given hand. * - * @param controller The controller number to get, with 0 being the primary controller. - * @return The specified controller's pose data. + * @param hand The hand number to get, with 0 being the main-hand and 1 being the off-hand. + * @return The specified hand's pose data. */ - default VRBodyPartData getController(int controller) { - if (controller != 0 && controller != 1) { - throw new IllegalArgumentException("Controller number must be controller 0 or controller 1."); + default VRBodyPartData getHand(int hand) { + if (hand != 0 && hand != 1) { + throw new IllegalArgumentException("Hand number must be 0 or 1."); } - return controller == 0 ? getBodyPartData(VRBodyPart.MAIN_HAND) : getBodyPartData(VRBodyPart.OFF_HAND); + return hand == 0 ? getBodyPartData(VRBodyPart.MAIN_HAND) : getBodyPartData(VRBodyPart.OFF_HAND); } /** @@ -55,30 +55,30 @@ default VRBodyPartData getController(int controller) { FBTMode getFBTMode(); /** - * Gets the pose for a given controller. + * Gets the pose for a given hand. * - * @param hand The interaction hand to get controller data for. - * @return The specified controller's pose data. + * @param hand The interaction hand to get hand data for. + * @return The specified hand's pose data. */ - default VRBodyPartData getController(InteractionHand hand) { - return getController(hand.ordinal()); + default VRBodyPartData getHand(InteractionHand hand) { + return getHand(hand.ordinal()); } /** - * Gets the pose for the primary controller. + * Gets the pose for the main-hand. * - * @return The main controller's pose data. + * @return The main-hand's pose data. */ - default VRBodyPartData getController0() { - return getController(0); + default VRBodyPartData getMainHand() { + return getHand(0); } /** - * Gets the pose for the secondary controller. + * Gets the pose for the off-hand. * - * @return The main controller's pose data. + * @return The off-hand's pose data. */ - default VRBodyPartData getController1() { - return getController(1); + default VRBodyPartData getOffHand() { + return getHand(1); } } diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java index 6ff26ab2e..88cc590ae 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRPoseImpl.java @@ -21,7 +21,7 @@ public VRBodyPartData getBodyPartData(VRBodyPart vrBodyPart) { throw new IllegalArgumentException("Cannot get a null body part's data!"); } return switch (vrBodyPart) { - case HEAD -> this.hmd; + case HMD -> this.hmd; case MAIN_HAND -> this.c0; case OFF_HAND -> this.c1; case RIGHT_FOOT -> this.rightFoot; @@ -41,6 +41,6 @@ public FBTMode getFBTMode() { @Override public String toString() { - return "HMD: " + getHMD() + "\nController 0: " + getController0() + "\nController 1: " + getController1(); + return "HMD: " + getHMD() + "\nController 0: " + getMainHand() + "\nController 1: " + getOffHand(); } } From 31af70bd8fb4c3f6b335e55c56a2eac5517858aa Mon Sep 17 00:00:00 2001 From: hammy275 Date: Tue, 14 Jan 2025 15:15:04 -0500 Subject: [PATCH 12/33] Vivecraft to VR Rename --- .../vivecraft/api/{VivecraftAPI.java => VRAPI.java} | 8 ++++---- .../main/java/org/vivecraft/api/client/Tracker.java | 7 ++++--- .../{VivecraftClientAPI.java => VRClientAPI.java} | 10 +++++----- ...{VivecraftRenderingAPI.java => VRRenderingAPI.java} | 10 +++++----- ...ivecraftClientAPIImpl.java => VRClientAPIImpl.java} | 8 ++++---- ...ftRenderingAPIImpl.java => VRRenderingAPIImpl.java} | 8 ++++---- .../src/main/java/org/vivecraft/client_vr/VRState.java | 4 ++-- .../org/vivecraft/client_vr/gameplay/VRPlayer.java | 4 ++-- .../api_impl/{VivecraftAPIImpl.java => VRAPIImpl.java} | 8 ++++---- 9 files changed, 34 insertions(+), 33 deletions(-) rename common/src/main/java/org/vivecraft/api/{VivecraftAPI.java => VRAPI.java} (85%) rename common/src/main/java/org/vivecraft/api/client/{VivecraftClientAPI.java => VRClientAPI.java} (96%) rename common/src/main/java/org/vivecraft/api/client/{VivecraftRenderingAPI.java => VRRenderingAPI.java} (72%) rename common/src/main/java/org/vivecraft/client/api_impl/{VivecraftClientAPIImpl.java => VRClientAPIImpl.java} (94%) rename common/src/main/java/org/vivecraft/client/api_impl/{VivecraftRenderingAPIImpl.java => VRRenderingAPIImpl.java} (68%) rename common/src/main/java/org/vivecraft/common/api_impl/{VivecraftAPIImpl.java => VRAPIImpl.java} (82%) diff --git a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java b/common/src/main/java/org/vivecraft/api/VRAPI.java similarity index 85% rename from common/src/main/java/org/vivecraft/api/VivecraftAPI.java rename to common/src/main/java/org/vivecraft/api/VRAPI.java index 6d44f86c4..e333ce725 100644 --- a/common/src/main/java/org/vivecraft/api/VivecraftAPI.java +++ b/common/src/main/java/org/vivecraft/api/VRAPI.java @@ -2,20 +2,20 @@ import net.minecraft.world.entity.player.Player; import org.vivecraft.api.data.VRPose; -import org.vivecraft.common.api_impl.VivecraftAPIImpl; +import org.vivecraft.common.api_impl.VRAPIImpl; import javax.annotation.Nullable; /** * The main interface for interacting with Vivecraft from common code. */ -public interface VivecraftAPI { +public interface VRAPI { /** * @return The Vivecraft API instance for interacting with Vivecraft's API. */ - static VivecraftAPI getInstance() { - return VivecraftAPIImpl.INSTANCE; + static VRAPI getInstance() { + return VRAPIImpl.INSTANCE; } /** diff --git a/common/src/main/java/org/vivecraft/api/client/Tracker.java b/common/src/main/java/org/vivecraft/api/client/Tracker.java index af7996a67..75a29e8e0 100644 --- a/common/src/main/java/org/vivecraft/api/client/Tracker.java +++ b/common/src/main/java/org/vivecraft/api/client/Tracker.java @@ -2,13 +2,14 @@ import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.player.Player; +import org.vivecraft.api.VRAPI; /** * A tracker is an object that is run for the local player during the game tick or before rendering a frame only if * they are in VR. Using trackers are one of the cleanest ways to interact with Vivecraft's data; it's how Vivecraft - * itself does. Trackers should generally use {@link VivecraftClientAPI#getPreTickWorldPose()}, as this provides - * the most up-to-date data, and other methods such as {@link VivecraftClientAPI#getPostTickWorldPose()} or - * {@link org.vivecraft.api.VivecraftAPI#getVRPose(Player)} may not have data available when the tracker is run. + * itself does. Trackers should generally use {@link VRClientAPI#getPreTickWorldPose()}, as this provides + * the most up-to-date data, and other methods such as {@link VRClientAPI#getPostTickWorldPose()} or + * {@link VRAPI#getVRPose(Player)} may not have data available when the tracker is run. */ public interface Tracker { diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java similarity index 96% rename from common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java rename to common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index a4ec8de7c..9ca6c368f 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -3,18 +3,18 @@ import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.FBTMode; import org.vivecraft.api.data.VRPose; -import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; +import org.vivecraft.client.api_impl.VRClientAPIImpl; import javax.annotation.Nullable; /** * The main interface for interacting with Vivecraft from client code. For rendering, one should use - * {@link VivecraftRenderingAPI}. + * {@link VRRenderingAPI}. */ -public interface VivecraftClientAPI { +public interface VRClientAPI { - static VivecraftClientAPI getInstance() { - return VivecraftClientAPIImpl.INSTANCE; + static VRClientAPI getInstance() { + return VRClientAPIImpl.INSTANCE; } /** diff --git a/common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java similarity index 72% rename from common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java rename to common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java index 75cd7e232..c53716c0d 100644 --- a/common/src/main/java/org/vivecraft/api/client/VivecraftRenderingAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java @@ -1,16 +1,16 @@ package org.vivecraft.api.client; -import org.vivecraft.client.api_impl.VivecraftRenderingAPIImpl; +import org.vivecraft.client.api_impl.VRRenderingAPIImpl; import org.vivecraft.client_vr.render.RenderPass; /** * The main interface for interacting with Vivecraft from rendering code. For other client-side code, one should use - * {@link VivecraftClientAPI}. + * {@link VRClientAPI}. */ -public interface VivecraftRenderingAPI { +public interface VRRenderingAPI { - static VivecraftRenderingAPI getInstance() { - return VivecraftRenderingAPIImpl.INSTANCE; + static VRRenderingAPI getInstance() { + return VRRenderingAPIImpl.INSTANCE; } /** diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java similarity index 94% rename from common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java rename to common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index a8ef7881b..d25f4bcd8 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -2,7 +2,7 @@ import org.jetbrains.annotations.Nullable; import org.vivecraft.api.client.Tracker; -import org.vivecraft.api.client.VivecraftClientAPI; +import org.vivecraft.api.client.VRClientAPI; import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.FBTMode; import org.vivecraft.api.data.VRPose; @@ -12,13 +12,13 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.provider.ControllerType; -public final class VivecraftClientAPIImpl implements VivecraftClientAPI { +public final class VRClientAPIImpl implements VRClientAPI { - public static final VivecraftClientAPIImpl INSTANCE = new VivecraftClientAPIImpl(); + public static final VRClientAPIImpl INSTANCE = new VRClientAPIImpl(); private final VRPoseHistoryImpl poseHistory = new VRPoseHistoryImpl(); - private VivecraftClientAPIImpl() { + private VRClientAPIImpl() { } public void clearHistories() { diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java similarity index 68% rename from common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java rename to common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java index aaebb0f47..eba62f112 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VivecraftRenderingAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java @@ -1,15 +1,15 @@ package org.vivecraft.client.api_impl; -import org.vivecraft.api.client.VivecraftRenderingAPI; +import org.vivecraft.api.client.VRRenderingAPI; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_xr.render_pass.RenderPassType; -public class VivecraftRenderingAPIImpl implements VivecraftRenderingAPI { +public class VRRenderingAPIImpl implements VRRenderingAPI { - public static final VivecraftRenderingAPIImpl INSTANCE = new VivecraftRenderingAPIImpl(); + public static final VRRenderingAPIImpl INSTANCE = new VRRenderingAPIImpl(); - private VivecraftRenderingAPIImpl() { + private VRRenderingAPIImpl() { } @Override diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index 6e1fb8f41..1ced3e55b 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -8,7 +8,7 @@ import org.vivecraft.client.gui.screens.GarbageCollectorScreen; import org.vivecraft.client.utils.TextUtils; import org.vivecraft.client_vr.gameplay.VRPlayer; -import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; +import org.vivecraft.client.api_impl.VRClientAPIImpl; import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; import org.vivecraft.client_vr.provider.nullvr.NullVR; import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; @@ -153,6 +153,6 @@ public static void destroyVR(boolean disableVRSetting) { // this reloads any PostChain, at least in vanilla Minecraft.getInstance().levelRenderer.onResourceManagerReload(Minecraft.getInstance().getResourceManager()); } - VivecraftClientAPIImpl.INSTANCE.clearHistories(); + VRClientAPIImpl.INSTANCE.clearHistories(); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index f8e58c31f..56c80390f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -25,7 +25,7 @@ import org.joml.Vector3fc; import org.vivecraft.api.client.Tracker; import org.vivecraft.client.VivecraftVRMod; -import org.vivecraft.client.api_impl.VivecraftClientAPIImpl; +import org.vivecraft.client.api_impl.VRClientAPIImpl; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.common.VRServerPerms; import org.vivecraft.client.network.ClientNetworking; @@ -237,7 +237,7 @@ public void preTick() { this.dh.vrSettings.worldRotation = this.dh.vr.seatedRot; } - VivecraftClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRPose()); + VRClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRPose()); } public void postTick() { diff --git a/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java similarity index 82% rename from common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java rename to common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java index e23614bb5..749181d42 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/VivecraftAPIImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java @@ -2,17 +2,17 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; -import org.vivecraft.api.VivecraftAPI; +import org.vivecraft.api.VRAPI; import org.vivecraft.client.ClientVRPlayers; import org.jetbrains.annotations.Nullable; import org.vivecraft.api.data.VRPose; import org.vivecraft.server.ServerVRPlayers; -public final class VivecraftAPIImpl implements VivecraftAPI { +public final class VRAPIImpl implements VRAPI { - public static final VivecraftAPIImpl INSTANCE = new VivecraftAPIImpl(); + public static final VRAPIImpl INSTANCE = new VRAPIImpl(); - private VivecraftAPIImpl() { + private VRAPIImpl() { } @Override From fe5aa1c3a1fca240907826252f3f7dc0613b8d51 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Tue, 14 Jan 2025 16:06:35 -0500 Subject: [PATCH 13/33] Translate Position for Player in Common API --- .../org/vivecraft/client/ClientVRPlayers.java | 30 +++++++++---------- .../vivecraft/common/api_impl/VRAPIImpl.java | 4 +-- .../org/vivecraft/common/network/Pose.java | 6 ++-- .../common/network/VrPlayerState.java | 29 ++++++++++-------- .../vivecraft/server/ServerVivePlayer.java | 4 +-- 5 files changed, 39 insertions(+), 34 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index 4b7047310..746816a2e 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -572,18 +572,18 @@ public float getBodyYawRad() { return (float) Math.atan2(-dir.x, dir.z); } - public VRPose asVRPose() { + public VRPose asVRPose(Vec3 playerPos) { return new VRPoseImpl( - makeBodyPartData(this.headPos, this.headRot, this.headQuat), - makeBodyPartData(this.mainHandPos, this.mainHandRot, this.mainHandQuat), - makeBodyPartData(this.offHandPos, this.offHandRot, this.offHandQuat), - makeBodyPartData(this.rightFootPos, this.rightFootQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), - makeBodyPartData(this.leftFootPos, this.leftFootQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), - makeBodyPartData(this.waistPos, this.waistQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), - makeBodyPartData(this.rightKneePos, this.rightKneeQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), - makeBodyPartData(this.leftKneePos, this.leftKneeQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), - makeBodyPartData(this.rightElbowPos, this.rightElbowQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), - makeBodyPartData(this.leftElbowPos, this.leftElbowQuat, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), + makeBodyPartData(this.headPos, this.headRot, this.headQuat, playerPos), + makeBodyPartData(this.mainHandPos, this.mainHandRot, this.mainHandQuat, playerPos), + makeBodyPartData(this.offHandPos, this.offHandRot, this.offHandQuat, playerPos), + makeBodyPartData(this.rightFootPos, this.rightFootQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), + makeBodyPartData(this.leftFootPos, this.leftFootQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), + makeBodyPartData(this.waistPos, this.waistQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), + makeBodyPartData(this.rightKneePos, this.rightKneeQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), + makeBodyPartData(this.leftKneePos, this.leftKneeQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), + makeBodyPartData(this.rightElbowPos, this.rightElbowQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), + makeBodyPartData(this.leftElbowPos, this.leftElbowQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), this.seated, this.leftHanded, this.fbtMode @@ -591,13 +591,13 @@ public VRPose asVRPose() { } } - private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Vector3fc rot, Quaternionfc quat) { - return new VRBodyPartDataImpl(fromVector3fc(pos), fromVector3fc(rot), quat); + private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Vector3fc rot, Quaternionfc quat, Vec3 playerPos) { + return new VRBodyPartDataImpl(fromVector3fc(pos).add(playerPos), fromVector3fc(rot), quat); } - private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Quaternionfc quat, boolean partAvailable) { + private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Quaternionfc quat, Vec3 playerPos, boolean partAvailable) { return partAvailable - ? new VRBodyPartDataImpl(fromVector3fc(pos), fromVector3fc(quat.transform(MathUtils.BACK, new Vector3f())), quat) + ? makeBodyPartData(pos, quat.transform(MathUtils.BACK, new Vector3f()), quat, playerPos) : null; } diff --git a/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java index 749181d42..62f08311a 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java @@ -31,9 +31,9 @@ public VRPose getVRPose(Player player) { return null; } if (player instanceof ServerPlayer serverPlayer) { - return ServerVRPlayers.getVivePlayer(serverPlayer).asVRPose(); + return ServerVRPlayers.getVivePlayer(serverPlayer).asVRPose(serverPlayer.position()); } - return ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()).asVRPose(); + return ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()).asVRPose(player.position()); } } diff --git a/common/src/main/java/org/vivecraft/common/network/Pose.java b/common/src/main/java/org/vivecraft/common/network/Pose.java index 7e5eb4da0..17e5029eb 100644 --- a/common/src/main/java/org/vivecraft/common/network/Pose.java +++ b/common/src/main/java/org/vivecraft/common/network/Pose.java @@ -39,10 +39,12 @@ public void serialize(FriendlyByteBuf buffer) { } /** + * @param playerPos The current position of the player. + * * @return This Pose as VRBodyPartData for use with the API. */ - public VRBodyPartData asBodyPartData() { - return new VRBodyPartDataImpl(fromVector3fc(this.position), fromVector3fc(this.orientation.transform(MathUtils.BACK, new Vector3f())), this.orientation); + public VRBodyPartData asBodyPartData(Vec3 playerPos) { + return new VRBodyPartDataImpl(fromVector3fc(this.position).add(playerPos), fromVector3fc(this.orientation.transform(MathUtils.BACK, new Vector3f())), this.orientation); } private static Vec3 fromVector3fc(Vector3fc vec) { diff --git a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java index deede66ef..974499ab9 100644 --- a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java +++ b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java @@ -2,6 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.phys.Vec3; import org.joml.Quaternionf; import org.joml.Vector3f; import org.vivecraft.api.data.FBTMode; @@ -237,20 +238,22 @@ public void serialize(FriendlyByteBuf buffer) { } /** + * @param playerPos The current position of the player. + * * @return This object as a pose for use with the API. */ - public VRPoseImpl asPose() { + public VRPoseImpl asPose(Vec3 playerPos) { return new VRPoseImpl( - this.hmd.asBodyPartData(), - this.mainHand.asBodyPartData(), - this.offHand.asBodyPartData(), - getDataOrNull(this.rightFoot), - getDataOrNull(this.leftFoot), - getDataOrNull(this.waist), - getDataOrNull(this.rightKnee), - getDataOrNull(this.leftKnee), - getDataOrNull(this.rightElbow), - getDataOrNull(this.leftElbow), + this.hmd.asBodyPartData(playerPos), + this.mainHand.asBodyPartData(playerPos), + this.offHand.asBodyPartData(playerPos), + getDataOrNull(this.rightFoot, playerPos), + getDataOrNull(this.leftFoot, playerPos), + getDataOrNull(this.waist, playerPos), + getDataOrNull(this.rightKnee, playerPos), + getDataOrNull(this.leftKnee, playerPos), + getDataOrNull(this.rightElbow, playerPos), + getDataOrNull(this.leftElbow, playerPos), this.seated, this.leftHanded, this.fbtMode @@ -258,8 +261,8 @@ public VRPoseImpl asPose() { } @Nullable - private static VRBodyPartData getDataOrNull(Pose pose) { - return pose == null ? null : pose.asBodyPartData(); + private static VRBodyPartData getDataOrNull(Pose pose, Vec3 playerPos) { + return pose == null ? null : pose.asBodyPartData(playerPos); } } diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index a411769b7..9e07c7b78 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -191,10 +191,10 @@ public boolean isLeftHanded() { return this.vrPlayerState.leftHanded(); } - public VRPose asVRPose() { + public VRPose asVRPose(Vec3 playerPos) { if (this.vrPlayerState == null) { return null; } - return this.vrPlayerState.asPose(); + return this.vrPlayerState.asPose(playerPos); } } From fab686c2191732366445946053132db8c880231f Mon Sep 17 00:00:00 2001 From: hammy275 Date: Wed, 15 Jan 2025 12:53:22 -0500 Subject: [PATCH 14/33] Not VR Active Conditional for Default Return --- .../java/org/vivecraft/client/api_impl/VRClientAPIImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index d25f4bcd8..5b160e53d 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -106,7 +106,7 @@ public boolean isLeftHanded() { @Override public FBTMode getFBTMode() { // Need to check if VR is running, not just initialized, since the VR player is set after initialization - if (isVRActive()) { + if (!isVRActive()) { return FBTMode.ARMS_ONLY; } return ClientDataHolderVR.getInstance().vrPlayer.vrdata_world_pre.fbtMode; From f43d9e39698db5fc6396016525e6129aa50d98b1 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Wed, 15 Jan 2025 15:27:54 -0500 Subject: [PATCH 15/33] Expose getControllerRenderPos and setupRenderingAtController in API --- .../vivecraft/api/client/VRRenderingAPI.java | 24 +++++++++++++++++++ .../api/client/data/RenderPosOption.java | 12 ++++++++++ .../client/api_impl/VRRenderingAPIImpl.java | 14 +++++++++++ 3 files changed, 50 insertions(+) create mode 100644 common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java diff --git a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java index c53716c0d..a464b6378 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java @@ -1,5 +1,10 @@ package org.vivecraft.api.client; +import com.google.common.annotations.Beta; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.Vec3; +import org.vivecraft.api.client.data.RenderPosOption; import org.vivecraft.client.api_impl.VRRenderingAPIImpl; import org.vivecraft.client_vr.render.RenderPass; @@ -27,4 +32,23 @@ static VRRenderingAPI getInstance() { * @return Whether the current render pass is the first one it performed for this render cycle. */ boolean isFirstRenderPass(); + + /** + * Gets the position that the provided {@link RenderPosOption} renders at. Unlike + * {@link org.vivecraft.api.data.VRPose#getHand(InteractionHand)} for {@link VRClientAPI#getWorldRenderPose()}, this + * returns a reasonable, default value for seated mode and can also be used to retrieve the rendering position + * for the third person camera. + * @param option The rendering position to be returned. + * @return The rendering position for the provided hand. + */ + @Beta + Vec3 getRenderPos(RenderPosOption option); + + /** + * Sets the provided {@link PoseStack} to render at the position provided. + * @param option The rendering position to set the PoseStack to. + * @param stack The PoseStack to be set. + */ + @Beta + void setupRendering(RenderPosOption option, PoseStack stack); } diff --git a/common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java b/common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java new file mode 100644 index 000000000..2d90ab267 --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java @@ -0,0 +1,12 @@ +package org.vivecraft.api.client.data; + +import com.google.common.annotations.Beta; +import net.minecraft.world.InteractionHand; + +/** + * The option to pass to {@link org.vivecraft.api.client.VRRenderingAPI#getRenderPos(RenderPosOption)}. + */ +@Beta +public enum RenderPosOption { + MAIN_HAND, OFF_HAND, THIRD_PERSON_CAMERA +} diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java index eba62f112..c22527747 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java @@ -1,8 +1,12 @@ package org.vivecraft.client.api_impl; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.world.phys.Vec3; import org.vivecraft.api.client.VRRenderingAPI; +import org.vivecraft.api.client.data.RenderPosOption; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_vr.render.helpers.RenderHelper; import org.vivecraft.client_xr.render_pass.RenderPassType; public class VRRenderingAPIImpl implements VRRenderingAPI { @@ -26,4 +30,14 @@ public RenderPass getCurrentRenderPass() { public boolean isFirstRenderPass() { return ClientDataHolderVR.getInstance().isFirstPass; } + + @Override + public Vec3 getRenderPos(RenderPosOption option) { + return RenderHelper.getControllerRenderPos(option.ordinal()); + } + + @Override + public void setupRendering(RenderPosOption option, PoseStack stack) { + RenderHelper.setupRenderingAtController(option.ordinal(), stack); + } } From d2da436e224cccecd6e4eedf58d6bfa1d30f0fff Mon Sep 17 00:00:00 2001 From: hammy275 Date: Wed, 15 Jan 2025 15:47:14 -0500 Subject: [PATCH 16/33] Just Expose Hands --- .../vivecraft/api/client/VRRenderingAPI.java | 18 ++++++++---------- .../api/client/data/RenderPosOption.java | 12 ------------ .../client/api_impl/VRRenderingAPIImpl.java | 10 +++++----- 3 files changed, 13 insertions(+), 27 deletions(-) delete mode 100644 common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java diff --git a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java index a464b6378..98ad1d2af 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java @@ -4,7 +4,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.world.InteractionHand; import net.minecraft.world.phys.Vec3; -import org.vivecraft.api.client.data.RenderPosOption; import org.vivecraft.client.api_impl.VRRenderingAPIImpl; import org.vivecraft.client_vr.render.RenderPass; @@ -34,21 +33,20 @@ static VRRenderingAPI getInstance() { boolean isFirstRenderPass(); /** - * Gets the position that the provided {@link RenderPosOption} renders at. Unlike - * {@link org.vivecraft.api.data.VRPose#getHand(InteractionHand)} for {@link VRClientAPI#getWorldRenderPose()}, this - * returns a reasonable, default value for seated mode and can also be used to retrieve the rendering position - * for the third person camera. - * @param option The rendering position to be returned. + * Gets the position that the provided {@link InteractionHand} renders at. Unlike + * {@link org.vivecraft.api.data.VRPose#getHand(InteractionHand)} from {@link VRClientAPI#getWorldRenderPose()}, + * this returns a reasonable, default value for seated mode. + * @param hand The hand to get the rendering position of. * @return The rendering position for the provided hand. */ @Beta - Vec3 getRenderPos(RenderPosOption option); + Vec3 getHandRenderPos(InteractionHand hand); /** - * Sets the provided {@link PoseStack} to render at the position provided. - * @param option The rendering position to set the PoseStack to. + * Sets the provided {@link PoseStack} to render at the position of the provided {@link InteractionHand}. + * @param hand The hand to set the PoseStack to. * @param stack The PoseStack to be set. */ @Beta - void setupRendering(RenderPosOption option, PoseStack stack); + void setupRenderingAtHand(InteractionHand hand, PoseStack stack); } diff --git a/common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java b/common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java deleted file mode 100644 index 2d90ab267..000000000 --- a/common/src/main/java/org/vivecraft/api/client/data/RenderPosOption.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.vivecraft.api.client.data; - -import com.google.common.annotations.Beta; -import net.minecraft.world.InteractionHand; - -/** - * The option to pass to {@link org.vivecraft.api.client.VRRenderingAPI#getRenderPos(RenderPosOption)}. - */ -@Beta -public enum RenderPosOption { - MAIN_HAND, OFF_HAND, THIRD_PERSON_CAMERA -} diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java index c22527747..68b49aee4 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRRenderingAPIImpl.java @@ -1,9 +1,9 @@ package org.vivecraft.client.api_impl; import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.world.InteractionHand; import net.minecraft.world.phys.Vec3; import org.vivecraft.api.client.VRRenderingAPI; -import org.vivecraft.api.client.data.RenderPosOption; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.render.helpers.RenderHelper; @@ -32,12 +32,12 @@ public boolean isFirstRenderPass() { } @Override - public Vec3 getRenderPos(RenderPosOption option) { - return RenderHelper.getControllerRenderPos(option.ordinal()); + public Vec3 getHandRenderPos(InteractionHand hand) { + return RenderHelper.getControllerRenderPos(hand.ordinal()); } @Override - public void setupRendering(RenderPosOption option, PoseStack stack) { - RenderHelper.setupRenderingAtController(option.ordinal(), stack); + public void setupRenderingAtHand(InteractionHand hand, PoseStack stack) { + RenderHelper.setupRenderingAtController(hand.ordinal(), stack); } } From 0f0559183d6c8d89c1989366cd16e5fd76d763f3 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:11:14 -0500 Subject: [PATCH 17/33] Docstring Improvements --- .../main/java/org/vivecraft/api/client/Tracker.java | 12 ++++++------ .../java/org/vivecraft/api/client/VRClientAPI.java | 4 +--- .../org/vivecraft/api/client/VRRenderingAPI.java | 5 +++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/Tracker.java b/common/src/main/java/org/vivecraft/api/client/Tracker.java index 75a29e8e0..ca0ad22e0 100644 --- a/common/src/main/java/org/vivecraft/api/client/Tracker.java +++ b/common/src/main/java/org/vivecraft/api/client/Tracker.java @@ -38,9 +38,9 @@ public interface Tracker { TrackerTickType tickType(); /** - * Called for the client player if this tracker is currently causing the item to be used to not release the use key. - * In other words, if you want the item currently being held to act as the use key being held, one should call - * the use item function, then return true from this method while the item should still remain used. + * Called for the client player, to check if this tracker is currently causing the item to be used to not release + * the use key. In other words, if you want the item currently being held to act as the use key being held, one + * should call the use item function, then return true from this method while the item should still remain used. * @param player The local player which is running this tracker. * @return Whether the item should remain in use. */ @@ -49,16 +49,16 @@ default boolean itemInUse(LocalPlayer player) { } /** - * Called to reset data for the local player. This is called whenever {@link #isActive(LocalPlayer)} returns false. + * Called to reset this tracker's state. This is called whenever {@link #isActive(LocalPlayer)} returns false. * - * @param player The local player, which will have their data reset. + * @param player The local player. */ default void reset(LocalPlayer player) { } /** - * Called for all players, whether the tracker is active or not for them. This runs before + * Called for the local player, whether the tracker is active or not for them. This runs before * {@link #isActive(LocalPlayer)} or {@link #reset(LocalPlayer)}. * * @param player Player to do an idle tick for, which is the local player. diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index 9ca6c368f..00d1effdf 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -66,9 +66,7 @@ static VRClientAPI getInstance() { VRPose getPostTickWorldPose(); /** - * Gets the VR pose representing the player in Minecraft world coordinates after the game tick interpolated for - * rendering. - * This is the same pose as {@link #getPostTickWorldPose()}, however it is interpolated for rendering. + * Gets the VR pose representing the player in Minecraft world coordinates interpolated for rendering. * * @return The VR pose representing the player in Minecraft space post-tick interpolated for rendering, or null if * the local player isn't in VR. diff --git a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java index 98ad1d2af..71d29f928 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java @@ -28,7 +28,7 @@ static VRRenderingAPI getInstance() { RenderPass getCurrentRenderPass(); /** - * @return Whether the current render pass is the first one it performed for this render cycle. + * @return Whether the current render pass is the first one performed for this render cycle. */ boolean isFirstRenderPass(); @@ -43,7 +43,8 @@ static VRRenderingAPI getInstance() { Vec3 getHandRenderPos(InteractionHand hand); /** - * Sets the provided {@link PoseStack} to render at the position of the provided {@link InteractionHand}. + * Sets the provided {@link PoseStack} to render at the position of and with the rotation of the provided + * {@link InteractionHand}. * @param hand The hand to set the PoseStack to. * @param stack The PoseStack to be set. */ From 5b781f2ead2ac9371ae118aca0342cad03fb054b Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:19:50 -0500 Subject: [PATCH 18/33] Some Minor Adjustments --- .../java/org/vivecraft/client_vr/ClientDataHolderVR.java | 2 +- common/src/main/java/org/vivecraft/client_vr/VRData.java | 4 +--- .../java/org/vivecraft/client_vr/gameplay/VRPlayer.java | 6 ++---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java index 7d2299a53..c15e6be4c 100644 --- a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java @@ -150,6 +150,6 @@ public List getTrackers() { * @return Whether some tracker is currently using an item. */ public boolean isTrackerUsingItem(LocalPlayer player) { - return ClientDataHolderVR.getInstance().getTrackers().stream().anyMatch(tracker -> tracker.itemInUse(player)); + return this.trackers.stream().anyMatch(tracker -> tracker.itemInUse(player)); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/VRData.java b/common/src/main/java/org/vivecraft/client_vr/VRData.java index af0990949..51eceb4f5 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRData.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRData.java @@ -535,12 +535,10 @@ public Matrix4f getMatrix() { } public VRBodyPartData asVRBodyPart() { - Quaternionf quat = new Quaternionf(); - quat.setFromUnnormalized(getMatrix()); return new VRBodyPartDataImpl( getPosition(), new Vec3(getDirection()), - quat + new Quaternionf().setFromUnnormalized(getMatrix()) ); } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 56c80390f..e2893b264 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -301,10 +301,8 @@ public void preRender(float partialTick) { interpolatedWorldScale, interpolatedWorldRotation_Radians); - for (Tracker tracker : ClientDataHolderVR.getInstance().getTrackers()) - { - if (tracker.tickType() == Tracker.TrackerTickType.PER_FRAME) - { + for (Tracker tracker : ClientDataHolderVR.getInstance().getTrackers()) { + if (tracker.tickType() == Tracker.TrackerTickType.PER_FRAME) { tracker.idleTick(this.mc.player); if (tracker.isActive(this.mc.player)) { tracker.doProcess(this.mc.player); From 50b9497abd5f776eaff3f61c54fbfbbb5c5cdcd6 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:26:53 -0500 Subject: [PATCH 19/33] More Adjustments --- .../java/org/vivecraft/client/ClientVRPlayers.java | 6 ++---- .../org/vivecraft/common/api_impl/VRAPIImpl.java | 2 +- .../common/api_impl/data/VRBodyPartDataImpl.java | 14 ++------------ .../java/org/vivecraft/common/network/Pose.java | 6 ++---- .../java/org/vivecraft/common/utils/MathUtils.java | 9 +++++++++ .../org/vivecraft/server/ServerVivePlayer.java | 4 ++-- 6 files changed, 18 insertions(+), 23 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index 746816a2e..22f76d88d 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -35,6 +35,8 @@ import java.util.*; +import static org.vivecraft.common.utils.MathUtils.fromVector3fc; + public class ClientVRPlayers { private static ClientVRPlayers INSTANCE; @@ -600,8 +602,4 @@ private static VRBodyPartDataImpl makeBodyPartData(Vector3fc pos, Quaternionfc q ? makeBodyPartData(pos, quat.transform(MathUtils.BACK, new Vector3f()), quat, playerPos) : null; } - - private static Vec3 fromVector3fc(Vector3fc vec) { - return new Vec3(vec.x(), vec.y(), vec.z()); - } } diff --git a/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java index 62f08311a..13fa86f3c 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/VRAPIImpl.java @@ -31,7 +31,7 @@ public VRPose getVRPose(Player player) { return null; } if (player instanceof ServerPlayer serverPlayer) { - return ServerVRPlayers.getVivePlayer(serverPlayer).asVRPose(serverPlayer.position()); + return ServerVRPlayers.getVivePlayer(serverPlayer).asVRPose(); } return ClientVRPlayers.getInstance().getRotationsForPlayer(player.getUUID()).asVRPose(player.position()); diff --git a/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java b/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java index 3d824ae1b..a08eb4534 100644 --- a/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java +++ b/common/src/main/java/org/vivecraft/common/api_impl/data/VRBodyPartDataImpl.java @@ -4,17 +4,7 @@ import org.joml.Quaternionfc; import org.vivecraft.api.data.VRBodyPartData; -public class VRBodyPartDataImpl implements VRBodyPartData { - - private final Vec3 pos; - private final Vec3 rot; - private final Quaternionfc quaternion; - - public VRBodyPartDataImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) { - this.pos = pos; - this.rot = rot; - this.quaternion = quaternion; - } +public record VRBodyPartDataImpl(Vec3 pos, Vec3 rot, Quaternionfc quaternion) implements VRBodyPartData { @Override public Vec3 getPos() { @@ -49,6 +39,6 @@ public Quaternionfc getQuaternion() { @Override public String toString() { - return "Position: " + getPos() + "\tRotation: " + getRot(); + return "Position: " + getPos() + ", Rotation: " + getRot(); } } diff --git a/common/src/main/java/org/vivecraft/common/network/Pose.java b/common/src/main/java/org/vivecraft/common/network/Pose.java index 17e5029eb..eaebe3fc6 100644 --- a/common/src/main/java/org/vivecraft/common/network/Pose.java +++ b/common/src/main/java/org/vivecraft/common/network/Pose.java @@ -9,6 +9,8 @@ import org.vivecraft.common.api_impl.data.VRBodyPartDataImpl; import org.vivecraft.common.utils.MathUtils; +import static org.vivecraft.common.utils.MathUtils.fromVector3fc; + /** * holds a device Pose * @@ -46,8 +48,4 @@ public void serialize(FriendlyByteBuf buffer) { public VRBodyPartData asBodyPartData(Vec3 playerPos) { return new VRBodyPartDataImpl(fromVector3fc(this.position).add(playerPos), fromVector3fc(this.orientation.transform(MathUtils.BACK, new Vector3f())), this.orientation); } - - private static Vec3 fromVector3fc(Vector3fc vec) { - return new Vec3(vec.x(), vec.y(), vec.z()); - } } 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 f89102e38..0409cb046 100644 --- a/common/src/main/java/org/vivecraft/common/utils/MathUtils.java +++ b/common/src/main/java/org/vivecraft/common/utils/MathUtils.java @@ -233,4 +233,13 @@ public static float bodyYawRad(Vector3fc rightHand, Vector3fc leftHand, Vector3f dir.normalize().lerp(headDir, 0.5F, dir); return (float) Math.atan2(-dir.x, dir.z); } + + /** + * Converst a {@link Vector3fc} to a {@link Vec3}. + * @param vec The original Vector3fc. + * @return The Vec3. + */ + public static Vec3 fromVector3fc(Vector3fc vec) { + return new Vec3(vec.x(), vec.y(), vec.z()); + } } diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index 9e07c7b78..803119fc2 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -191,10 +191,10 @@ public boolean isLeftHanded() { return this.vrPlayerState.leftHanded(); } - public VRPose asVRPose(Vec3 playerPos) { + public VRPose asVRPose() { if (this.vrPlayerState == null) { return null; } - return this.vrPlayerState.asPose(playerPos); + return this.vrPlayerState.asPose(player.position()); } } From 63fda6c9467b73d8fc60cdbb58695c0647e0c7ea Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:28:28 -0500 Subject: [PATCH 20/33] Remove Unused Method --- .../java/org/vivecraft/server/ServerVivePlayer.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index 803119fc2..bbcd6390a 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -147,19 +147,6 @@ public Vec3 getBodyPartPos(BodyPart bodyPart) { return getBodyPartPos(bodyPart, false); } - /** - * - * @param c controller to get the rotation for - * @return controller rotation as a quaternion - */ - public Quaternionfc getControllerQuaternion(int c) { - if (this.vrPlayerState != null) { - Pose controllerPose = c == 0 ? this.vrPlayerState.mainHand() : this.vrPlayerState.offHand(); - return controllerPose.orientation(); - } - return null; // Should only return null if player isn't in VR. - } - /** * @return if the player has VR active */ From 81a5a4be9dea5a65f3e05a83cdf81680ddd3c7d2 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:39:34 -0500 Subject: [PATCH 21/33] More Fixing Up --- .../java/org/vivecraft/api/client/data/VRPoseHistory.java | 2 +- .../java/org/vivecraft/client_vr/gameplay/VRPlayer.java | 6 +++--- .../vivecraft/client_vr/gameplay/trackers/SwingTracker.java | 2 +- .../src/main/java/org/vivecraft/common/utils/MathUtils.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java index 96c7d9760..ba2384b6d 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -17,7 +17,7 @@ public interface VRPoseHistory { * Passing a value larger than this number to any methods below in their maxTicksBack or ticksBack parameters * will throw an {@link IllegalArgumentException}. */ - int MAX_TICKS_BACK = 20; + int MAX_TICKS_BACK = 100; /** * @return The amount of ticks worth of history being held. The number returned by this method will never be higher diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index e2893b264..12941677f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -402,9 +402,9 @@ public void tick(LocalPlayer player) { { if (tracker.tickType() == Tracker.TrackerTickType.PER_TICK) { - tracker.idleTick(mc.player); - if (tracker.isActive(mc.player)) { - tracker.doProcess(mc.player); + tracker.idleTick(player); + if (tracker.isActive(player)) { + tracker.doProcess(player); } else { tracker.reset(player); } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java index 75479e563..dac33315b 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java @@ -241,7 +241,7 @@ public void doProcess(LocalPlayer player) { for (Entity entity : mobs) { if (entity.isPickable() && entity != this.mc.getCameraEntity().getVehicle()) { if (entityAct) { - // Minecraft.getInstance().physicalGuiManager.preClickAction(); + // this.mc.physicalGuiManager.preClickAction(); if (!EpicFightHelper.isLoaded() || !EpicFightHelper.attack()) { ClientNetworking.sendActiveBodyPart(BodyPart.values()[i]); 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 0409cb046..366d21fcd 100644 --- a/common/src/main/java/org/vivecraft/common/utils/MathUtils.java +++ b/common/src/main/java/org/vivecraft/common/utils/MathUtils.java @@ -235,7 +235,7 @@ public static float bodyYawRad(Vector3fc rightHand, Vector3fc leftHand, Vector3f } /** - * Converst a {@link Vector3fc} to a {@link Vec3}. + * Converts a {@link Vector3fc} to a {@link Vec3}. * @param vec The original Vector3fc. * @return The Vec3. */ From 58c9d91fdf1af810f2cb0c40556f41f9c104f238 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:45:17 -0500 Subject: [PATCH 22/33] Adjust Names and Javadocs for Room Pose Client Methods --- .../java/org/vivecraft/api/client/VRClientAPI.java | 13 +++++-------- .../vivecraft/client/api_impl/VRClientAPIImpl.java | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index 00d1effdf..4ad832924 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -26,13 +26,12 @@ static VRClientAPI getInstance() { void registerTracker(Tracker tracker); /** - * Gets the VR pose representing the player in the room before the game tick. - * Note that this pose is gathered BEFORE mod loaders' pre-tick events. + * Gets the VR pose representing the player in the room after the most recent poll of VR hardware. * - * @return The VR pose representing the player in the room pre-tick, or null if the local player isn't in VR. + * @return The most up-to-date VR pose representing the player in the room, or null if the local player isn't in VR. */ @Nullable - VRPose getPreTickRoomPose(); + VRPose getLatestRoomPose(); /** * Gets the VR pose representing the player in the room after the game tick. @@ -44,10 +43,8 @@ static VRClientAPI getInstance() { VRPose getPostTickRoomPose(); /** - * Gets the VR pose representing the player in Minecraft world coordinates before the game tick. - * This is the same as {@link #getPreTickRoomPose()} with translation to in-game world coordinates as of the last - * tick, and is the main pose source used by Vivecraft for gameplay. If you're unsure which {@link VRPose} method - * to use, you likely want to use this one. + * Gets the VR pose representing the player in Minecraft world coordinates before the game tick. If you're unsure + * which {@link VRPose} method to use, you very likely want to use this one. * Note that this pose is gathered BEFORE mod loaders' pre-tick events. * * @return The VR pose representing the player in world space pre-tick, or null if the local player isn't in VR. diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index 5b160e53d..4e30112a4 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -31,7 +31,7 @@ public void addPosesToHistory(VRPose pose) { @Nullable @Override - public VRPose getPreTickRoomPose() { + public VRPose getLatestRoomPose() { if (!isVRActive()) { return null; } From be1382546af58fc91f966b36173be56bd3c8e702 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 16:49:23 -0500 Subject: [PATCH 23/33] Fix Undoing Refactor Changes --- .../gameplay/trackers/RowTracker.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java index 135130740..bbdfe79f2 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/RowTracker.java @@ -31,21 +31,19 @@ public RowTracker(Minecraft mc, ClientDataHolderVR dh) { this.dh = dh; } - public boolean isActive(LocalPlayer p) { + public boolean isActive(LocalPlayer player) { if (this.dh.vrSettings.seated) { return false; } else if (!this.dh.vrSettings.realisticRowEnabled) { return false; - } else if (p != null && p.isAlive()) { - if (this.mc.gameMode == null) { - return false; - } else if (this.mc.options.keyUp.isDown()) { - return false; - } else if (!(p.getVehicle() instanceof Boat)) { - return false; - } else { - return !this.dh.bowTracker.isNotched(); - } + } else if (player == null || !player.isAlive()) { + return false; + } else if (this.mc.gameMode == null) { + return false; + } else if (this.mc.options.keyUp.isDown()) { // important + return false; + } else if (!(player.getVehicle() instanceof Boat)) { + return false; } else { return !this.dh.bowTracker.isNotched(); } From 45e8f42dcb8984bcda7628cbbdd856567e5ade24 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Thu, 16 Jan 2025 17:19:03 -0500 Subject: [PATCH 24/33] VRPoseHistory Fixes --- .../api_impl/data/VRPoseHistoryImpl.java | 77 +++++++++++-------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java index e8e63fb75..856048cb8 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java @@ -6,9 +6,11 @@ import org.vivecraft.api.data.VRBodyPartData; import org.vivecraft.api.data.VRPose; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.stream.DoubleStream; public class VRPoseHistoryImpl implements VRPoseHistory { @@ -19,7 +21,7 @@ public VRPoseHistoryImpl() { public void addPose(VRPose pose) { this.dataQueue.addFirst(pose); - if (this.dataQueue.size() > VRPoseHistory.MAX_TICKS_BACK) { + if (this.dataQueue.size() > VRPoseHistory.MAX_TICKS_BACK + 1) { this.dataQueue.removeLast(); } } @@ -69,51 +71,66 @@ public Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArg public Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); - VRBodyPartData currentData = this.dataQueue.getLast().getBodyPartData(bodyPart); - if (currentData == null) { - return null; + maxTicksBack = getNumTicksBack(maxTicksBack); + List diffs = new ArrayList<>(maxTicksBack); + for (int i = 0; i < maxTicksBack; i++) { + VRBodyPartData newer = dataQueue.get(i).getBodyPartData(bodyPart); + VRBodyPartData older = dataQueue.get(i + 1).getBodyPartData(bodyPart); + if (newer == null || older == null) { + break; + } + diffs.add(newer.getPos().subtract(older.getPos())); } - Vec3 current = currentData.getPos(); - VRBodyPartData oldData = getOldPose(maxTicksBack).getBodyPartData(bodyPart); - if (oldData == null) { - return null; + if (diffs.isEmpty()) { + // Return no change if the body part is available but no historical data or null if body part isn't + // available. + return dataQueue.getFirst().getBodyPartData(bodyPart) != null ? Vec3.ZERO : null; } - Vec3 old = oldData.getPos(); - return current.subtract(old).scale(1d / getNumTicksBack(maxTicksBack)); + return new Vec3( + diffs.stream().mapToDouble(vec -> vec.x).average().orElse(0), + diffs.stream().mapToDouble(vec -> vec.y).average().orElse(0), + diffs.stream().mapToDouble(vec -> vec.z).average().orElse(0) + ); } @Override public double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { - Vec3 averageVelocity = averageVelocity(bodyPart, maxTicksBack); - if (averageVelocity == null) { - return 0; + checkPartNonNull(bodyPart); + checkTicksBack(maxTicksBack); + maxTicksBack = getNumTicksBack(maxTicksBack); + List speeds = new ArrayList<>(maxTicksBack); + for (int i = 0; i < maxTicksBack; i++) { + VRBodyPartData newer = dataQueue.get(i).getBodyPartData(bodyPart); + VRBodyPartData older = dataQueue.get(i + 1).getBodyPartData(bodyPart); + if (newer == null || older == null) { + break; + } + speeds.add(newer.getPos().distanceTo(older.getPos())); } - return Math.sqrt(averageVelocity.x() * averageVelocity.x() + - averageVelocity.y() * averageVelocity.y() + - averageVelocity.z() * averageVelocity.z()); + return speeds.stream().mapToDouble(Double::valueOf).average().orElse(0); } @Override public Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); - int iters = getNumTicksBack(maxTicksBack); - VRBodyPartData currentData = this.dataQueue.getLast().getBodyPartData(bodyPart); - if (currentData == null) { - return null; - } - ListIterator iterator = this.dataQueue.listIterator(this.dataQueue.size() - 1); - Vec3 avg = currentData.getPos(); - int i = iters; - while (i > 0) { - VRBodyPartData oldData = iterator.previous().getBodyPartData(bodyPart); - if (oldData == null) { + maxTicksBack = getNumTicksBack(maxTicksBack); + List positions = new ArrayList<>(maxTicksBack); + for (VRPose pose : dataQueue) { + VRBodyPartData data = pose.getBodyPartData(bodyPart); + if (data == null) { break; } - avg = avg.add(oldData.getPos()); - i--; + positions.add(data.getPos()); + } + if (positions.isEmpty()) { + return null; } - return avg.scale(1d / (iters + 1)); + return new Vec3( + positions.stream().mapToDouble(vec -> vec.x).average().orElse(0), + positions.stream().mapToDouble(vec -> vec.y).average().orElse(0), + positions.stream().mapToDouble(vec -> vec.z).average().orElse(0) + ); } private void checkTicksBack(int ticksBack) { From dd8b95d1d1bd53dd761936bc01f6e0eb49096919 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Fri, 17 Jan 2025 10:58:29 -0500 Subject: [PATCH 25/33] Merge VRBodyPart to One Enum --- .../org/vivecraft/api/data/VRBodyPart.java | 31 +++++++---- .../client/network/ClientNetworking.java | 8 +-- .../gameplay/trackers/SwingTracker.java | 8 +-- .../vivecraft/common/network/BodyPart.java | 52 ------------------- .../common/network/VrPlayerState.java | 4 +- .../packet/c2s/ActiveBodyPartPayloadC2S.java | 10 ++-- .../advancements/PlayerPredicateMixin.java | 6 +-- .../MultiPlayerGameModeVRMixin.java | 8 +-- .../mixin/world/entity/InventoryMixin.java | 8 +-- .../vivecraft/server/ServerNetworking.java | 4 +- .../java/org/vivecraft/server/ServerUtil.java | 6 +-- .../vivecraft/server/ServerVivePlayer.java | 24 ++++----- 12 files changed, 64 insertions(+), 105 deletions(-) delete mode 100644 common/src/main/java/org/vivecraft/common/network/BodyPart.java diff --git a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java index 06a269f4e..4963f96e4 100644 --- a/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java +++ b/common/src/main/java/org/vivecraft/api/data/VRBodyPart.java @@ -1,10 +1,6 @@ package org.vivecraft.api.data; -/** - * The device tracking a specific body part. - */ public enum VRBodyPart { - HMD, MAIN_HAND, OFF_HAND, RIGHT_FOOT, @@ -13,10 +9,11 @@ public enum VRBodyPart { RIGHT_KNEE, LEFT_KNEE, RIGHT_ELBOW, - LEFT_ELBOW; + LEFT_ELBOW, + HMD; /** - * @return The opposite body part to this one, or the same body part if it has no opposite. + * @return the opposite limb */ public VRBodyPart opposite() { return switch (this) { @@ -34,14 +31,28 @@ public VRBodyPart opposite() { /** * Whether this body part type is available in the provided full-body tracking mode. - * @param mode The full-body tracking mode to check. + * @param fbtMode The full-body tracking mode to check. * @return Whether this body part has available data in the provided mode. */ - public boolean availableInMode(FBTMode mode) { + public boolean availableInMode(FBTMode fbtMode) { return switch (this) { case HMD, MAIN_HAND, OFF_HAND -> true; - case RIGHT_FOOT, LEFT_FOOT, WAIST -> mode != FBTMode.ARMS_ONLY; - case RIGHT_KNEE, LEFT_KNEE, RIGHT_ELBOW, LEFT_ELBOW -> mode == FBTMode.WITH_JOINTS; + case RIGHT_FOOT, LEFT_FOOT, WAIST -> fbtMode != FBTMode.ARMS_ONLY; + case RIGHT_KNEE, LEFT_KNEE, RIGHT_ELBOW, LEFT_ELBOW -> fbtMode == FBTMode.WITH_JOINTS; }; } + + /** + * @return Whether this body part is a foot. + */ + public boolean isFoot() { + return this == RIGHT_FOOT || this == LEFT_FOOT; + } + + /** + * @return Whether this body part is a hand. + */ + public boolean isHand() { + return this == MAIN_HAND || this == OFF_HAND; + } } diff --git a/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java b/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java index d4d5ff9e0..547700f80 100644 --- a/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java +++ b/common/src/main/java/org/vivecraft/client/network/ClientNetworking.java @@ -23,7 +23,7 @@ import org.vivecraft.common.CommonDataHolder; import org.vivecraft.common.VRServerPerms; import org.vivecraft.common.network.CommonNetworkHelper; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.common.network.packet.c2s.*; import org.vivecraft.common.network.packet.s2c.*; @@ -51,7 +51,7 @@ public class ClientNetworking { private static float CAPTURED_YAW; private static float CAPTURED_PITCH; private static boolean OVERRIDE_ACTIVE; - public static BodyPart LAST_SENT_BODY_PART = BodyPart.MAIN_HAND; + public static VRBodyPart LAST_SENT_BODY_PART = VRBodyPart.MAIN_HAND; public static boolean NEEDS_RESET = true; @@ -193,11 +193,11 @@ public static int getTeleportHorizLimit() { public static void sendActiveHand(InteractionHand hand) { if (SERVER_WANTS_DATA) { - sendActiveBodyPart(hand == InteractionHand.MAIN_HAND ? BodyPart.MAIN_HAND : BodyPart.OFF_HAND); + sendActiveBodyPart(hand == InteractionHand.MAIN_HAND ? VRBodyPart.MAIN_HAND : VRBodyPart.OFF_HAND); } } - public static void sendActiveBodyPart(BodyPart bodyPart) { + public static void sendActiveBodyPart(VRBodyPart bodyPart) { if (SERVER_WANTS_DATA) { // only send if the hand is different from last time, don't need to spam packets if (bodyPart != LAST_SENT_BODY_PART) { diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java index dac33315b..595099696 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/SwingTracker.java @@ -35,7 +35,7 @@ import org.vivecraft.client_vr.Vector3fHistory; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.api.data.FBTMode; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.BlockTags; import org.vivecraft.data.ItemTags; @@ -244,7 +244,7 @@ public void doProcess(LocalPlayer player) { // this.mc.physicalGuiManager.preClickAction(); if (!EpicFightHelper.isLoaded() || !EpicFightHelper.attack()) { - ClientNetworking.sendActiveBodyPart(BodyPart.values()[i]); + ClientNetworking.sendActiveBodyPart(VRBodyPart.values()[i]); // only attack if epic fight didn't trigger this.mc.gameMode.attack(player, entity); } else { @@ -358,7 +358,7 @@ else if (blockstate.getBlock() instanceof NoteBlock || // this.mc.physicalGuiManager.preClickAction(); // send hitting hand - ClientNetworking.sendActiveBodyPart(BodyPart.values()[i]); + ClientNetworking.sendActiveBodyPart(VRBodyPart.values()[i]); // this will either destroy the block if in creative or set it as the current block. // does nothing in survival if you are already hitting this block. @@ -400,7 +400,7 @@ else if (blockstate.getBlock() instanceof NoteBlock || } // reset hitting hand - ClientNetworking.sendActiveBodyPart(BodyPart.MAIN_HAND); + ClientNetworking.sendActiveBodyPart(VRBodyPart.MAIN_HAND); this.mc.getProfiler().pop(); } diff --git a/common/src/main/java/org/vivecraft/common/network/BodyPart.java b/common/src/main/java/org/vivecraft/common/network/BodyPart.java deleted file mode 100644 index 86670f413..000000000 --- a/common/src/main/java/org/vivecraft/common/network/BodyPart.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.vivecraft.common.network; - -import org.vivecraft.api.data.FBTMode; - -public enum BodyPart { - MAIN_HAND, - OFF_HAND, - RIGHT_FOOT, - LEFT_FOOT, - WAIST, - RIGHT_KNEE, - LEFT_KNEE, - RIGHT_ELBOW, - LEFT_ELBOW; - - /** - * @return the opposite limb - */ - public BodyPart opposite() { - return switch (this) { - case MAIN_HAND -> OFF_HAND; - case OFF_HAND -> MAIN_HAND; - case RIGHT_FOOT -> LEFT_FOOT; - case LEFT_FOOT -> RIGHT_FOOT; - case RIGHT_KNEE -> LEFT_KNEE; - case LEFT_KNEE -> RIGHT_KNEE; - case RIGHT_ELBOW -> LEFT_ELBOW; - case LEFT_ELBOW -> RIGHT_ELBOW; - default -> this; - }; - } - - /** - * @param fbtMode FBT mode to check for - * @return if {@code this} limb is valid for the given FBT mode - */ - public boolean isValid(FBTMode fbtMode) { - return switch (this) { - case MAIN_HAND, OFF_HAND -> true; - case RIGHT_FOOT, LEFT_FOOT, WAIST -> fbtMode != FBTMode.ARMS_ONLY; - 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/common/network/VrPlayerState.java b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java index 974499ab9..41bfcfc5a 100644 --- a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java +++ b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java @@ -5,6 +5,7 @@ import net.minecraft.world.phys.Vec3; import org.joml.Quaternionf; import org.joml.Vector3f; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.api.data.FBTMode; import org.vivecraft.api.data.VRBodyPartData; import org.vivecraft.client.network.ClientNetworking; @@ -196,7 +197,7 @@ public static VrPlayerState deserialize(FriendlyByteBuf buffer, int bytesAfter) * @return Pose of the {@code bodyPart}, or {@code null} if the body part is not valid for the current FBT mode */ @Nullable - public Pose getBodyPartPose(BodyPart bodyPart) { + public Pose getBodyPartPose(VRBodyPart bodyPart) { return switch(bodyPart) { case MAIN_HAND -> this.mainHand; case OFF_HAND -> this.offHand; @@ -207,6 +208,7 @@ public Pose getBodyPartPose(BodyPart bodyPart) { case LEFT_KNEE -> this.leftKnee; case RIGHT_KNEE -> this.rightKnee; case WAIST -> this.waist; + case HMD -> this.hmd; }; } diff --git a/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java b/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java index 15bd9eb50..2d4f40a18 100644 --- a/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java +++ b/common/src/main/java/org/vivecraft/common/network/packet/c2s/ActiveBodyPartPayloadC2S.java @@ -3,7 +3,7 @@ import net.minecraft.network.FriendlyByteBuf; import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.common.network.CommonNetworkHelper; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.api.data.FBTMode; import org.vivecraft.common.network.packet.PayloadIdentifier; @@ -12,7 +12,7 @@ * * @param bodyPart the active BodyPart */ -public record ActiveBodyPartPayloadC2S(BodyPart bodyPart) implements VivecraftPayloadC2S { +public record ActiveBodyPartPayloadC2S(VRBodyPart bodyPart) implements VivecraftPayloadC2S { @Override public PayloadIdentifier payloadId() { @@ -23,16 +23,16 @@ public PayloadIdentifier payloadId() { public void write(FriendlyByteBuf buffer) { buffer.writeByte(payloadId().ordinal()); if (ClientNetworking.USED_NETWORK_VERSION < CommonNetworkHelper.NETWORK_VERSION_DUAL_WIELDING && - !this.bodyPart.isValid(FBTMode.ARMS_ONLY)) + !this.bodyPart.availableInMode(FBTMode.ARMS_ONLY)) { // old plugins only support main and offhand - buffer.writeByte(BodyPart.MAIN_HAND.ordinal()); + buffer.writeByte(VRBodyPart.MAIN_HAND.ordinal()); } else { buffer.writeByte(this.bodyPart.ordinal()); } } public static ActiveBodyPartPayloadC2S read(FriendlyByteBuf buffer) { - return new ActiveBodyPartPayloadC2S(BodyPart.values()[buffer.readByte()]); + return new ActiveBodyPartPayloadC2S(VRBodyPart.values()[buffer.readByte()]); } } diff --git a/common/src/main/java/org/vivecraft/mixin/advancements/PlayerPredicateMixin.java b/common/src/main/java/org/vivecraft/mixin/advancements/PlayerPredicateMixin.java index d9dbbcedb..61f517c1f 100644 --- a/common/src/main/java/org/vivecraft/mixin/advancements/PlayerPredicateMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/advancements/PlayerPredicateMixin.java @@ -10,7 +10,7 @@ import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.server.ServerVRPlayers; import org.vivecraft.server.ServerVivePlayer; @@ -24,7 +24,7 @@ public class PlayerPredicateMixin { if (player.getUseItem().is(Items.SPYGLASS) && ServerVRPlayers.isVRPlayer(player)) { vivePlayer.set(ServerVRPlayers.getVivePlayer(player)); if (!vivePlayer.get().isSeated()) { - return vivePlayer.get().getBodyPartPos(BodyPart.values()[player.getUsedItemHand().ordinal()]); + return vivePlayer.get().getBodyPartPos(VRBodyPart.values()[player.getUsedItemHand().ordinal()]); } } return original.call(player); @@ -37,7 +37,7 @@ public class PlayerPredicateMixin { { if (vivePlayer.get() != null && !vivePlayer.get().isSeated()) { return vivePlayer.get() - .getBodyPartVectorCustom(BodyPart.values()[player.getUsedItemHand().ordinal()], MathUtils.DOWN); + .getBodyPartVectorCustom(VRBodyPart.values()[player.getUsedItemHand().ordinal()], MathUtils.DOWN); } else { return original.call(player, partialTick); } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/MultiPlayerGameModeVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/MultiPlayerGameModeVRMixin.java index 5e48441ff..30815097c 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/MultiPlayerGameModeVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/multiplayer/MultiPlayerGameModeVRMixin.java @@ -20,7 +20,7 @@ import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; /** * we override the players look direction so the server handles any interactions as if the player looked at the interacted block @@ -66,12 +66,12 @@ public class MultiPlayerGameModeVRMixin { if (VRState.VR_RUNNING && ClientNetworking.SERVER_ALLOWS_DUAL_WIELDING) { // check if main or offhand items match the started item, we want to limit abuse of this, // but still make both items work - BodyPart lastBodyPart = ClientNetworking.LAST_SENT_BODY_PART; + VRBodyPart lastBodyPart = ClientNetworking.LAST_SENT_BODY_PART; - ClientNetworking.LAST_SENT_BODY_PART = BodyPart.MAIN_HAND; + ClientNetworking.LAST_SENT_BODY_PART = VRBodyPart.MAIN_HAND; boolean sameItem = original.call(pos); - ClientNetworking.LAST_SENT_BODY_PART = BodyPart.OFF_HAND; + ClientNetworking.LAST_SENT_BODY_PART = VRBodyPart.OFF_HAND; sameItem |= original.call(pos); ClientNetworking.LAST_SENT_BODY_PART = lastBodyPart; diff --git a/common/src/main/java/org/vivecraft/mixin/world/entity/InventoryMixin.java b/common/src/main/java/org/vivecraft/mixin/world/entity/InventoryMixin.java index 3b124d8ec..5b5129c01 100644 --- a/common/src/main/java/org/vivecraft/mixin/world/entity/InventoryMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/world/entity/InventoryMixin.java @@ -17,7 +17,7 @@ import org.vivecraft.client.network.ClientNetworking; import org.vivecraft.client_vr.VRState; import org.vivecraft.common.network.CommonNetworkHelper; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.server.ServerVRPlayers; import org.vivecraft.server.ServerVivePlayer; import org.vivecraft.server.config.ServerConfig; @@ -44,7 +44,7 @@ public class InventoryMixin { @Unique private ItemStack vivecraft$activeItem(ItemStack original) { - BodyPart bodyPart = null; + VRBodyPart bodyPart = null; // server side if (this.player instanceof ServerPlayer serverPlayer && ServerConfig.DUAL_WIELDING.get()) { if (ServerVRPlayers.isVRPlayer(serverPlayer)) { @@ -61,9 +61,9 @@ else if (this.player.isLocalPlayer() && VRState.VR_RUNNING && ClientNetworking.S } if (bodyPart != null) { - if (bodyPart == BodyPart.OFF_HAND) { + if (bodyPart == VRBodyPart.OFF_HAND) { return this.offhand.get(0); - } else if (bodyPart != BodyPart.MAIN_HAND) { + } else if (bodyPart != VRBodyPart.MAIN_HAND) { // feet return ItemStack.EMPTY; } diff --git a/common/src/main/java/org/vivecraft/server/ServerNetworking.java b/common/src/main/java/org/vivecraft/server/ServerNetworking.java index fcc337efe..df15bbfb0 100644 --- a/common/src/main/java/org/vivecraft/server/ServerNetworking.java +++ b/common/src/main/java/org/vivecraft/server/ServerNetworking.java @@ -19,7 +19,7 @@ import org.vivecraft.common.CommonDataHolder; import org.vivecraft.common.network.CommonNetworkHelper; import org.vivecraft.api.data.FBTMode; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.network.VrPlayerState; import org.vivecraft.common.network.packet.PayloadIdentifier; import org.vivecraft.common.network.packet.c2s.*; @@ -194,7 +194,7 @@ public static void handlePacket( player.connection.aboveGroundTickCount = 0; } case ACTIVEHAND -> { - BodyPart newBodyPart = vivePlayer.isSeated() ? BodyPart.MAIN_HAND : ((ActiveBodyPartPayloadC2S) c2sPayload).bodyPart(); + VRBodyPart newBodyPart = vivePlayer.isSeated() ? VRBodyPart.MAIN_HAND : ((ActiveBodyPartPayloadC2S) c2sPayload).bodyPart(); if (vivePlayer.activeBodyPart != newBodyPart) { // handle equipment changes ItemStack oldItem = player.getItemBySlot(EquipmentSlot.MAINHAND); diff --git a/common/src/main/java/org/vivecraft/server/ServerUtil.java b/common/src/main/java/org/vivecraft/server/ServerUtil.java index fd9bad517..3766dbd34 100644 --- a/common/src/main/java/org/vivecraft/server/ServerUtil.java +++ b/common/src/main/java/org/vivecraft/server/ServerUtil.java @@ -19,7 +19,7 @@ import org.joml.Quaternionfc; import org.joml.Vector3f; import org.vivecraft.client.utils.UpdateChecker; -import org.vivecraft.common.network.BodyPart; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.server.config.ConfigBuilder; import org.vivecraft.server.config.ServerConfig; @@ -338,8 +338,8 @@ public static void registerCommands( */ public static void debugParticleAxes(ServerVivePlayer vivePlayer) { if (vivePlayer.isVR() && vivePlayer.vrPlayerState != null) { - for(BodyPart bodyPart : BodyPart.values()) { - if (bodyPart.isValid(vivePlayer.vrPlayerState.fbtMode())) { + for(VRBodyPart bodyPart : VRBodyPart.values()) { + if (bodyPart.availableInMode(vivePlayer.vrPlayerState.fbtMode()) && bodyPart != VRBodyPart.HMD) { debugParticleAxes( vivePlayer.player.serverLevel(), vivePlayer.getBodyPartPos(bodyPart), diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index bbcd6390a..1f170dc4c 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -3,14 +3,12 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; -import org.joml.Quaternionfc; import org.joml.Vector3f; import org.joml.Vector3fc; -import org.vivecraft.common.network.*; +import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.api.data.VRPose; import org.vivecraft.common.network.CommonNetworkHelper; -import org.vivecraft.common.network.Pose; import org.vivecraft.common.network.VrPlayerState; import javax.annotation.Nullable; @@ -23,7 +21,7 @@ public class ServerVivePlayer { public float draw; public float worldScale = 1.0F; public float heightScale = 1.0F; - public BodyPart activeBodyPart = BodyPart.MAIN_HAND; + public VRBodyPart activeBodyPart = VRBodyPart.MAIN_HAND; public boolean crawling; // if the player has VR active private boolean isVR = false; @@ -45,10 +43,10 @@ public ServerVivePlayer(ServerPlayer player) { * @param direction local direction to transform * @return direction in world space */ - public Vec3 getBodyPartVectorCustom(BodyPart bodyPart, Vector3fc direction) { + public Vec3 getBodyPartVectorCustom(VRBodyPart bodyPart, Vector3fc direction) { if (this.vrPlayerState != null) { - if (this.isSeated() || !bodyPart.isValid(this.vrPlayerState.fbtMode())) { - bodyPart = BodyPart.MAIN_HAND; + if (this.isSeated() || !bodyPart.availableInMode(this.vrPlayerState.fbtMode())) { + bodyPart = VRBodyPart.MAIN_HAND; } return new Vec3( @@ -62,7 +60,7 @@ public Vec3 getBodyPartVectorCustom(BodyPart bodyPart, Vector3fc direction) { * @param bodyPart BodyPart to get the direction from, if not available, will use the MAIN_HAND * @return forward direction of the given BodyPart */ - public Vec3 getBodyPartDir(BodyPart bodyPart) { + public Vec3 getBodyPartDir(VRBodyPart bodyPart) { return this.getBodyPartVectorCustom(bodyPart, MathUtils.BACK); } @@ -109,17 +107,17 @@ public Vec3 getHMDPos() { * @param realPosition if true disables the seated override * @return BodyPart position in world space */ - public Vec3 getBodyPartPos(BodyPart bodyPart, boolean realPosition) { + public Vec3 getBodyPartPos(VRBodyPart bodyPart, boolean realPosition) { if (this.vrPlayerState != null) { - if (!bodyPart.isValid(this.vrPlayerState.fbtMode())) { - bodyPart = BodyPart.MAIN_HAND; + if (!bodyPart.availableInMode(this.vrPlayerState.fbtMode())) { + bodyPart = VRBodyPart.MAIN_HAND; } // in seated the realPosition is at the head, // so reconstruct the seated position when wanting the visual position if (this.isSeated() && !realPosition) { Vec3 dir = this.getHMDDir(); - dir = dir.yRot(Mth.DEG_TO_RAD * (bodyPart == BodyPart.MAIN_HAND ? -35.0F : 35.0F)); + dir = dir.yRot(Mth.DEG_TO_RAD * (bodyPart == VRBodyPart.MAIN_HAND ? -35.0F : 35.0F)); dir = new Vec3(dir.x, 0.0D, dir.z); dir = dir.normalize(); return this.getHMDPos().add( @@ -143,7 +141,7 @@ public Vec3 getBodyPartPos(BodyPart bodyPart, boolean realPosition) { * @param bodyPart BodyPart to get the position for, if not available, will use the MAIN_HAND * @return BodyPart position in world space */ - public Vec3 getBodyPartPos(BodyPart bodyPart) { + public Vec3 getBodyPartPos(VRBodyPart bodyPart) { return getBodyPartPos(bodyPart, false); } From 428af8f67bcc8023d23364f3a9320a3341a987b4 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Mon, 20 Jan 2025 16:49:00 -0500 Subject: [PATCH 26/33] getInstance() --> instance() and Javadocs for a Couple --- common/src/main/java/org/vivecraft/api/VRAPI.java | 4 ++-- .../src/main/java/org/vivecraft/api/client/VRClientAPI.java | 5 ++++- .../main/java/org/vivecraft/api/client/VRRenderingAPI.java | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/VRAPI.java b/common/src/main/java/org/vivecraft/api/VRAPI.java index e333ce725..da608f17a 100644 --- a/common/src/main/java/org/vivecraft/api/VRAPI.java +++ b/common/src/main/java/org/vivecraft/api/VRAPI.java @@ -12,9 +12,9 @@ public interface VRAPI { /** - * @return The Vivecraft API instance for interacting with Vivecraft's API. + * @return The Vivecraft API instance for interacting with Vivecraft's common API. */ - static VRAPI getInstance() { + static VRAPI instance() { return VRAPIImpl.INSTANCE; } diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index 4ad832924..eaad02b66 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -13,7 +13,10 @@ */ public interface VRClientAPI { - static VRClientAPI getInstance() { + /** + * @return The Vivecraft API instance for interacting with Vivecraft's client API. + */ + static VRClientAPI instance() { return VRClientAPIImpl.INSTANCE; } diff --git a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java index 71d29f928..514f4dca0 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java @@ -13,7 +13,10 @@ */ public interface VRRenderingAPI { - static VRRenderingAPI getInstance() { + /** + * @return The Vivecraft API instance for interacting with Vivecraft's rendering API. + */ + static VRRenderingAPI instance() { return VRRenderingAPIImpl.INSTANCE; } From 5678cabb5280f24a597366a76502f1cfaacdd6da Mon Sep 17 00:00:00 2001 From: hammy275 Date: Tue, 21 Jan 2025 11:07:38 -0500 Subject: [PATCH 27/33] Refactor itemInUse() out to ItemInUseTracker --- .../api/client/ItemInUseTracker.java | 22 +++++++++++++++++++ .../org/vivecraft/api/client/Tracker.java | 11 ---------- .../client_vr/ClientDataHolderVR.java | 8 ++++++- .../gameplay/trackers/BowTracker.java | 3 ++- .../gameplay/trackers/EatingTracker.java | 3 ++- .../gameplay/trackers/TelescopeTracker.java | 3 ++- 6 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java diff --git a/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java b/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java new file mode 100644 index 000000000..d6fc7f90d --- /dev/null +++ b/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java @@ -0,0 +1,22 @@ +package org.vivecraft.api.client; + +import net.minecraft.client.player.LocalPlayer; + +/** + * An interface that should be implemented by {@link Tracker}s if they want to take advantage of + * {@link #itemInUse(LocalPlayer)}. + */ +public interface ItemInUseTracker { + + /** + * Called for the client player, to check if this tracker is currently causing the item to be used to not release + * the use key. In other words, if you want the item currently being held to act as the use key being held, one + * should call the use item function, then return true from this method while the item should still remain used. + * @param player The local player which is running this tracker. + * @return Whether the item should remain in use. + */ + default boolean itemInUse(LocalPlayer player) { + return false; + } + +} diff --git a/common/src/main/java/org/vivecraft/api/client/Tracker.java b/common/src/main/java/org/vivecraft/api/client/Tracker.java index ca0ad22e0..968e2a55a 100644 --- a/common/src/main/java/org/vivecraft/api/client/Tracker.java +++ b/common/src/main/java/org/vivecraft/api/client/Tracker.java @@ -37,17 +37,6 @@ public interface Tracker { */ TrackerTickType tickType(); - /** - * Called for the client player, to check if this tracker is currently causing the item to be used to not release - * the use key. In other words, if you want the item currently being held to act as the use key being held, one - * should call the use item function, then return true from this method while the item should still remain used. - * @param player The local player which is running this tracker. - * @return Whether the item should remain in use. - */ - default boolean itemInUse(LocalPlayer player) { - return false; - } - /** * Called to reset this tracker's state. This is called whenever {@link #isActive(LocalPlayer)} returns false. * diff --git a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java index c15e6be4c..59cc1a9d1 100644 --- a/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/ClientDataHolderVR.java @@ -4,6 +4,7 @@ import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.world.entity.HumanoidArm; +import org.vivecraft.api.client.ItemInUseTracker; import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.gameplay.VRPlayer; import org.vivecraft.client_vr.gameplay.trackers.*; @@ -44,6 +45,8 @@ public class ClientDataHolderVR { // list of all registered trackers private final List trackers = new ArrayList<>(); + // list of all trackers that control holding item usage + private final List itemInUseTrackers = new ArrayList<>(); // our trackers public final BackpackTracker backpackTracker = createTracker(BackpackTracker::new); @@ -136,6 +139,9 @@ public void registerTracker(Tracker tracker) throws IllegalArgumentException { throw new IllegalArgumentException("Tracker is already added and should not be added again!"); } this.trackers.add(tracker); + if (tracker instanceof ItemInUseTracker itemInUseTracker) { + this.itemInUseTrackers.add(itemInUseTracker); + } } /** @@ -150,6 +156,6 @@ public List getTrackers() { * @return Whether some tracker is currently using an item. */ public boolean isTrackerUsingItem(LocalPlayer player) { - return this.trackers.stream().anyMatch(tracker -> tracker.itemInUse(player)); + return this.itemInUseTrackers.stream().anyMatch(tracker -> tracker.itemInUse(player)); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java index e07c85469..f761bdaa7 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/BowTracker.java @@ -1,5 +1,6 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.ItemInUseTracker; import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.extensions.PlayerExtension; @@ -31,7 +32,7 @@ import org.vivecraft.common.network.packet.c2s.DrawPayloadC2S; import org.vivecraft.common.utils.MathUtils; -public class BowTracker implements Tracker { +public class BowTracker implements Tracker, ItemInUseTracker { private static final long MAX_DRAW_MILLIS = 1100L; private static final double NOTCH_DOT_THRESHOLD = 20F; diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java index 31accce51..dedd85bc9 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/EatingTracker.java @@ -1,5 +1,6 @@ package org.vivecraft.client_vr.gameplay.trackers; +import org.vivecraft.api.client.ItemInUseTracker; import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -13,7 +14,7 @@ import org.vivecraft.common.utils.MathUtils; import org.vivecraft.client_vr.VRData; -public class EatingTracker implements Tracker { +public class EatingTracker implements Tracker, ItemInUseTracker { private static final float MOUTH_TO_EYE_DISTANCE = 0.0F; private static final float THRESHOLD = 0.25F; private static final long EAT_TIME = 2100L; diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java index 292766730..f2b5d7fe6 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/trackers/TelescopeTracker.java @@ -8,6 +8,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.joml.Vector3f; +import org.vivecraft.api.client.ItemInUseTracker; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.api.client.Tracker; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -16,7 +17,7 @@ import org.vivecraft.common.utils.MathUtils; import org.vivecraft.data.ItemTags; -public class TelescopeTracker implements Tracker { +public class TelescopeTracker implements Tracker, ItemInUseTracker { public static final ModelResourceLocation SCOPE_MODEL = new ModelResourceLocation("vivecraft", "spyglass_in_hand", "inventory"); private static final float LENS_DIST_MAX = 0.05F; From 3459c65fe9400441a5be609cf38315b4ae11ff39 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Tue, 21 Jan 2025 11:11:22 -0500 Subject: [PATCH 28/33] Make Not Default --- .../main/java/org/vivecraft/api/client/ItemInUseTracker.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java b/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java index d6fc7f90d..82b6b5277 100644 --- a/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java +++ b/common/src/main/java/org/vivecraft/api/client/ItemInUseTracker.java @@ -15,8 +15,6 @@ public interface ItemInUseTracker { * @param player The local player which is running this tracker. * @return Whether the item should remain in use. */ - default boolean itemInUse(LocalPlayer player) { - return false; - } + boolean itemInUse(LocalPlayer player); } From 769b972575156f162c1358173b43c5e46e8b76e5 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 26 Jan 2025 11:16:35 -0500 Subject: [PATCH 29/33] Cache VRPoses and Only Make VRPoseHistory When Needed --- .../org/vivecraft/api/client/VRClientAPI.java | 3 +- .../org/vivecraft/client/ClientVRPlayers.java | 35 +++++++++++-------- .../client/api_impl/VRClientAPIImpl.java | 11 ++++-- .../java/org/vivecraft/client_vr/VRData.java | 35 +++++++++++-------- .../java/org/vivecraft/client_vr/VRState.java | 2 +- .../client_vr/gameplay/VRPlayer.java | 6 +++- .../common/network/VrPlayerState.java | 2 +- .../ServerGamePacketListenerImplMixin.java | 2 +- .../vivecraft/server/ServerNetworking.java | 10 +++--- .../java/org/vivecraft/server/ServerUtil.java | 8 ++--- .../vivecraft/server/ServerVivePlayer.java | 18 ++++++++-- 11 files changed, 84 insertions(+), 48 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index eaad02b66..9c5e2dc71 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -136,7 +136,8 @@ default void triggerHapticPulse(int controllerNum, float duration) { float getWorldScale(); /** - * Returns the history of VR poses for the player. Will return null if the player isn't in VR. + * Returns the history of VR poses for the player. Must be called at least once by some caller before the pose + * history is populated. * * @return The history of VR poses for the player, or null if the player isn't in VR. */ diff --git a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java index 22f76d88d..fc67d16e8 100644 --- a/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java +++ b/common/src/main/java/org/vivecraft/client/ClientVRPlayers.java @@ -551,6 +551,8 @@ public static class RotInfo { public Vector3fc leftElbowPos; public Quaternionfc leftElbowQuat; + private VRPose vrPose; + /** * IMPORTANT!!! when changing this, also change {@link VRData#getBodyYawRad()} */ @@ -575,21 +577,24 @@ public float getBodyYawRad() { } public VRPose asVRPose(Vec3 playerPos) { - return new VRPoseImpl( - makeBodyPartData(this.headPos, this.headRot, this.headQuat, playerPos), - makeBodyPartData(this.mainHandPos, this.mainHandRot, this.mainHandQuat, playerPos), - makeBodyPartData(this.offHandPos, this.offHandRot, this.offHandQuat, playerPos), - makeBodyPartData(this.rightFootPos, this.rightFootQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), - makeBodyPartData(this.leftFootPos, this.leftFootQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), - makeBodyPartData(this.waistPos, this.waistQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), - makeBodyPartData(this.rightKneePos, this.rightKneeQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), - makeBodyPartData(this.leftKneePos, this.leftKneeQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), - makeBodyPartData(this.rightElbowPos, this.rightElbowQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), - makeBodyPartData(this.leftElbowPos, this.leftElbowQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), - this.seated, - this.leftHanded, - this.fbtMode - ); + if (vrPose == null) { + vrPose = new VRPoseImpl( + makeBodyPartData(this.headPos, this.headRot, this.headQuat, playerPos), + makeBodyPartData(this.mainHandPos, this.mainHandRot, this.mainHandQuat, playerPos), + makeBodyPartData(this.offHandPos, this.offHandRot, this.offHandQuat, playerPos), + makeBodyPartData(this.rightFootPos, this.rightFootQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), + makeBodyPartData(this.leftFootPos, this.leftFootQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), + makeBodyPartData(this.waistPos, this.waistQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), + makeBodyPartData(this.rightKneePos, this.rightKneeQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), + makeBodyPartData(this.leftKneePos, this.leftKneeQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), + makeBodyPartData(this.rightElbowPos, this.rightElbowQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), + makeBodyPartData(this.leftElbowPos, this.leftElbowQuat, playerPos, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), + this.seated, + this.leftHanded, + this.fbtMode + ); + } + return vrPose; } } diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index 4e30112a4..8b7346add 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -17,18 +17,24 @@ public final class VRClientAPIImpl implements VRClientAPI { public static final VRClientAPIImpl INSTANCE = new VRClientAPIImpl(); private final VRPoseHistoryImpl poseHistory = new VRPoseHistoryImpl(); + private boolean gatherPoseHistory = false; private VRClientAPIImpl() { } - public void clearHistories() { + public void clearAndDisablePoseHistory() { this.poseHistory.clear(); + gatherPoseHistory = false; } - public void addPosesToHistory(VRPose pose) { + public void addPoseToHistory(VRPose pose) { this.poseHistory.addPose(pose); } + public boolean gatherPoseHistory() { + return this.gatherPoseHistory; + } + @Nullable @Override public VRPose getLatestRoomPose() { @@ -137,6 +143,7 @@ public VRPoseHistory getHistoricalVRPoses() { if (!isVRActive()) { return null; } + gatherPoseHistory = true; return this.poseHistory; } diff --git a/common/src/main/java/org/vivecraft/client_vr/VRData.java b/common/src/main/java/org/vivecraft/client_vr/VRData.java index 51eceb4f5..94157e8df 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRData.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRData.java @@ -66,6 +66,8 @@ public class VRData { // pose positions get scaled by that public float worldScale; + private VRPose vrPose; + public VRData(Vec3 origin, float walkMul, float worldScale, float rotation) { ClientDataHolderVR dataHolder = ClientDataHolderVR.getInstance(); MCVR mcVR = dataHolder.vr; @@ -368,21 +370,24 @@ public VRDevicePose getEye(RenderPass pass) { * @return this data in a manner better-suited for the API */ public VRPose asVRPose() { - return new VRPoseImpl( - this.hmd.asVRBodyPart(), - this.c0.asVRBodyPart(), - this.c1.asVRBodyPart(), - getDataIfAvailable(this.foot_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), - getDataIfAvailable(this.foot_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), - getDataIfAvailable(this.waist, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), - getDataIfAvailable(this.knee_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), - getDataIfAvailable(this.knee_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), - getDataIfAvailable(this.elbow_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), - getDataIfAvailable(this.elbow_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), - ClientDataHolderVR.getInstance().vrSettings.seated, - ClientDataHolderVR.getInstance().vrSettings.reverseHands, - this.fbtMode - ); + if (vrPose == null) { + vrPose = new VRPoseImpl( + this.hmd.asVRBodyPart(), + this.c0.asVRBodyPart(), + this.c1.asVRBodyPart(), + getDataIfAvailable(this.foot_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_FOOT)), + getDataIfAvailable(this.foot_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_FOOT)), + getDataIfAvailable(this.waist, this.fbtMode.bodyPartAvailable(VRBodyPart.WAIST)), + getDataIfAvailable(this.knee_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_KNEE)), + getDataIfAvailable(this.knee_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_KNEE)), + getDataIfAvailable(this.elbow_right, this.fbtMode.bodyPartAvailable(VRBodyPart.RIGHT_ELBOW)), + getDataIfAvailable(this.elbow_left, this.fbtMode.bodyPartAvailable(VRBodyPart.LEFT_ELBOW)), + ClientDataHolderVR.getInstance().vrSettings.seated, + ClientDataHolderVR.getInstance().vrSettings.reverseHands, + this.fbtMode + ); + } + return vrPose; } @Nullable diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index 1ced3e55b..f4d1be42b 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -153,6 +153,6 @@ public static void destroyVR(boolean disableVRSetting) { // this reloads any PostChain, at least in vanilla Minecraft.getInstance().levelRenderer.onResourceManagerReload(Minecraft.getInstance().getResourceManager()); } - VRClientAPIImpl.INSTANCE.clearHistories(); + VRClientAPIImpl.INSTANCE.clearAndDisablePoseHistory(); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 12941677f..81cbef30c 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -237,7 +237,11 @@ public void preTick() { this.dh.vrSettings.worldRotation = this.dh.vr.seatedRot; } - VRClientAPIImpl.INSTANCE.addPosesToHistory(this.vrdata_world_pre.asVRPose()); + // Gather VRPose history if some API consumer wants it and we're in a non-paused world. + if (VRClientAPIImpl.INSTANCE.gatherPoseHistory() && this.mc.level != null && + (this.mc.getSingleplayerServer() == null || !this.mc.getSingleplayerServer().isPaused())) { + VRClientAPIImpl.INSTANCE.addPoseToHistory(this.vrdata_world_pre.asVRPose()); + } } public void postTick() { diff --git a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java index 41bfcfc5a..7ff53c9bb 100644 --- a/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java +++ b/common/src/main/java/org/vivecraft/common/network/VrPlayerState.java @@ -244,7 +244,7 @@ public void serialize(FriendlyByteBuf buffer) { * * @return This object as a pose for use with the API. */ - public VRPoseImpl asPose(Vec3 playerPos) { + public VRPoseImpl asVRPose(Vec3 playerPos) { return new VRPoseImpl( this.hmd.asBodyPartData(playerPos), this.mainHand.asBodyPartData(playerPos), diff --git a/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java b/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java index 7712eba6c..b9731d48e 100644 --- a/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/server/ServerGamePacketListenerImplMixin.java @@ -45,7 +45,7 @@ public ServerGamePacketListenerImplMixin( if (this.player.hasDisconnected()) { // if they did disconnect remove them ServerVRPlayers.getPlayersWithVivecraft(this.player.server).remove(this.player.getUUID()); - } else if (vivePlayer.isVR() && vivePlayer.vrPlayerState != null) { + } else if (vivePlayer.isVR() && vivePlayer.vrPlayerState() != null) { ServerNetworking.sendVrPlayerStateToClients(vivePlayer); if (ServerConfig.DEBUG_PARTICLES.get()) { ServerUtil.debugParticleAxes(vivePlayer); diff --git a/common/src/main/java/org/vivecraft/server/ServerNetworking.java b/common/src/main/java/org/vivecraft/server/ServerNetworking.java index df15bbfb0..5713f54b3 100644 --- a/common/src/main/java/org/vivecraft/server/ServerNetworking.java +++ b/common/src/main/java/org/vivecraft/server/ServerNetworking.java @@ -182,7 +182,7 @@ public static void handlePacket( } } case DRAW -> vivePlayer.draw = ((DrawPayloadC2S) c2sPayload).draw(); - case VR_PLAYER_STATE -> vivePlayer.vrPlayerState = ((VRPlayerStatePayloadC2S) c2sPayload).playerState(); + case VR_PLAYER_STATE -> vivePlayer.setVrPlayerState(((VRPlayerStatePayloadC2S) c2sPayload).playerState()); case WORLDSCALE -> vivePlayer.worldScale = ((WorldScalePayloadC2S) c2sPayload).worldScale(); case HEIGHT -> vivePlayer.heightScale = ((HeightPayloadC2S) c2sPayload).heightScale(); case TELEPORT -> { @@ -239,7 +239,7 @@ public static void handlePacket( LegacyHeadDataPayloadC2S headData = (LegacyHeadDataPayloadC2S) playerData .get(PayloadIdentifier.HEADDATA); - vivePlayer.vrPlayerState = new VrPlayerState( + vivePlayer.setVrPlayerState(new VrPlayerState( headData.seated(), // isSeated headData.hmdPose(), // head pose controller0Data.leftHanded(), // leftHanded 0 @@ -249,7 +249,7 @@ public static void handlePacket( FBTMode.ARMS_ONLY, null, null, null, null, null, - null, null); + null, null)); LEGACY_DATA_MAP.remove(player.getUUID()); } @@ -287,10 +287,10 @@ public static VivecraftPayloadS2C getClimbeyServerPayload() { public static void sendVrPlayerStateToClients(ServerVivePlayer vivePlayer) { // create the packets here, to try to avoid unnecessary memory copies when creating multiple packets Packet legacyPacket = Xplat.getS2CPacket( - new UberPacketPayloadS2C(vivePlayer.player.getUUID(), new VrPlayerState(vivePlayer.vrPlayerState, 0), + new UberPacketPayloadS2C(vivePlayer.player.getUUID(), new VrPlayerState(vivePlayer.vrPlayerState(), 0), vivePlayer.worldScale, vivePlayer.heightScale)); Packet newPacket = Xplat.getS2CPacket( - new UberPacketPayloadS2C(vivePlayer.player.getUUID(), vivePlayer.vrPlayerState, vivePlayer.worldScale, + new UberPacketPayloadS2C(vivePlayer.player.getUUID(), vivePlayer.vrPlayerState(), vivePlayer.worldScale, vivePlayer.heightScale)); sendPacketToTrackingPlayers(vivePlayer, (version) -> version < 1 ? legacyPacket : newPacket); diff --git a/common/src/main/java/org/vivecraft/server/ServerUtil.java b/common/src/main/java/org/vivecraft/server/ServerUtil.java index 3766dbd34..470d1f277 100644 --- a/common/src/main/java/org/vivecraft/server/ServerUtil.java +++ b/common/src/main/java/org/vivecraft/server/ServerUtil.java @@ -337,13 +337,13 @@ public static void registerCommands( * @param vivePlayer vive vivePlayer to spawn particles for */ public static void debugParticleAxes(ServerVivePlayer vivePlayer) { - if (vivePlayer.isVR() && vivePlayer.vrPlayerState != null) { + if (vivePlayer.isVR() && vivePlayer.vrPlayerState() != null) { for(VRBodyPart bodyPart : VRBodyPart.values()) { - if (bodyPart.availableInMode(vivePlayer.vrPlayerState.fbtMode()) && bodyPart != VRBodyPart.HMD) { + if (bodyPart.availableInMode(vivePlayer.vrPlayerState().fbtMode()) && bodyPart != VRBodyPart.HMD) { debugParticleAxes( vivePlayer.player.serverLevel(), vivePlayer.getBodyPartPos(bodyPart), - vivePlayer.vrPlayerState.getBodyPartPose(bodyPart).orientation()); + vivePlayer.vrPlayerState().getBodyPartPose(bodyPart).orientation()); } } @@ -351,7 +351,7 @@ public static void debugParticleAxes(ServerVivePlayer vivePlayer) { debugParticleAxes( vivePlayer.player.serverLevel(), vivePlayer.getHMDPos(), - vivePlayer.vrPlayerState.hmd().orientation()); + vivePlayer.vrPlayerState().hmd().orientation()); } } } diff --git a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java index 1f170dc4c..9af64826f 100644 --- a/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java +++ b/common/src/main/java/org/vivecraft/server/ServerVivePlayer.java @@ -16,7 +16,8 @@ public class ServerVivePlayer { // player movement state @Nullable - public VrPlayerState vrPlayerState; + private VrPlayerState vrPlayerState; + private VRPose vrPlayerStateAsPose; // how much the player is drawing the roomscale bow public float draw; public float worldScale = 1.0F; @@ -176,10 +177,23 @@ public boolean isLeftHanded() { return this.vrPlayerState.leftHanded(); } + @Nullable + public VrPlayerState vrPlayerState() { + return this.vrPlayerState; + } + + public void setVrPlayerState(VrPlayerState vrPlayerState) { + this.vrPlayerState = vrPlayerState; + this.vrPlayerStateAsPose = null; + } + public VRPose asVRPose() { if (this.vrPlayerState == null) { return null; } - return this.vrPlayerState.asPose(player.position()); + if (this.vrPlayerStateAsPose == null) { + this.vrPlayerStateAsPose = this.vrPlayerState.asVRPose(player.position()); + } + return this.vrPlayerStateAsPose; } } From 2eb9047023314fe718958910ba77f9ab246e94db Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 26 Jan 2025 12:06:05 -0500 Subject: [PATCH 30/33] Request Max Ticks of History Needed + Several VRPoseHistory Fixes --- .../org/vivecraft/api/client/VRClientAPI.java | 8 ++++ .../api/client/data/VRPoseHistory.java | 28 ++++++-------- .../client/api_impl/VRClientAPIImpl.java | 24 +++++++++--- .../api_impl/data/VRPoseHistoryImpl.java | 37 ++++++++++++------- .../java/org/vivecraft/client_vr/VRState.java | 2 +- .../client_vr/gameplay/VRPlayer.java | 2 +- 6 files changed, 64 insertions(+), 37 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index 9c5e2dc71..c30aafeb1 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -135,6 +135,14 @@ default void triggerHapticPulse(int controllerNum, float duration) { */ float getWorldScale(); + /** + * Sets the amount of ticks of history wanted for {@link #getHistoricalVRPoses()}. Any value larger than 200 will + * be capped at 200. + * @param maxTicksBack The maximum number of ticks of history wanted. + * @throws IllegalArgumentException If a non-positive number is supplied. + */ + void setTicksOfHistory(int maxTicksBack) throws IllegalArgumentException; + /** * Returns the history of VR poses for the player. Must be called at least once by some caller before the pose * history is populated. diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java index ba2384b6d..dc8505d03 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -9,19 +9,10 @@ public interface VRPoseHistory { - /** - * The maximum amount of ticks back poses are held for. - * It is only guaranteed that the pose history does not go beyond this number of ticks back. Functions do not - * guarantee that they will reference this many ticks, as, for example, this amount of ticks may not have gone - * by for the player this history represents. - * Passing a value larger than this number to any methods below in their maxTicksBack or ticksBack parameters - * will throw an {@link IllegalArgumentException}. - */ - int MAX_TICKS_BACK = 100; - /** * @return The amount of ticks worth of history being held. The number returned by this method will never be higher - * than {@link VRPoseHistory#MAX_TICKS_BACK}, however can be lower than it. + * than the largest valid value set by {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)}, however + * can be lower than it. */ int ticksOfHistory(); @@ -39,7 +30,8 @@ public interface VRPoseHistory { * @param ticksBack Ticks back to retrieve data. * @return A {@link VRPose} instance from index ticks ago. * @throws IllegalStateException If ticksBack references a tick that there is not yet data for. - * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by + * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. */ VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; @@ -51,7 +43,8 @@ public interface VRPoseHistory { * @param maxTicksBack The maximum amount of ticks back to compare the most recent data with. * @return The aforementioned net movement. Note that this will return zero change on all axes if only zero ticks * can be looked back. Will be null if the body part requested isn't available. - * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by + * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. */ @Nullable Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; @@ -64,7 +57,8 @@ public interface VRPoseHistory { * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. * @return The aforementioned average velocity on each axis. Note that this will return zero velocity on all axes * if only zero ticks can be looked back. Will be null if the body part requested isn't available. - * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by + * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. */ @Nullable Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; @@ -77,7 +71,8 @@ public interface VRPoseHistory { * @param maxTicksBack The maximum amount of ticks back to calculate speed with. * @return The aforementioned average speed on each axis. Note that this will return zero speed if only zero ticks * can be looked back. Will be 0 if the body part requested isn't available. - * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by + * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. */ double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; @@ -89,7 +84,8 @@ public interface VRPoseHistory { * @param maxTicksBack The maximum amount of ticks back to calculate velocity with. * @return The aforementioned average position. Note that this will return the current position if only zero ticks * can be looked back. Will be null if the body part requested isn't available. - * @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0. + * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by + * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. */ @Nullable Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index 8b7346add..8dad6f924 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -15,24 +15,29 @@ public final class VRClientAPIImpl implements VRClientAPI { public static final VRClientAPIImpl INSTANCE = new VRClientAPIImpl(); + // If updated, should also update Javadocs in VRClientAPI + private static final int MAX_CONFIGURABLE_HISTORY_TICKS = 200; private final VRPoseHistoryImpl poseHistory = new VRPoseHistoryImpl(); - private boolean gatherPoseHistory = false; + private int maxPoseHistorySize = 0; private VRClientAPIImpl() { } - public void clearAndDisablePoseHistory() { + public void clearPoseHistory() { this.poseHistory.clear(); - gatherPoseHistory = false; } public void addPoseToHistory(VRPose pose) { this.poseHistory.addPose(pose); } - public boolean gatherPoseHistory() { - return this.gatherPoseHistory; + public int maxPoseHistorySize() { + return this.maxPoseHistorySize; + } + + public void setMaxPoseHistorySize(int newSize) { + this.maxPoseHistorySize = Math.max(this.maxPoseHistorySize, newSize); } @Nullable @@ -137,13 +142,20 @@ public float getWorldScale() { } } + @Override + public void setTicksOfHistory(int maxTicksBack) throws IllegalArgumentException { + if (maxTicksBack <= 0) { + throw new IllegalArgumentException("Must call setTicksOfHistory() with a positive number."); + } + setMaxPoseHistorySize(Math.min(maxTicksBack, MAX_CONFIGURABLE_HISTORY_TICKS)); + } + @Override @Nullable public VRPoseHistory getHistoricalVRPoses() { if (!isVRActive()) { return null; } - gatherPoseHistory = true; return this.poseHistory; } diff --git a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java index 856048cb8..e2845dcd1 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/data/VRPoseHistoryImpl.java @@ -1,10 +1,12 @@ package org.vivecraft.client.api_impl.data; import net.minecraft.world.phys.Vec3; +import org.vivecraft.api.client.VRClientAPI; import org.vivecraft.api.client.data.VRPoseHistory; import org.vivecraft.api.data.VRBodyPart; import org.vivecraft.api.data.VRBodyPartData; import org.vivecraft.api.data.VRPose; +import org.vivecraft.client.api_impl.VRClientAPIImpl; import java.util.ArrayList; import java.util.LinkedList; @@ -14,6 +16,7 @@ public class VRPoseHistoryImpl implements VRPoseHistory { + // Holds historical VRPose data. The index into here is simply the number of ticks back that data is. private final LinkedList dataQueue = new LinkedList<>(); public VRPoseHistoryImpl() { @@ -21,7 +24,7 @@ public VRPoseHistoryImpl() { public void addPose(VRPose pose) { this.dataQueue.addFirst(pose); - if (this.dataQueue.size() > VRPoseHistory.MAX_TICKS_BACK + 1) { + if (this.dataQueue.size() > maxTicksOfHistory() + 1) { this.dataQueue.removeLast(); } } @@ -54,12 +57,15 @@ public VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, public Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); - VRBodyPartData currentData = this.dataQueue.getLast().getBodyPartData(bodyPart); + if (this.dataQueue.size() <= 1) { + return Vec3.ZERO; + } + VRBodyPartData currentData = this.dataQueue.getFirst().getBodyPartData(bodyPart); if (currentData == null) { return null; } Vec3 current = currentData.getPos(); - VRBodyPartData oldData = getOldPose(maxTicksBack).getBodyPartData(bodyPart); + VRBodyPartData oldData = this.dataQueue.get(maxTicksBack).getBodyPartData(bodyPart); if (oldData == null) { return null; } @@ -71,6 +77,9 @@ public Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArg public Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); + if (this.dataQueue.size() <= 1) { + return Vec3.ZERO; + } maxTicksBack = getNumTicksBack(maxTicksBack); List diffs = new ArrayList<>(maxTicksBack); for (int i = 0; i < maxTicksBack; i++) { @@ -97,6 +106,9 @@ public Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws Illega public double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); + if (this.dataQueue.size() <= 1) { + return 0; + } maxTicksBack = getNumTicksBack(maxTicksBack); List speeds = new ArrayList<>(maxTicksBack); for (int i = 0; i < maxTicksBack; i++) { @@ -114,6 +126,9 @@ public double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws Illegal public Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException { checkPartNonNull(bodyPart); checkTicksBack(maxTicksBack); + if (this.dataQueue.size() <= 1) { + return VRClientAPI.instance().getPreTickWorldPose().getBodyPartData(bodyPart).getPos(); + } maxTicksBack = getNumTicksBack(maxTicksBack); List positions = new ArrayList<>(maxTicksBack); for (VRPose pose : dataQueue) { @@ -134,8 +149,8 @@ public Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws Illega } private void checkTicksBack(int ticksBack) { - if (ticksBack < 0 || ticksBack > VRPoseHistory.MAX_TICKS_BACK) { - throw new IllegalArgumentException("Value must be between 0 and " + VRPoseHistory.MAX_TICKS_BACK + "."); + if (ticksBack < 0 || ticksBack > maxTicksOfHistory()) { + throw new IllegalArgumentException("Value must be between 0 and " + maxTicksOfHistory() + "."); } } @@ -145,14 +160,6 @@ private void checkPartNonNull(VRBodyPart bodyPart) { } } - private VRPose getOldPose(int maxTicksBack) { - if (this.dataQueue.size() <= maxTicksBack) { - return this.dataQueue.getFirst(); - } else { - return this.dataQueue.get(this.dataQueue.size() - maxTicksBack - 1); - } - } - private int getNumTicksBack(int maxTicksBack) { if (this.dataQueue.size() <= maxTicksBack) { return this.dataQueue.size() - 1; @@ -160,4 +167,8 @@ private int getNumTicksBack(int maxTicksBack) { return maxTicksBack; } } + + private int maxTicksOfHistory() { + return VRClientAPIImpl.INSTANCE.maxPoseHistorySize(); + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index f4d1be42b..ef104e825 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -153,6 +153,6 @@ public static void destroyVR(boolean disableVRSetting) { // this reloads any PostChain, at least in vanilla Minecraft.getInstance().levelRenderer.onResourceManagerReload(Minecraft.getInstance().getResourceManager()); } - VRClientAPIImpl.INSTANCE.clearAndDisablePoseHistory(); + VRClientAPIImpl.INSTANCE.clearPoseHistory(); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java index 81cbef30c..9bf0363bf 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/VRPlayer.java @@ -238,7 +238,7 @@ public void preTick() { } // Gather VRPose history if some API consumer wants it and we're in a non-paused world. - if (VRClientAPIImpl.INSTANCE.gatherPoseHistory() && this.mc.level != null && + if (VRClientAPIImpl.INSTANCE.maxPoseHistorySize() > 0 && this.mc.level != null && (this.mc.getSingleplayerServer() == null || !this.mc.getSingleplayerServer().isPaused())) { VRClientAPIImpl.INSTANCE.addPoseToHistory(this.vrdata_world_pre.asVRPose()); } From e17fe8c66b010a12b58c7f54cb14bb3cd91c16d5 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 26 Jan 2025 12:14:46 -0500 Subject: [PATCH 31/33] setTicksOfHistory --> requestTicksOfHistory --- .../java/org/vivecraft/api/client/VRClientAPI.java | 6 +++--- .../org/vivecraft/api/client/data/VRPoseHistory.java | 12 ++++++------ .../vivecraft/client/api_impl/VRClientAPIImpl.java | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index c30aafeb1..0f3d5e49f 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -136,12 +136,12 @@ default void triggerHapticPulse(int controllerNum, float duration) { float getWorldScale(); /** - * Sets the amount of ticks of history wanted for {@link #getHistoricalVRPoses()}. Any value larger than 200 will - * be capped at 200. + * Requests the amount of ticks of history wanted for {@link #getHistoricalVRPoses()}. Any value larger than 200 + * will be capped at 200. * @param maxTicksBack The maximum number of ticks of history wanted. * @throws IllegalArgumentException If a non-positive number is supplied. */ - void setTicksOfHistory(int maxTicksBack) throws IllegalArgumentException; + void requestTicksOfHistory(int maxTicksBack) throws IllegalArgumentException; /** * Returns the history of VR poses for the player. Must be called at least once by some caller before the pose diff --git a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java index dc8505d03..f8d07b699 100644 --- a/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java +++ b/common/src/main/java/org/vivecraft/api/client/data/VRPoseHistory.java @@ -11,7 +11,7 @@ public interface VRPoseHistory { /** * @return The amount of ticks worth of history being held. The number returned by this method will never be higher - * than the largest valid value set by {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)}, however + * than the largest valid value set by {@link org.vivecraft.api.client.VRClientAPI#requestTicksOfHistory(int)}, however * can be lower than it. */ int ticksOfHistory(); @@ -31,7 +31,7 @@ public interface VRPoseHistory { * @return A {@link VRPose} instance from index ticks ago. * @throws IllegalStateException If ticksBack references a tick that there is not yet data for. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by - * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. + * {@link org.vivecraft.api.client.VRClientAPI#requestTicksOfHistory(int)} or less than 0. */ VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException; @@ -44,7 +44,7 @@ public interface VRPoseHistory { * @return The aforementioned net movement. Note that this will return zero change on all axes if only zero ticks * can be looked back. Will be null if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by - * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. + * {@link org.vivecraft.api.client.VRClientAPI#requestTicksOfHistory(int)} or less than 0. */ @Nullable Vec3 netMovement(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; @@ -58,7 +58,7 @@ public interface VRPoseHistory { * @return The aforementioned average velocity on each axis. Note that this will return zero velocity on all axes * if only zero ticks can be looked back. Will be null if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by - * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. + * {@link org.vivecraft.api.client.VRClientAPI#requestTicksOfHistory(int)} or less than 0. */ @Nullable Vec3 averageVelocity(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; @@ -72,7 +72,7 @@ public interface VRPoseHistory { * @return The aforementioned average speed on each axis. Note that this will return zero speed if only zero ticks * can be looked back. Will be 0 if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by - * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. + * {@link org.vivecraft.api.client.VRClientAPI#requestTicksOfHistory(int)} or less than 0. */ double averageSpeed(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; @@ -85,7 +85,7 @@ public interface VRPoseHistory { * @return The aforementioned average position. Note that this will return the current position if only zero ticks * can be looked back. Will be null if the body part requested isn't available. * @throws IllegalArgumentException Thrown when maxTicksBack is larger than the largest valid value set by - * {@link org.vivecraft.api.client.VRClientAPI#setTicksOfHistory(int)} or less than 0. + * {@link org.vivecraft.api.client.VRClientAPI#requestTicksOfHistory(int)} or less than 0. */ @Nullable Vec3 averagePosition(VRBodyPart bodyPart, int maxTicksBack) throws IllegalArgumentException; diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index 8dad6f924..0c3ca8e29 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -143,9 +143,9 @@ public float getWorldScale() { } @Override - public void setTicksOfHistory(int maxTicksBack) throws IllegalArgumentException { + public void requestTicksOfHistory(int maxTicksBack) throws IllegalArgumentException { if (maxTicksBack <= 0) { - throw new IllegalArgumentException("Must call setTicksOfHistory() with a positive number."); + throw new IllegalArgumentException("Must call requestTicksOfHistory() with a positive number."); } setMaxPoseHistorySize(Math.min(maxTicksBack, MAX_CONFIGURABLE_HISTORY_TICKS)); } From b7b0fc36070f1ef10f10bf039065ec8f5212cc1f Mon Sep 17 00:00:00 2001 From: hammy275 Date: Sun, 26 Jan 2025 12:19:42 -0500 Subject: [PATCH 32/33] One Set Method Instead of Two --- .../java/org/vivecraft/client/api_impl/VRClientAPIImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index 0c3ca8e29..7f919954d 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -36,10 +36,6 @@ public int maxPoseHistorySize() { return this.maxPoseHistorySize; } - public void setMaxPoseHistorySize(int newSize) { - this.maxPoseHistorySize = Math.max(this.maxPoseHistorySize, newSize); - } - @Nullable @Override public VRPose getLatestRoomPose() { @@ -147,7 +143,7 @@ public void requestTicksOfHistory(int maxTicksBack) throws IllegalArgumentExcept if (maxTicksBack <= 0) { throw new IllegalArgumentException("Must call requestTicksOfHistory() with a positive number."); } - setMaxPoseHistorySize(Math.min(maxTicksBack, MAX_CONFIGURABLE_HISTORY_TICKS)); + this.maxPoseHistorySize = Math.max(this.maxPoseHistorySize, Math.min(maxTicksBack, MAX_CONFIGURABLE_HISTORY_TICKS)); } @Override From 54d8e633a25831dd417b31a8cd8f41ef5286ac19 Mon Sep 17 00:00:00 2001 From: hammy275 Date: Fri, 31 Jan 2025 16:01:58 -0500 Subject: [PATCH 33/33] Javadoc Update --- .../main/java/org/vivecraft/api/client/VRClientAPI.java | 7 ++++--- .../org/vivecraft/client/api_impl/VRClientAPIImpl.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java index 0f3d5e49f..c1742cd68 100644 --- a/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java +++ b/common/src/main/java/org/vivecraft/api/client/VRClientAPI.java @@ -144,10 +144,11 @@ default void triggerHapticPulse(int controllerNum, float duration) { void requestTicksOfHistory(int maxTicksBack) throws IllegalArgumentException; /** - * Returns the history of VR poses for the player. Must be called at least once by some caller before the pose - * history is populated. + * Returns the history of VR poses for the player. One should make one call to {@link #requestTicksOfHistory(int)} + * before calling this method to inform Vivecraft of the amount of history to keep. * - * @return The history of VR poses for the player, or null if the player isn't in VR. + * @return The history of VR poses for the player. Will be null if the player isn't in VR or if + * {@link #requestTicksOfHistory(int)} has yet to be called. */ @Nullable VRPoseHistory getHistoricalVRPoses(); diff --git a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java index 7f919954d..85d26bcda 100644 --- a/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java +++ b/common/src/main/java/org/vivecraft/client/api_impl/VRClientAPIImpl.java @@ -149,7 +149,7 @@ public void requestTicksOfHistory(int maxTicksBack) throws IllegalArgumentExcept @Override @Nullable public VRPoseHistory getHistoricalVRPoses() { - if (!isVRActive()) { + if (!isVRActive() || this.maxPoseHistorySize <= 0) { return null; } return this.poseHistory;