Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: [1.20.4] Many API Additions #255

Open
wants to merge 25 commits into
base: Multiloader-1.20.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0e21ed3
Initial API
hammy275 Aug 21, 2023
fe58a0b
Fix Rebase Double-Tracker-Register Bug
hammy275 Jan 12, 2025
6633de2
Left-Handed API Rename
hammy275 Jan 13, 2025
66c682f
Rename API Impl Classes to Match API Classes
hammy275 Jan 13, 2025
f7cdeff
VRPose and VRBodyPart Rename
hammy275 Jan 13, 2025
575fe9c
Separate Vivecraft Rendering API Interface
hammy275 Jan 13, 2025
1fcc15e
VR Capitalization Consistency
hammy275 Jan 13, 2025
c59fbf8
Migrate History to VRPoseHistory
hammy275 Jan 13, 2025
6d46dc2
FBT Additions (untested)
hammy275 Jan 13, 2025
132eb2d
Move averageSpeed() to Impl Class
hammy275 Jan 13, 2025
1897a29
Hand Renaming and Docstring Changes
hammy275 Jan 13, 2025
e624ebb
Vivecraft to VR Rename
hammy275 Jan 14, 2025
c6b407a
Translate Position for Player in Common API
hammy275 Jan 14, 2025
0fb2a73
Not VR Active Conditional for Default Return
hammy275 Jan 15, 2025
af16234
Expose getControllerRenderPos and setupRenderingAtController in API
hammy275 Jan 15, 2025
f515006
Just Expose Hands
hammy275 Jan 15, 2025
5cf9044
Docstring Improvements
hammy275 Jan 16, 2025
95286a3
Some Minor Adjustments
hammy275 Jan 16, 2025
29ac1bf
More Adjustments
hammy275 Jan 16, 2025
dbbc810
Remove Unused Method
hammy275 Jan 16, 2025
3f8ebdf
More Fixing Up
hammy275 Jan 16, 2025
142f8ff
Adjust Names and Javadocs for Room Pose Client Methods
hammy275 Jan 16, 2025
04fad54
Fix Undoing Refactor Changes
hammy275 Jan 16, 2025
e1db417
VRPoseHistory Fixes
hammy275 Jan 16, 2025
88e8924
Merge VRBodyPart to One Enum
hammy275 Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions common/src/main/java/org/vivecraft/api/VRAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.vivecraft.api;

import net.minecraft.world.entity.player.Player;
import org.vivecraft.api.data.VRPose;
import org.vivecraft.common.api_impl.VRAPIImpl;

import javax.annotation.Nullable;

/**
* The main interface for interacting with Vivecraft from common code.
*/
public interface VRAPI {

/**
* @return The Vivecraft API instance for interacting with Vivecraft's API.
*/
static VRAPI getInstance() {
return VRAPIImpl.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 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 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
VRPose getVRPose(Player player);
}
76 changes: 76 additions & 0 deletions common/src/main/java/org/vivecraft/api/client/Tracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.vivecraft.api.client;

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 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 {

/**
* 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, 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.
*
* @param player The local player.
*/
default void reset(LocalPlayer player) {

}

/**
* 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.
*/
default void idleTick(LocalPlayer player) {

}

/**
* The timing type used for ticking trackers.
*/
enum TrackerTickType {
PER_FRAME, PER_TICK
}
}
151 changes: 151 additions & 0 deletions common/src/main/java/org/vivecraft/api/client/VRClientAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
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.VRClientAPIImpl;

import javax.annotation.Nullable;

/**
* The main interface for interacting with Vivecraft from client code. For rendering, one should use
* {@link VRRenderingAPI}.
*/
public interface VRClientAPI {

static VRClientAPI getInstance() {
return VRClientAPIImpl.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 the VR pose representing the player in the room after the most recent poll of VR hardware.
*
* @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 getLatestRoomPose();

/**
* 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 The VR pose representing the player in the room post-tick, or null if the local player isn't in VR.
*/
@Nullable
VRPose getPostTickRoomPose();

/**
* 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.
*/
@Nullable
VRPose getPreTickWorldPose();

/**
* 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 The VR pose representing the player in Minecraft space post-tick, or null if the local player isn't in VR.
*/
@Nullable
VRPose getPostTickWorldPose();

/**
* 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.
*/
@Nullable
VRPose getWorldRenderPose();

/**
* 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 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.
* @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 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.
*/
default void triggerHapticPulse(int controllerNum, float duration) {
triggerHapticPulse(controllerNum, duration, 160F, 1F, 0F);
}

/**
* @return Whether the local player is currently in seated mode.
*/
boolean isSeated();

/**
* @return Whether the local player is playing with left-handed controls.
*/
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.
*/
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. Will return 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
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
* 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);
}
53 changes: 53 additions & 0 deletions common/src/main/java/org/vivecraft/api/client/VRRenderingAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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.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 VRClientAPI}.
*/
public interface VRRenderingAPI {

static VRRenderingAPI getInstance() {
return VRRenderingAPIImpl.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 performed for this render cycle.
*/
boolean isFirstRenderPass();

/**
* 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 getHandRenderPos(InteractionHand hand);

/**
* 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.
*/
@Beta
void setupRenderingAtHand(InteractionHand hand, PoseStack stack);
}
Loading