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

Many API Additions #184

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
35 changes: 35 additions & 0 deletions common/src/main/java/org/vivecraft/api/VivecraftAPI.java
Original file line number Diff line number Diff line change
@@ -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);
}
64 changes: 64 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,64 @@
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 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
}
}
199 changes: 199 additions & 0 deletions common/src/main/java/org/vivecraft/api/client/VivecraftClientAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
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 javax.annotation.Nullable;

public interface VivecraftClientAPI {

static VivecraftClientAPI getInstance() {
return ClientAPIImpl.INSTANCE;
}

/**
* Adds 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 addTracker(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 Whether the current render pass is a vanilla render pass.
*/
@Beta
boolean isVanillaRenderPass();

/**
* @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);
}
Original file line number Diff line number Diff line change
@@ -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<VRPose> 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;
}
Loading