Skip to main content

Input API

Interface ID 9. The base contract is 1.0; the compatible 1.1 placement reservation appends one getter. Include ROCK/Input.h; link the header-only RPS::ROCKInput target. Namespace: rock::api::input. All table calls return rock::api::Status. Follow the shared runtime contract and discovery rules.

Input exposes physical buttons/thumbsticks, logical actions, native context and owner-scoped suppression. Physical hand identity remains independent from the firing role. Raw button state is level state; derive your own edges from held state and sample sequence. Availability reason and sample age distinguish an unsampled hook from a released button.

Suppression is a leased write with matching clear and effective-state readback. Chord reservations retain the physical left/right masks and release-to-rearm behavior. Suppressing a native game action does not manufacture button edges or make another provider's hand available. Keep renewals tied to the provider publication boundary and clear when the consumer stops owning the interaction.

Entry points​

The order below is local to this interface. Permissions never transfer between families. Exact argument types, enums, record defaults and bounds appear in the complete declarations below.

FunctionPermissionThreadPurpose
setHandInputSuppressionV1WriteGame ownerPublish/refresh a bounded per-hand suppression lease.
clearHandInputSuppressionV1WriteGame ownerClear one or both caller suppression leases.
getRawWandButtonStateV1ReadGame ownerRead sampled button level, availability, age, and sequence.
isNativePipboyInputSuppressedV1ReadGame ownerRead effective native Pip-Boy action suppression.
getHandInputSuppressionStateV1ReadGame ownerRead effective/caller flags, expiry, and invalidation.
getLogicalInputActionStateV1ReadGame ownerRead semantic Jump level and press/sample sequences.
getRawWandThumbstickV1ReadGame ownerRead physical Axis0 before native game-input suppression.
getNativeInputContextV1ReadGame ownerRead native menu and primary activation priority from a frame callback.
getSampleReadAny; no borrowed-callback reentryRead the publication identity used to join family observations.
copyEventsReadAny; no borrowed-callback reentryRead this owner/family event stream with retention and loss information.

Types, flags, bounds, and signatures​

These declarations are taken from the current public header. Initialize sized records and every sized array element with {}; check status, validity flags and copied counts before reading results.

Complete public declarations: ROCK/Input.h
ROCK/Input.h
#pragma once
#include "Abi.h"

#pragma pack(push, 8)
namespace rock::api::input {
inline constexpr InterfaceId kInterfaceId = InterfaceId::Input;
inline constexpr std::uint32_t kMajor = 1;
inline constexpr std::uint32_t kMinor = 0;
inline constexpr std::uint32_t kMaxSuppressions = 32;
inline constexpr std::uint32_t kMaxSuppressionLeaseFrames = 120;
inline constexpr std::uint32_t kEventCapacityPerOwner = 256;


enum class HandInputSuppressionFlagV1 : std::uint32_t
{
None = 0,
SuppressNormalGrabPress = 1u << 0,
SuppressGrabRelease = 1u << 1,
SuppressHeldWeaponTriggerEquip = 1u << 2,
SuppressGameplayCandidates = 1u << 3,
SuppressOpenVrGameInput = 1u << 4,
SuppressNativeVats = 1u << 5,
SuppressNativeVans = 1u << 6,
SuppressGrenadeQuickDraw = 1u << 7,
ReserveTriggerGripChord = 1u << 8,
ReserveButtonChord = 1u << 9,
SuppressConfigModeChord =
static_cast<std::uint32_t>(SuppressNormalGrabPress) |
static_cast<std::uint32_t>(SuppressGrabRelease) |
static_cast<std::uint32_t>(SuppressHeldWeaponTriggerEquip) |
static_cast<std::uint32_t>(SuppressGameplayCandidates),
};

enum class InputAvailabilityReasonV1 : std::uint32_t
{
Available = 0,
HookNotSampled = 1,
BlockingMenu = 2,
ReleaseToRearm = 3,
InvalidButton = 4,
};

enum class LogicalInputActionV1 : std::uint32_t
{
Jump = 1,
};

enum class SuppressionInvalidationReasonV1 : std::uint32_t
{
None = 0,
Expired = 1,
GenerationChanged = 2,
OwnerUnregistered = 3,
ProviderLost = 4,
ExplicitClear = 5,
CallbackFault = 6,
};

struct HandInputSuppressionRequestV1
{
std::uint32_t size{ sizeof(HandInputSuppressionRequestV1) };
std::uint32_t version{ 1 };
Hand hand{ Hand::None };
std::uint32_t flags{ 0 };
std::uint32_t leaseFrames{ 0 };
std::uint32_t worldGeneration{ 0 };
std::uint32_t skeletonGeneration{ 0 };
std::uint32_t providerGeneration{ 0 };
std::uint32_t chordButtonsLow[2]{};
std::uint32_t chordButtonsHigh[2]{};
std::uint32_t reserved[4]{};
};

enum class NativeInputContextFlagV1 : std::uint32_t
{
Available = 1u << 0,
MenuActive = 1u << 1,
PrimaryActivationTarget = 1u << 2,
};

struct RawWandButtonStateV1
{
std::uint32_t size{ sizeof(RawWandButtonStateV1) };
std::uint32_t version{ 1 };
std::uint32_t available{ 0 };
std::uint32_t held{ 0 };
std::uint64_t sampleSequence{ 0 };
std::uint32_t sampleAgeMilliseconds{ 0 };
InputAvailabilityReasonV1 availabilityReason{
InputAvailabilityReasonV1::HookNotSampled
};
};

struct LogicalInputActionStateV1
{
std::uint32_t size{ sizeof(LogicalInputActionStateV1) };
std::uint32_t version{ 1 };
LogicalInputActionV1 action{
LogicalInputActionV1::Jump
};
std::uint32_t available{ 0 };
std::uint32_t held{ 0 };
InputAvailabilityReasonV1 availabilityReason{
InputAvailabilityReasonV1::HookNotSampled
};
std::uint64_t sampleSequence{ 0 };
std::uint64_t pressSequence{ 0 };
std::uint64_t frameIndex{ 0 };
std::uint32_t sampleAgeMilliseconds{ 0 };
std::uint32_t worldGeneration{ 0 };
std::uint32_t skeletonGeneration{ 0 };
std::uint32_t providerGeneration{ 0 };
std::uint32_t reserved[4]{};
};

struct HandInputSuppressionStateV1
{
std::uint32_t size{ sizeof(HandInputSuppressionStateV1) };
std::uint32_t version{ 1 };
std::uint64_t frameIndex{ 0 };
Hand hand{ Hand::None };
std::uint32_t callerFlags{ 0 };
std::uint32_t effectiveFlags{ 0 };
std::uint32_t callerLeaseActive{ 0 };
std::uint64_t callerExpiresAfterFrame{ 0 };
std::uint32_t callerRemainingFrames{ 0 };
SuppressionInvalidationReasonV1 lastInvalidationReason{
SuppressionInvalidationReasonV1::None
};
std::uint32_t worldGeneration{ 0 };
std::uint32_t skeletonGeneration{ 0 };
std::uint32_t providerGeneration{ 0 };
std::uint32_t reserved[5]{};
};


// Permission bits are local to this interface major. Discovery grants none.
enum class PermissionV1 : std::uint32_t { Read=1, Write=2 };
inline constexpr std::uint32_t kSupportedPermissions = 3;

struct EventV1 {
std::uint32_t size{sizeof(EventV1)};
std::uint32_t kind{};
std::uint64_t sequence{};
std::uint64_t frameIndex{};
std::uint64_t ownerToken{};
std::uint32_t worldGeneration{};
std::uint32_t skeletonGeneration{};
std::uint32_t providerGeneration{};
std::uint32_t authority{}; std::uint32_t reason{};
};
enum class EventKindV1 : std::uint32_t { AuthorityLost=1 };

struct ApiV1 {
static constexpr InterfaceId interfaceId=kInterfaceId;
static constexpr std::uint32_t majorVersion=kMajor;
static constexpr std::uint32_t minorVersion=kMinor;
Status(ROCK_CALL* setHandInputSuppressionV1)(std::uint64_t ownerToken, const HandInputSuppressionRequestV1* request) noexcept;
Status(ROCK_CALL* clearHandInputSuppressionV1)(std::uint64_t ownerToken, Hand hand) noexcept;
Status(ROCK_CALL* getRawWandButtonStateV1)(OwnerToken ownerToken, Hand hand, std::uint32_t buttonId, RawWandButtonStateV1* outState) noexcept;
Status(ROCK_CALL* isNativePipboyInputSuppressedV1)(OwnerToken ownerToken, std::uint32_t* outValue) noexcept;
Status(ROCK_CALL* getHandInputSuppressionStateV1)(std::uint64_t ownerToken, Hand hand, HandInputSuppressionStateV1* outState) noexcept;
Status(ROCK_CALL* getLogicalInputActionStateV1)(std::uint64_t ownerToken, LogicalInputActionV1 action, LogicalInputActionStateV1* outState) noexcept;
Status(ROCK_CALL* getRawWandThumbstickV1)(OwnerToken ownerToken, Hand hand, float* outX, float* outY) noexcept;
Status(ROCK_CALL* getNativeInputContextV1)(OwnerToken ownerToken, std::uint32_t* outValue) noexcept;
// Family-local publication identity; compare before combining readbacks.
Status(ROCK_CALL* getSample)(OwnerToken owner, SampleV1* outSample) noexcept;
Status(ROCK_CALL* copyEvents)(OwnerToken, std::uint64_t afterSequence, EventV1*, std::uint32_t capacity, StreamV1*) noexcept;
};
}

#pragma pack(pop)

Input 1.1 entry points​

The compatible extension keeps ID 9, major 1, and Core 1.0. Include ROCK/InputV1_1.h, acquire rock::api::input::v1_1::Api with Input Read (1), and continue linking RPS::ROCKInput. Negotiate minimum minor 1 and the full 88-byte table before reading its appended slot. The 80-byte/10-call Input 1.0 prefix and ROCK/Input.h remain unchanged.

FunctionPermissionThreadPurpose
getPlacementClickStateReadROCK frame ownerObserve an add-on's held-placement click reservation, including release, with its current publication sample.

Reading placement reservations​

Initialize PlacementClickState with {}. PlacementClickFlag::InputReserved is bit 1 (2): the physical right-stick click belongs to an add-on's placement gesture. Yield the entire press and release, so losing contact or placing the object cannot replay that release into a menu opening.

objectFormId is the submitted candidate, or zero while draining a spent click. It is not an eligibility flag, write permission, or persistent placement key. The record is 48 bytes and includes SampleV1; compare its frame and relevant lifecycle generations with the ROCK snapshot used by your input decision. Read this observation after ROCK has processed its update; BeforeRock is where the placement owner submits its intent, before the new reservation is applied.

A missing minor on an older provider leaves this feature unavailable. Once the extension is negotiated, NotReady or a stale sample does not establish that an input gesture is free. RobCo PALM's integration denies capture in that case. A valid unreserved observation allows its normal input policy to continue.

This getter observes reservation only. It does not consume a raw edge, publish suppression, anchor an object or grant Grab Write. Placement is requested through Grab 1.1; BipodInputReserved retains its separate weapon-support meaning. Completed native placements do not depend on this query or on the input consumer remaining loaded.

Input 1.1 declarations​

Complete public declarations: ROCK/InputV1_1.h
ROCK/InputV1_1.h
#pragma once
#include "Input.h"
#include <cstddef>
#include <type_traits>

#pragma pack(push, 8)
namespace rock::api::input::v1_1 {
inline constexpr InterfaceId kInterfaceId = input::kInterfaceId;
inline constexpr std::uint32_t kMajor = 1;
inline constexpr std::uint32_t kMinor = 1;

enum class PlacementClickFlag : std::uint32_t { InputReserved=2 };
struct PlacementClickState {
std::uint32_t size{sizeof(PlacementClickState)};
std::uint32_t flags{};
std::uint32_t objectFormId{}; // Submitted candidate; zero while draining a spent click.
std::uint32_t reserved{};
SampleV1 sample{};
};
// Negotiate Input major 1, minimum minor 1 and sizeof(Api), then bind Read.
// Call on the ROCK frame thread. A reserved right-stick click belongs to
// an add-on's held placement action, including release; other users yield.
// Native keyframing persists independently of this observational query.
struct Api {
static constexpr InterfaceId interfaceId=kInterfaceId;
static constexpr std::uint32_t majorVersion=kMajor;
static constexpr std::uint32_t minorVersion=kMinor;
input::ApiV1 v1;
Status(ROCK_CALL* getPlacementClickState)(OwnerToken, PlacementClickState*) noexcept;
};
static_assert(std::is_standard_layout_v<Api>);
static_assert(offsetof(Api, v1)==0);
static_assert(offsetof(Api, getPlacementClickState)==sizeof(input::ApiV1));
static_assert(sizeof(Api)==sizeof(input::ApiV1)+sizeof(void*));
}
#pragma pack(pop)