2 Commits

Author SHA1 Message Date
Kristian Ollikainen
42e009bc8a Merge 1d88a03b93 into 32341574dc 2025-10-31 22:53:23 +00:00
DatCaptainHorse
1d88a03b93 More multi-controller fixes, better controller polling logic, clean up dead relay code 2025-11-01 00:53:15 +02:00
18 changed files with 1149 additions and 1289 deletions

View File

@@ -41,7 +41,7 @@ RUN --mount=type=cache,target=/var/cache/pacman/pkg \
pacman -Sy --noconfirm lib32-gcc-libs pacman -Sy --noconfirm lib32-gcc-libs
# Clone repository # Clone repository
RUN git clone --depth 1 --rev "f2f21561ddcb814d74455311969d3e8934b052c6" https://github.com/DatCaptainHorse/vimputti.git RUN git clone --depth 1 --rev "2fde5376b6b9a38cdbd94ccc6a80c9d29a81a417" https://github.com/DatCaptainHorse/vimputti.git
#-------------------------------------------------------------------- #--------------------------------------------------------------------
FROM vimputti-manager-deps AS vimputti-manager-planner FROM vimputti-manager-deps AS vimputti-manager-planner

View File

@@ -3,10 +3,8 @@ import { WebRTCStream } from "./webrtc-stream";
import { import {
ProtoControllerAttachSchema, ProtoControllerAttachSchema,
ProtoControllerDetachSchema, ProtoControllerDetachSchema,
ProtoControllerButtonSchema, ProtoControllerStateBatchSchema,
ProtoControllerTriggerSchema, ProtoControllerStateBatch,
ProtoControllerAxisSchema,
ProtoControllerStickSchema,
ProtoControllerRumble, ProtoControllerRumble,
} from "./proto/types_pb"; } from "./proto/types_pb";
import { create, toBinary, fromBinary } from "@bufbuild/protobuf"; import { create, toBinary, fromBinary } from "@bufbuild/protobuf";
@@ -19,6 +17,7 @@ interface Props {
} }
interface GamepadState { interface GamepadState {
previousButtonState: Map<number, boolean>;
buttonState: Map<number, boolean>; buttonState: Map<number, boolean>;
leftTrigger: number; leftTrigger: number;
rightTrigger: number; rightTrigger: number;
@@ -30,11 +29,17 @@ interface GamepadState {
dpadY: number; dpadY: number;
} }
enum PollState {
IDLE,
RUNNING,
}
export class Controller { export class Controller {
protected wrtc: WebRTCStream; protected wrtc: WebRTCStream;
protected connected: boolean = false; protected connected: boolean = false;
protected gamepad: Gamepad | null = null; protected gamepad: Gamepad | null = null;
protected lastState: GamepadState = { protected state: GamepadState = {
previousButtonState: new Map<number, boolean>(),
buttonState: new Map<number, boolean>(), buttonState: new Map<number, boolean>(),
leftTrigger: 0, leftTrigger: 0,
rightTrigger: 0, rightTrigger: 0,
@@ -48,22 +53,34 @@ export class Controller {
// TODO: As user configurable, set quite low now for decent controllers (not Nintendo ones :P) // TODO: As user configurable, set quite low now for decent controllers (not Nintendo ones :P)
protected stickDeadzone: number = 2048; // 2048 / 32768 = ~0.06 (6% of stick range) protected stickDeadzone: number = 2048; // 2048 / 32768 = ~0.06 (6% of stick range)
private updateInterval = 10.0; // 100 updates per second // Polling configuration
private isIdle: boolean = true; private readonly FULL_RATE_MS = 10; // 100 UPS
private readonly IDLE_THRESHOLD = 100; // ms before considering idle/hands off controller
private readonly FULL_INTERVAL= 250; // ms before sending full state occassionally, to verify inputs are synced
// Polling state
private pollingState: PollState = PollState.IDLE;
private lastInputTime: number = Date.now(); private lastInputTime: number = Date.now();
private idleUpdateInterval: number = 150.0; // ~6-7 updates per second for keep-alive packets private lastFullTime: number = Date.now();
private inputDetected: boolean = false; private pollInterval: any = null;
private lastFullStateSend: number = Date.now();
private fullStateSendInterval: number = 500.0; // send full state every 0.5 seconds (helps packet loss) // Controller batch vars
private forceFullStateSend: boolean = false; private sequence: number = 0;
private readonly CHANGED_BUTTONS_STATE = 1 << 0;
private readonly CHANGED_LEFT_STICK_X = 1 << 1;
private readonly CHANGED_LEFT_STICK_Y = 1 << 2;
private readonly CHANGED_RIGHT_STICK_X = 1 << 3;
private readonly CHANGED_RIGHT_STICK_Y = 1 << 4;
private readonly CHANGED_LEFT_TRIGGER = 1 << 5;
private readonly CHANGED_RIGHT_TRIGGER = 1 << 6;
private readonly CHANGED_DPAD_X = 1 << 7;
private readonly CHANGED_DPAD_Y = 1 << 8;
private _dcHandler: ((data: ArrayBuffer) => void) | null = null; private _dcHandler: ((data: ArrayBuffer) => void) | null = null;
constructor({ webrtc, e }: Props) { constructor({ webrtc, e }: Props) {
this.wrtc = webrtc; this.wrtc = webrtc;
this.updateInterval = 1000 / webrtc.currentFrameRate;
// Get vendor of gamepad from id string (i.e. "... Vendor: 054c Product: 09cc") // Get vendor of gamepad from id string (i.e. "... Vendor: 054c Product: 09cc")
const vendorMatch = e.gamepad.id.match(/Vendor:\s?([0-9a-fA-F]{4})/); const vendorMatch = e.gamepad.id.match(/Vendor:\s?([0-9a-fA-F]{4})/);
const vendorId = vendorMatch ? vendorMatch[1].toLowerCase() : "unknown"; const vendorId = vendorMatch ? vendorMatch[1].toLowerCase() : "unknown";
@@ -89,6 +106,7 @@ export class Controller {
console.log( console.log(
`Gamepad connected: ${e.gamepad.id}, local slot ${e.gamepad.index}, msg: ${attachMsg.sessionSlot}`, `Gamepad connected: ${e.gamepad.id}, local slot ${e.gamepad.index}, msg: ${attachMsg.sessionSlot}`,
); );
this.run();
} }
} catch (err) { } catch (err) {
console.error("Error decoding datachannel message:", err); console.error("Error decoding datachannel message:", err);
@@ -162,52 +180,70 @@ export class Controller {
return ((value - fromMin) * (toMax - toMin)) / (fromMax - fromMin) + toMin; return ((value - fromMin) * (toMax - toMin)) / (fromMax - fromMin) + toMin;
} }
private pollGamepad() { private restartPolling() {
// Get updated gamepad state // Clear existing interval
const gamepads = navigator.getGamepads(); if (this.pollInterval) {
clearInterval(this.pollInterval);
// Periodically force send full state to clear stuck inputs this.pollInterval = null;
if (Date.now() - this.lastFullStateSend > this.fullStateSendInterval) {
this.forceFullStateSend = true;
this.lastFullStateSend = Date.now();
} }
if (this.gamepad) { // Restart with active polling
if (gamepads[this.gamepad.index]) { this.pollingState = PollState.RUNNING;
this.gamepad = gamepads[this.gamepad!.index]; this.lastInputTime = Date.now();
/* Button handling */
this.gamepad.buttons.forEach((button, index) => {
// Ignore d-pad buttons (12-15) as we handle those as axis
if (index >= 12 && index <= 15) return;
// ignore trigger buttons (6-7) as we handle those as axis
if (index === 6 || index === 7) return;
// If state differs, send
if (button.pressed !== this.lastState.buttonState.get(index) || this.forceFullStateSend) {
const linuxCode = this.controllerButtonToVirtualKeyCode(index);
if (linuxCode === undefined) {
// Skip unmapped button index
this.lastState.buttonState.set(index, button.pressed);
return;
}
const buttonMessage = createMessage( // Start interval
create(ProtoControllerButtonSchema, { this.pollInterval = setInterval(
sessionSlot: this.gamepad.index, () => this.pollGamepad(),
sessionId: this.wrtc.getSessionID(), this.FULL_RATE_MS,
button: linuxCode,
pressed: button.pressed,
}),
"controllerInput",
); );
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, buttonMessage));
this.inputDetected = true;
// Store button state
this.lastState.buttonState.set(index, button.pressed);
} }
});
/* Trigger handling */ private pollGamepad() {
// map trigger value from 0.0 to 1.0 to -32768 to 32767 if (!this.connected || !this.gamepad) return;
const gamepads = navigator.getGamepads();
if (!gamepads[this.gamepad.index]) return;
this.gamepad = gamepads[this.gamepad.index];
// Collect state changes
const changedFields = this.collectStateChanges();
// Send batched changes update if there's changes
if (changedFields > 0) {
let send_type = 1;
const timeSinceFull = Date.now() - this.lastFullTime;
if (timeSinceFull > this.FULL_INTERVAL) {
send_type = 0;
this.lastFullTime = Date.now();
}
this.sendBatchedState(changedFields, send_type);
this.lastInputTime = Date.now();
if (this.pollingState !== PollState.RUNNING) {
this.pollingState = PollState.RUNNING;
}
}
const timeSinceInput = Date.now() - this.lastInputTime;
if (timeSinceInput > this.IDLE_THRESHOLD) {
// Changing from running to idle..
if (this.pollingState === PollState.RUNNING) {
// Send full state on idle assumption
this.sendBatchedState(0xFF, 0);
this.pollingState = PollState.IDLE;
}
}
this.state.buttonState.forEach((b, i) =>
this.state.previousButtonState.set(i, b),
);
}
private collectStateChanges(): number {
let changedFields = 0;
// Collect analog values
const leftTrigger = Math.round( const leftTrigger = Math.round(
this.remapFromTo( this.remapFromTo(
this.gamepad.buttons[6]?.value ?? 0, this.gamepad.buttons[6]?.value ?? 0,
@@ -217,21 +253,6 @@ export class Controller {
32767, 32767,
), ),
); );
// If state differs, send
if (leftTrigger !== this.lastState.leftTrigger || this.forceFullStateSend) {
const triggerMessage = createMessage(
create(ProtoControllerTriggerSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
trigger: 0, // 0 = left, 1 = right
value: leftTrigger,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, triggerMessage));
this.inputDetected = true;
this.lastState.leftTrigger = leftTrigger;
}
const rightTrigger = Math.round( const rightTrigger = Math.round(
this.remapFromTo( this.remapFromTo(
this.gamepad.buttons[7]?.value ?? 0, this.gamepad.buttons[7]?.value ?? 0,
@@ -241,62 +262,7 @@ export class Controller {
32767, 32767,
), ),
); );
// If state differs, send
if (rightTrigger !== this.lastState.rightTrigger || this.forceFullStateSend) {
const triggerMessage = createMessage(
create(ProtoControllerTriggerSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
trigger: 1, // 0 = left, 1 = right
value: rightTrigger,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, triggerMessage));
this.inputDetected = true;
this.lastState.rightTrigger = rightTrigger;
}
/* DPad handling */
// We send dpad buttons as axis values -1 to 1 for left/up, right/down
const dpadLeft = this.gamepad.buttons[14]?.pressed ? 1 : 0;
const dpadRight = this.gamepad.buttons[15]?.pressed ? 1 : 0;
const dpadX = dpadLeft ? -1 : dpadRight ? 1 : 0;
if (dpadX !== this.lastState.dpadX || this.forceFullStateSend) {
const dpadMessage = createMessage(
create(ProtoControllerAxisSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
axis: 0, // 0 = dpadX, 1 = dpadY
value: dpadX,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, dpadMessage));
this.inputDetected = true;
this.lastState.dpadX = dpadX;
}
const dpadUp = this.gamepad.buttons[12]?.pressed ? 1 : 0;
const dpadDown = this.gamepad.buttons[13]?.pressed ? 1 : 0;
const dpadY = dpadUp ? -1 : dpadDown ? 1 : 0;
if (dpadY !== this.lastState.dpadY || this.forceFullStateSend) {
const dpadMessage = createMessage(
create(ProtoControllerAxisSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
axis: 1, // 0 = dpadX, 1 = dpadY
value: dpadY,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, dpadMessage));
this.inputDetected = true;
this.lastState.dpadY = dpadY;
}
/* Stick handling */
// stick values need to be mapped from -1.0 to 1.0 to -32768 to 32767
const leftX = this.remapFromTo( const leftX = this.remapFromTo(
this.gamepad.axes[0] ?? 0, this.gamepad.axes[0] ?? 0,
-1, -1,
@@ -311,32 +277,10 @@ export class Controller {
-32768, -32768,
32767, 32767,
); );
// Apply deadzone
const sendLeftX = const sendLeftX =
Math.abs(leftX) > this.stickDeadzone ? Math.round(leftX) : 0; Math.abs(leftX) > this.stickDeadzone ? Math.round(leftX) : 0;
const sendLeftY = const sendLeftY =
Math.abs(leftY) > this.stickDeadzone ? Math.round(leftY) : 0; Math.abs(leftY) > this.stickDeadzone ? Math.round(leftY) : 0;
// if outside deadzone, send normally if changed
// if moves inside deadzone, zero it if not inside deadzone last time
if (
sendLeftX !== this.lastState.leftX ||
sendLeftY !== this.lastState.leftY || this.forceFullStateSend
) {
const stickMessage = createMessage(
create(ProtoControllerStickSchema, {
sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(),
stick: 0, // 0 = left, 1 = right
x: sendLeftX,
y: sendLeftY,
}),
"controllerInput",
);
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, stickMessage));
this.inputDetected = true;
this.lastState.leftX = sendLeftX;
this.lastState.leftY = sendLeftY;
}
const rightX = this.remapFromTo( const rightX = this.remapFromTo(
this.gamepad.axes[2] ?? 0, this.gamepad.axes[2] ?? 0,
@@ -352,76 +296,167 @@ export class Controller {
-32768, -32768,
32767, 32767,
); );
// Apply deadzone
const sendRightX = const sendRightX =
Math.abs(rightX) > this.stickDeadzone ? Math.round(rightX) : 0; Math.abs(rightX) > this.stickDeadzone ? Math.round(rightX) : 0;
const sendRightY = const sendRightY =
Math.abs(rightY) > this.stickDeadzone ? Math.round(rightY) : 0; Math.abs(rightY) > this.stickDeadzone ? Math.round(rightY) : 0;
if (
sendRightX !== this.lastState.rightX || const dpadX =
sendRightY !== this.lastState.rightY || this.forceFullStateSend (this.gamepad.buttons[14]?.pressed ? -1 : 0) +
) { (this.gamepad.buttons[15]?.pressed ? 1 : 0);
const stickMessage = createMessage( const dpadY =
create(ProtoControllerStickSchema, { (this.gamepad.buttons[12]?.pressed ? -1 : 0) +
(this.gamepad.buttons[13]?.pressed ? 1 : 0);
// Check what changed
for (let i = 0; i < this.gamepad.buttons.length; i++) {
if (i >= 6 && i <= 7) continue; // Skip triggers
if (i >= 12 && i <= 15) continue; // Skip d-pad
if (this.state.buttonState.get(i) !== this.gamepad.buttons[i].pressed) {
changedFields |= this.CHANGED_BUTTONS_STATE;
}
this.state.buttonState.set(i, this.gamepad.buttons[i].pressed);
}
if (leftTrigger !== this.state.leftTrigger) {
changedFields |= this.CHANGED_LEFT_TRIGGER;
}
this.state.leftTrigger = leftTrigger;
if (rightTrigger !== this.state.rightTrigger) {
changedFields |= this.CHANGED_RIGHT_TRIGGER;
}
this.state.rightTrigger = rightTrigger;
if (sendLeftX !== this.state.leftX) {
changedFields |= this.CHANGED_LEFT_STICK_X;
}
this.state.leftX = sendLeftX;
if (sendLeftY !== this.state.leftY) {
changedFields |= this.CHANGED_LEFT_STICK_Y;
}
this.state.leftY = sendLeftY;
if (sendRightX !== this.state.rightX) {
changedFields |= this.CHANGED_RIGHT_STICK_X;
}
this.state.rightX = sendRightX;
if (sendRightY !== this.state.rightY) {
changedFields |= this.CHANGED_RIGHT_STICK_Y;
}
this.state.rightY = sendRightY;
if (dpadX !== this.state.dpadX) {
changedFields |= this.CHANGED_DPAD_X;
}
this.state.dpadX = dpadX;
if (dpadY !== this.state.dpadY) {
changedFields |= this.CHANGED_DPAD_Y;
}
this.state.dpadY = dpadY;
return changedFields;
}
private sendBatchedState(changedFields: number, updateType: number) {
// @ts-ignore
let message: ProtoControllerStateBatch = {
sessionSlot: this.gamepad.index, sessionSlot: this.gamepad.index,
sessionId: this.wrtc.getSessionID(), sessionId: this.wrtc.getSessionID(),
stick: 1, // 0 = left, 1 = right updateType: updateType,
x: sendRightX, sequence: this.sequence++,
y: sendRightY, };
// For FULL_STATE, include everything
if (updateType === 0) {
message.changedFields = 0xFF;
message.buttonChangedMask = Object.fromEntries(
Array.from(this.state.buttonState).map(([key, value]) => {
return [this.controllerButtonToVirtualKeyCode(key), value];
}), }),
);
message.leftStickX = this.state.leftX;
message.leftStickY = this.state.leftY;
message.rightStickX = this.state.rightX;
message.rightStickY = this.state.rightY;
message.leftTrigger = this.state.leftTrigger;
message.rightTrigger = this.state.rightTrigger;
message.dpadX = this.state.dpadX;
message.dpadY = this.state.dpadY;
}
// For DELTA, only include changed fields
else {
message.changedFields = changedFields;
if (changedFields & this.CHANGED_BUTTONS_STATE) {
const currentStateMap = this.state.buttonState;
const previousStateMap = this.state.previousButtonState;
const allKeys = new Set([
// @ts-ignore
...currentStateMap.keys(),
// @ts-ignore
...previousStateMap.keys(),
]);
message.buttonChangedMask = Object.fromEntries(
Array.from(allKeys)
.filter((key) => {
const newState = currentStateMap.get(key);
const oldState = previousStateMap.get(key);
return newState !== oldState;
})
.map((key) => {
const newValue = currentStateMap.get(key) ?? false;
return [this.controllerButtonToVirtualKeyCode(key), newValue];
}),
);
}
if (changedFields & this.CHANGED_LEFT_STICK_X) {
message.leftStickX = this.state.leftX;
}
if (changedFields & this.CHANGED_LEFT_STICK_Y) {
message.leftStickY = this.state.leftY;
}
if (changedFields & this.CHANGED_RIGHT_STICK_X) {
message.rightStickX = this.state.rightX;
}
if (changedFields & this.CHANGED_RIGHT_STICK_Y) {
message.rightStickY = this.state.rightY;
}
if (changedFields & this.CHANGED_LEFT_TRIGGER) {
message.leftTrigger = this.state.leftTrigger;
}
if (changedFields & this.CHANGED_RIGHT_TRIGGER) {
message.rightTrigger = this.state.rightTrigger;
}
if (changedFields & this.CHANGED_DPAD_X) {
message.dpadX = this.state.dpadX;
}
if (changedFields & this.CHANGED_DPAD_Y) {
message.dpadY = this.state.dpadY;
}
}
// Send message
const batchMessage = createMessage(
create(
ProtoControllerStateBatchSchema,
message as ProtoControllerStateBatch,
),
"controllerInput", "controllerInput",
); );
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, stickMessage)); this.wrtc.sendBinary(toBinary(ProtoMessageSchema, batchMessage));
this.inputDetected = true;
this.lastState.rightX = sendRightX;
this.lastState.rightY = sendRightY;
} }
}
}
this.forceFullStateSend = false;
}
private loopInterval: any = null;
public run() { public run() {
if (this.connected) this.stop(); if (this.connected) this.stop();
this.connected = true; this.connected = true;
this.isIdle = true;
this.lastInputTime = Date.now();
this.loopInterval = setInterval(() => { // Start with active polling
if (this.connected) { this.restartPolling();
this.inputDetected = false; // Reset before poll
this.pollGamepad();
// Switch polling rate based on input
if (this.inputDetected) {
this.lastInputTime = Date.now();
if (this.isIdle) {
this.isIdle = false;
clearInterval(this.loopInterval);
this.loopInterval = setInterval(() => {
if (this.connected) this.pollGamepad();
}, this.updateInterval);
}
} else if (!this.isIdle && Date.now() - this.lastInputTime > 200) {
// Switch to idle polling after 200ms of no input
this.isIdle = true;
clearInterval(this.loopInterval);
this.loopInterval = setInterval(() => {
if (this.connected) this.pollGamepad();
}, this.idleUpdateInterval);
}
}
}, this.isIdle ? this.idleUpdateInterval : this.updateInterval);
} }
public stop() { public stop() {
if (this.loopInterval) { if (this.pollInterval) {
clearInterval(this.loopInterval); clearInterval(this.pollInterval);
this.loopInterval = null; this.pollInterval = null;
} }
this.connected = false; this.connected = false;
} }
@@ -443,17 +478,18 @@ export class Controller {
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, detachMsg)); this.wrtc.sendBinary(toBinary(ProtoMessageSchema, detachMsg));
} }
private controllerButtonToVirtualKeyCode(code: number) { private controllerButtonToVirtualKeyCode(code: number): number | undefined {
return controllerButtonToLinuxEventCode[code] || undefined; return controllerButtonToLinuxEventCode[code] || undefined;
} }
private rumbleCallback(rumbleMsg: ProtoControllerRumble) { private rumbleCallback(rumbleMsg: ProtoControllerRumble) {
// If not connected, ignore if (!this.connected || !this.gamepad) return;
if (!this.connected) return;
// Check if aimed at this controller slot // Check if this rumble is for us
if (rumbleMsg.sessionId !== this.wrtc.getSessionID() && if (
rumbleMsg.sessionSlot !== this.gamepad.index) rumbleMsg.sessionId !== this.wrtc.getSessionID() &&
rumbleMsg.sessionSlot !== this.gamepad.index
)
return; return;
// Trigger actual rumble // Trigger actual rumble

View File

@@ -4,7 +4,7 @@
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
import type { ProtoClientDisconnected, ProtoClientRequestRoomStream, ProtoControllerAttach, ProtoControllerAxis, ProtoControllerButton, ProtoControllerDetach, ProtoControllerRumble, ProtoControllerStick, ProtoControllerTrigger, ProtoICE, ProtoKeyDown, ProtoKeyUp, ProtoMouseKeyDown, ProtoMouseKeyUp, ProtoMouseMove, ProtoMouseMoveAbs, ProtoMouseWheel, ProtoRaw, ProtoSDP, ProtoServerPushStream } from "./types_pb"; import type { ProtoClientDisconnected, ProtoClientRequestRoomStream, ProtoControllerAttach, ProtoControllerDetach, ProtoControllerRumble, ProtoControllerStateBatch, ProtoICE, ProtoKeyDown, ProtoKeyUp, ProtoMouseKeyDown, ProtoMouseKeyUp, ProtoMouseMove, ProtoMouseMoveAbs, ProtoMouseWheel, ProtoRaw, ProtoSDP, ProtoServerPushStream } from "./types_pb";
import { file_types } from "./types_pb"; import { file_types } from "./types_pb";
import type { ProtoLatencyTracker } from "./latency_tracker_pb"; import type { ProtoLatencyTracker } from "./latency_tracker_pb";
import { file_latency_tracker } from "./latency_tracker_pb"; import { file_latency_tracker } from "./latency_tracker_pb";
@@ -14,7 +14,7 @@ import type { Message } from "@bufbuild/protobuf";
* Describes the file messages.proto. * Describes the file messages.proto.
*/ */
export const file_messages: GenFile = /*@__PURE__*/ export const file_messages: GenFile = /*@__PURE__*/
fileDesc("Cg5tZXNzYWdlcy5wcm90bxIFcHJvdG8iVQoQUHJvdG9NZXNzYWdlQmFzZRIUCgxwYXlsb2FkX3R5cGUYASABKAkSKwoHbGF0ZW5jeRgCIAEoCzIaLnByb3RvLlByb3RvTGF0ZW5jeVRyYWNrZXIiyQgKDFByb3RvTWVzc2FnZRItCgxtZXNzYWdlX2Jhc2UYASABKAsyFy5wcm90by5Qcm90b01lc3NhZ2VCYXNlEisKCm1vdXNlX21vdmUYAiABKAsyFS5wcm90by5Qcm90b01vdXNlTW92ZUgAEjIKDm1vdXNlX21vdmVfYWJzGAMgASgLMhgucHJvdG8uUHJvdG9Nb3VzZU1vdmVBYnNIABItCgttb3VzZV93aGVlbBgEIAEoCzIWLnByb3RvLlByb3RvTW91c2VXaGVlbEgAEjIKDm1vdXNlX2tleV9kb3duGAUgASgLMhgucHJvdG8uUHJvdG9Nb3VzZUtleURvd25IABIuCgxtb3VzZV9rZXlfdXAYBiABKAsyFi5wcm90by5Qcm90b01vdXNlS2V5VXBIABInCghrZXlfZG93bhgHIAEoCzITLnByb3RvLlByb3RvS2V5RG93bkgAEiMKBmtleV91cBgIIAEoCzIRLnByb3RvLlByb3RvS2V5VXBIABI5ChFjb250cm9sbGVyX2F0dGFjaBgJIAEoCzIcLnByb3RvLlByb3RvQ29udHJvbGxlckF0dGFjaEgAEjkKEWNvbnRyb2xsZXJfZGV0YWNoGAogASgLMhwucHJvdG8uUHJvdG9Db250cm9sbGVyRGV0YWNoSAASOQoRY29udHJvbGxlcl9idXR0b24YCyABKAsyHC5wcm90by5Qcm90b0NvbnRyb2xsZXJCdXR0b25IABI7ChJjb250cm9sbGVyX3RyaWdnZXIYDCABKAsyHS5wcm90by5Qcm90b0NvbnRyb2xsZXJUcmlnZ2VySAASNwoQY29udHJvbGxlcl9zdGljaxgNIAEoCzIbLnByb3RvLlByb3RvQ29udHJvbGxlclN0aWNrSAASNQoPY29udHJvbGxlcl9heGlzGA4gASgLMhoucHJvdG8uUHJvdG9Db250cm9sbGVyQXhpc0gAEjkKEWNvbnRyb2xsZXJfcnVtYmxlGA8gASgLMhwucHJvdG8uUHJvdG9Db250cm9sbGVyUnVtYmxlSAASHgoDaWNlGBQgASgLMg8ucHJvdG8uUHJvdG9JQ0VIABIeCgNzZHAYFSABKAsyDy5wcm90by5Qcm90b1NEUEgAEh4KA3JhdxgWIAEoCzIPLnByb3RvLlByb3RvUmF3SAASSQoaY2xpZW50X3JlcXVlc3Rfcm9vbV9zdHJlYW0YFyABKAsyIy5wcm90by5Qcm90b0NsaWVudFJlcXVlc3RSb29tU3RyZWFtSAASPQoTY2xpZW50X2Rpc2Nvbm5lY3RlZBgYIAEoCzIeLnByb3RvLlByb3RvQ2xpZW50RGlzY29ubmVjdGVkSAASOgoSc2VydmVyX3B1c2hfc3RyZWFtGBkgASgLMhwucHJvdG8uUHJvdG9TZXJ2ZXJQdXNoU3RyZWFtSABCCQoHcGF5bG9hZEIWWhRyZWxheS9pbnRlcm5hbC9wcm90b2IGcHJvdG8z", [file_types, file_latency_tracker]); fileDesc("Cg5tZXNzYWdlcy5wcm90bxIFcHJvdG8iVQoQUHJvdG9NZXNzYWdlQmFzZRIUCgxwYXlsb2FkX3R5cGUYASABKAkSKwoHbGF0ZW5jeRgCIAEoCzIaLnByb3RvLlByb3RvTGF0ZW5jeVRyYWNrZXIipQcKDFByb3RvTWVzc2FnZRItCgxtZXNzYWdlX2Jhc2UYASABKAsyFy5wcm90by5Qcm90b01lc3NhZ2VCYXNlEisKCm1vdXNlX21vdmUYAiABKAsyFS5wcm90by5Qcm90b01vdXNlTW92ZUgAEjIKDm1vdXNlX21vdmVfYWJzGAMgASgLMhgucHJvdG8uUHJvdG9Nb3VzZU1vdmVBYnNIABItCgttb3VzZV93aGVlbBgEIAEoCzIWLnByb3RvLlByb3RvTW91c2VXaGVlbEgAEjIKDm1vdXNlX2tleV9kb3duGAUgASgLMhgucHJvdG8uUHJvdG9Nb3VzZUtleURvd25IABIuCgxtb3VzZV9rZXlfdXAYBiABKAsyFi5wcm90by5Qcm90b01vdXNlS2V5VXBIABInCghrZXlfZG93bhgHIAEoCzITLnByb3RvLlByb3RvS2V5RG93bkgAEiMKBmtleV91cBgIIAEoCzIRLnByb3RvLlByb3RvS2V5VXBIABI5ChFjb250cm9sbGVyX2F0dGFjaBgJIAEoCzIcLnByb3RvLlByb3RvQ29udHJvbGxlckF0dGFjaEgAEjkKEWNvbnRyb2xsZXJfZGV0YWNoGAogASgLMhwucHJvdG8uUHJvdG9Db250cm9sbGVyRGV0YWNoSAASOQoRY29udHJvbGxlcl9ydW1ibGUYCyABKAsyHC5wcm90by5Qcm90b0NvbnRyb2xsZXJSdW1ibGVIABJCChZjb250cm9sbGVyX3N0YXRlX2JhdGNoGAwgASgLMiAucHJvdG8uUHJvdG9Db250cm9sbGVyU3RhdGVCYXRjaEgAEh4KA2ljZRgUIAEoCzIPLnByb3RvLlByb3RvSUNFSAASHgoDc2RwGBUgASgLMg8ucHJvdG8uUHJvdG9TRFBIABIeCgNyYXcYFiABKAsyDy5wcm90by5Qcm90b1Jhd0gAEkkKGmNsaWVudF9yZXF1ZXN0X3Jvb21fc3RyZWFtGBcgASgLMiMucHJvdG8uUHJvdG9DbGllbnRSZXF1ZXN0Um9vbVN0cmVhbUgAEj0KE2NsaWVudF9kaXNjb25uZWN0ZWQYGCABKAsyHi5wcm90by5Qcm90b0NsaWVudERpc2Nvbm5lY3RlZEgAEjoKEnNlcnZlcl9wdXNoX3N0cmVhbRgZIAEoCzIcLnByb3RvLlByb3RvU2VydmVyUHVzaFN0cmVhbUgAQgkKB3BheWxvYWRCFloUcmVsYXkvaW50ZXJuYWwvcHJvdG9iBnByb3RvMw", [file_types, file_latency_tracker]);
/** /**
* @generated from message proto.ProtoMessageBase * @generated from message proto.ProtoMessageBase
@@ -96,6 +96,8 @@ export type ProtoMessage = Message<"proto.ProtoMessage"> & {
case: "keyUp"; case: "keyUp";
} | { } | {
/** /**
* Controller input types
*
* @generated from field: proto.ProtoControllerAttach controller_attach = 9; * @generated from field: proto.ProtoControllerAttach controller_attach = 9;
*/ */
value: ProtoControllerAttach; value: ProtoControllerAttach;
@@ -108,34 +110,16 @@ export type ProtoMessage = Message<"proto.ProtoMessage"> & {
case: "controllerDetach"; case: "controllerDetach";
} | { } | {
/** /**
* @generated from field: proto.ProtoControllerButton controller_button = 11; * @generated from field: proto.ProtoControllerRumble controller_rumble = 11;
*/
value: ProtoControllerButton;
case: "controllerButton";
} | {
/**
* @generated from field: proto.ProtoControllerTrigger controller_trigger = 12;
*/
value: ProtoControllerTrigger;
case: "controllerTrigger";
} | {
/**
* @generated from field: proto.ProtoControllerStick controller_stick = 13;
*/
value: ProtoControllerStick;
case: "controllerStick";
} | {
/**
* @generated from field: proto.ProtoControllerAxis controller_axis = 14;
*/
value: ProtoControllerAxis;
case: "controllerAxis";
} | {
/**
* @generated from field: proto.ProtoControllerRumble controller_rumble = 15;
*/ */
value: ProtoControllerRumble; value: ProtoControllerRumble;
case: "controllerRumble"; case: "controllerRumble";
} | {
/**
* @generated from field: proto.ProtoControllerStateBatch controller_state_batch = 12;
*/
value: ProtoControllerStateBatch;
case: "controllerStateBatch";
} | { } | {
/** /**
* Signaling types * Signaling types

View File

@@ -2,15 +2,15 @@
// @generated from file types.proto (package proto, syntax proto3) // @generated from file types.proto (package proto, syntax proto3)
/* eslint-disable */ /* eslint-disable */
import type { GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2"; import type { GenEnum, GenFile, GenMessage } from "@bufbuild/protobuf/codegenv2";
import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
import type { Message } from "@bufbuild/protobuf"; import type { Message } from "@bufbuild/protobuf";
/** /**
* Describes the file types.proto. * Describes the file types.proto.
*/ */
export const file_types: GenFile = /*@__PURE__*/ export const file_types: GenFile = /*@__PURE__*/
fileDesc("Cgt0eXBlcy5wcm90bxIFcHJvdG8iJgoOUHJvdG9Nb3VzZU1vdmUSCQoBeBgBIAEoBRIJCgF5GAIgASgFIikKEVByb3RvTW91c2VNb3ZlQWJzEgkKAXgYASABKAUSCQoBeRgCIAEoBSInCg9Qcm90b01vdXNlV2hlZWwSCQoBeBgBIAEoBRIJCgF5GAIgASgFIiAKEVByb3RvTW91c2VLZXlEb3duEgsKA2tleRgBIAEoBSIeCg9Qcm90b01vdXNlS2V5VXASCwoDa2V5GAEgASgFIhsKDFByb3RvS2V5RG93bhILCgNrZXkYASABKAUiGQoKUHJvdG9LZXlVcBILCgNrZXkYASABKAUiTQoVUHJvdG9Db250cm9sbGVyQXR0YWNoEgoKAmlkGAEgASgJEhQKDHNlc3Npb25fc2xvdBgCIAEoBRISCgpzZXNzaW9uX2lkGAMgASgJIkEKFVByb3RvQ29udHJvbGxlckRldGFjaBIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCSJiChVQcm90b0NvbnRyb2xsZXJCdXR0b24SFAoMc2Vzc2lvbl9zbG90GAEgASgFEhIKCnNlc3Npb25faWQYAiABKAkSDgoGYnV0dG9uGAMgASgFEg8KB3ByZXNzZWQYBCABKAgiYgoWUHJvdG9Db250cm9sbGVyVHJpZ2dlchIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCRIPCgd0cmlnZ2VyGAMgASgFEg0KBXZhbHVlGAQgASgFImUKFFByb3RvQ29udHJvbGxlclN0aWNrEhQKDHNlc3Npb25fc2xvdBgBIAEoBRISCgpzZXNzaW9uX2lkGAIgASgJEg0KBXN0aWNrGAMgASgFEgkKAXgYBCABKAUSCQoBeRgFIAEoBSJcChNQcm90b0NvbnRyb2xsZXJBeGlzEhQKDHNlc3Npb25fc2xvdBgBIAEoBRISCgpzZXNzaW9uX2lkGAIgASgJEgwKBGF4aXMYAyABKAUSDQoFdmFsdWUYBCABKAUiggEKFVByb3RvQ29udHJvbGxlclJ1bWJsZRIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCRIVCg1sb3dfZnJlcXVlbmN5GAMgASgFEhYKDmhpZ2hfZnJlcXVlbmN5GAQgASgFEhAKCGR1cmF0aW9uGAUgASgFIqoBChNSVENJY2VDYW5kaWRhdGVJbml0EhEKCWNhbmRpZGF0ZRgBIAEoCRIaCg1zZHBNTGluZUluZGV4GAIgASgNSACIAQESEwoGc2RwTWlkGAMgASgJSAGIAQESHQoQdXNlcm5hbWVGcmFnbWVudBgEIAEoCUgCiAEBQhAKDl9zZHBNTGluZUluZGV4QgkKB19zZHBNaWRCEwoRX3VzZXJuYW1lRnJhZ21lbnQiNgoZUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdBILCgNzZHAYASABKAkSDAoEdHlwZRgCIAEoCSI5CghQcm90b0lDRRItCgljYW5kaWRhdGUYASABKAsyGi5wcm90by5SVENJY2VDYW5kaWRhdGVJbml0IjkKCFByb3RvU0RQEi0KA3NkcBgBIAEoCzIgLnByb3RvLlJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQiGAoIUHJvdG9SYXcSDAoEZGF0YRgBIAEoCSJFChxQcm90b0NsaWVudFJlcXVlc3RSb29tU3RyZWFtEhEKCXJvb21fbmFtZRgBIAEoCRISCgpzZXNzaW9uX2lkGAIgASgJIkcKF1Byb3RvQ2xpZW50RGlzY29ubmVjdGVkEhIKCnNlc3Npb25faWQYASABKAkSGAoQY29udHJvbGxlcl9zbG90cxgCIAMoBSIqChVQcm90b1NlcnZlclB1c2hTdHJlYW0SEQoJcm9vbV9uYW1lGAEgASgJQhZaFHJlbGF5L2ludGVybmFsL3Byb3RvYgZwcm90bzM"); fileDesc("Cgt0eXBlcy5wcm90bxIFcHJvdG8iJgoOUHJvdG9Nb3VzZU1vdmUSCQoBeBgBIAEoBRIJCgF5GAIgASgFIikKEVByb3RvTW91c2VNb3ZlQWJzEgkKAXgYASABKAUSCQoBeRgCIAEoBSInCg9Qcm90b01vdXNlV2hlZWwSCQoBeBgBIAEoBRIJCgF5GAIgASgFIiAKEVByb3RvTW91c2VLZXlEb3duEgsKA2tleRgBIAEoBSIeCg9Qcm90b01vdXNlS2V5VXASCwoDa2V5GAEgASgFIhsKDFByb3RvS2V5RG93bhILCgNrZXkYASABKAUiGQoKUHJvdG9LZXlVcBILCgNrZXkYASABKAUiTQoVUHJvdG9Db250cm9sbGVyQXR0YWNoEgoKAmlkGAEgASgJEhQKDHNlc3Npb25fc2xvdBgCIAEoBRISCgpzZXNzaW9uX2lkGAMgASgJIkEKFVByb3RvQ29udHJvbGxlckRldGFjaBIUCgxzZXNzaW9uX3Nsb3QYASABKAUSEgoKc2Vzc2lvbl9pZBgCIAEoCSKCAQoVUHJvdG9Db250cm9sbGVyUnVtYmxlEhQKDHNlc3Npb25fc2xvdBgBIAEoBRISCgpzZXNzaW9uX2lkGAIgASgJEhUKDWxvd19mcmVxdWVuY3kYAyABKAUSFgoOaGlnaF9mcmVxdWVuY3kYBCABKAUSEAoIZHVyYXRpb24YBSABKAUi0AUKGVByb3RvQ29udHJvbGxlclN0YXRlQmF0Y2gSFAoMc2Vzc2lvbl9zbG90GAEgASgFEhIKCnNlc3Npb25faWQYAiABKAkSQAoLdXBkYXRlX3R5cGUYAyABKA4yKy5wcm90by5Qcm90b0NvbnRyb2xsZXJTdGF0ZUJhdGNoLlVwZGF0ZVR5cGUSEAoIc2VxdWVuY2UYBCABKA0SVAoTYnV0dG9uX2NoYW5nZWRfbWFzaxgFIAMoCzI3LnByb3RvLlByb3RvQ29udHJvbGxlclN0YXRlQmF0Y2guQnV0dG9uQ2hhbmdlZE1hc2tFbnRyeRIZCgxsZWZ0X3N0aWNrX3gYBiABKAVIAIgBARIZCgxsZWZ0X3N0aWNrX3kYByABKAVIAYgBARIaCg1yaWdodF9zdGlja194GAggASgFSAKIAQESGgoNcmlnaHRfc3RpY2tfeRgJIAEoBUgDiAEBEhkKDGxlZnRfdHJpZ2dlchgKIAEoBUgEiAEBEhoKDXJpZ2h0X3RyaWdnZXIYCyABKAVIBYgBARITCgZkcGFkX3gYDCABKAVIBogBARITCgZkcGFkX3kYDSABKAVIB4gBARIbCg5jaGFuZ2VkX2ZpZWxkcxgOIAEoDUgIiAEBGjgKFkJ1dHRvbkNoYW5nZWRNYXNrRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgIOgI4ASInCgpVcGRhdGVUeXBlEg4KCkZVTExfU1RBVEUQABIJCgVERUxUQRABQg8KDV9sZWZ0X3N0aWNrX3hCDwoNX2xlZnRfc3RpY2tfeUIQCg5fcmlnaHRfc3RpY2tfeEIQCg5fcmlnaHRfc3RpY2tfeUIPCg1fbGVmdF90cmlnZ2VyQhAKDl9yaWdodF90cmlnZ2VyQgkKB19kcGFkX3hCCQoHX2RwYWRfeUIRCg9fY2hhbmdlZF9maWVsZHMiqgEKE1JUQ0ljZUNhbmRpZGF0ZUluaXQSEQoJY2FuZGlkYXRlGAEgASgJEhoKDXNkcE1MaW5lSW5kZXgYAiABKA1IAIgBARITCgZzZHBNaWQYAyABKAlIAYgBARIdChB1c2VybmFtZUZyYWdtZW50GAQgASgJSAKIAQFCEAoOX3NkcE1MaW5lSW5kZXhCCQoHX3NkcE1pZEITChFfdXNlcm5hbWVGcmFnbWVudCI2ChlSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0EgsKA3NkcBgBIAEoCRIMCgR0eXBlGAIgASgJIjkKCFByb3RvSUNFEi0KCWNhbmRpZGF0ZRgBIAEoCzIaLnByb3RvLlJUQ0ljZUNhbmRpZGF0ZUluaXQiOQoIUHJvdG9TRFASLQoDc2RwGAEgASgLMiAucHJvdG8uUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCIYCghQcm90b1JhdxIMCgRkYXRhGAEgASgJIkUKHFByb3RvQ2xpZW50UmVxdWVzdFJvb21TdHJlYW0SEQoJcm9vbV9uYW1lGAEgASgJEhIKCnNlc3Npb25faWQYAiABKAkiRwoXUHJvdG9DbGllbnREaXNjb25uZWN0ZWQSEgoKc2Vzc2lvbl9pZBgBIAEoCRIYChBjb250cm9sbGVyX3Nsb3RzGAIgAygFIioKFVByb3RvU2VydmVyUHVzaFN0cmVhbRIRCglyb29tX25hbWUYASABKAlCFloUcmVsYXkvaW50ZXJuYWwvcHJvdG9iBnByb3RvMw");
/** /**
* MouseMove message * MouseMove message
@@ -223,181 +223,6 @@ export type ProtoControllerDetach = Message<"proto.ProtoControllerDetach"> & {
export const ProtoControllerDetachSchema: GenMessage<ProtoControllerDetach> = /*@__PURE__*/ export const ProtoControllerDetachSchema: GenMessage<ProtoControllerDetach> = /*@__PURE__*/
messageDesc(file_types, 8); messageDesc(file_types, 8);
/**
* ControllerButton message
*
* @generated from message proto.ProtoControllerButton
*/
export type ProtoControllerButton = Message<"proto.ProtoControllerButton"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Button code (linux input event code)
*
* @generated from field: int32 button = 3;
*/
button: number;
/**
* true if pressed, false if released
*
* @generated from field: bool pressed = 4;
*/
pressed: boolean;
};
/**
* Describes the message proto.ProtoControllerButton.
* Use `create(ProtoControllerButtonSchema)` to create a new message.
*/
export const ProtoControllerButtonSchema: GenMessage<ProtoControllerButton> = /*@__PURE__*/
messageDesc(file_types, 9);
/**
* ControllerTriggers message
*
* @generated from message proto.ProtoControllerTrigger
*/
export type ProtoControllerTrigger = Message<"proto.ProtoControllerTrigger"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Trigger number (0 for left, 1 for right)
*
* @generated from field: int32 trigger = 3;
*/
trigger: number;
/**
* trigger value (-32768 to 32767)
*
* @generated from field: int32 value = 4;
*/
value: number;
};
/**
* Describes the message proto.ProtoControllerTrigger.
* Use `create(ProtoControllerTriggerSchema)` to create a new message.
*/
export const ProtoControllerTriggerSchema: GenMessage<ProtoControllerTrigger> = /*@__PURE__*/
messageDesc(file_types, 10);
/**
* ControllerSticks message
*
* @generated from message proto.ProtoControllerStick
*/
export type ProtoControllerStick = Message<"proto.ProtoControllerStick"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Stick number (0 for left, 1 for right)
*
* @generated from field: int32 stick = 3;
*/
stick: number;
/**
* X axis value (-32768 to 32767)
*
* @generated from field: int32 x = 4;
*/
x: number;
/**
* Y axis value (-32768 to 32767)
*
* @generated from field: int32 y = 5;
*/
y: number;
};
/**
* Describes the message proto.ProtoControllerStick.
* Use `create(ProtoControllerStickSchema)` to create a new message.
*/
export const ProtoControllerStickSchema: GenMessage<ProtoControllerStick> = /*@__PURE__*/
messageDesc(file_types, 11);
/**
* ControllerAxis message
*
* @generated from message proto.ProtoControllerAxis
*/
export type ProtoControllerAxis = Message<"proto.ProtoControllerAxis"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
*
* @generated from field: int32 axis = 3;
*/
axis: number;
/**
* axis value (-1 to 1)
*
* @generated from field: int32 value = 4;
*/
value: number;
};
/**
* Describes the message proto.ProtoControllerAxis.
* Use `create(ProtoControllerAxisSchema)` to create a new message.
*/
export const ProtoControllerAxisSchema: GenMessage<ProtoControllerAxis> = /*@__PURE__*/
messageDesc(file_types, 12);
/** /**
* ControllerRumble message * ControllerRumble message
* *
@@ -445,7 +270,145 @@ export type ProtoControllerRumble = Message<"proto.ProtoControllerRumble"> & {
* Use `create(ProtoControllerRumbleSchema)` to create a new message. * Use `create(ProtoControllerRumbleSchema)` to create a new message.
*/ */
export const ProtoControllerRumbleSchema: GenMessage<ProtoControllerRumble> = /*@__PURE__*/ export const ProtoControllerRumbleSchema: GenMessage<ProtoControllerRumble> = /*@__PURE__*/
messageDesc(file_types, 13); messageDesc(file_types, 9);
/**
* ControllerStateBatch - single message containing full or partial controller state
*
* @generated from message proto.ProtoControllerStateBatch
*/
export type ProtoControllerStateBatch = Message<"proto.ProtoControllerStateBatch"> & {
/**
* Session specific slot number (0-3)
*
* @generated from field: int32 session_slot = 1;
*/
sessionSlot: number;
/**
* Session ID of the client
*
* @generated from field: string session_id = 2;
*/
sessionId: string;
/**
* @generated from field: proto.ProtoControllerStateBatch.UpdateType update_type = 3;
*/
updateType: ProtoControllerStateBatch_UpdateType;
/**
* Sequence number for packet loss detection
*
* @generated from field: uint32 sequence = 4;
*/
sequence: number;
/**
* Button state map (Linux event codes)
*
* @generated from field: map<int32, bool> button_changed_mask = 5;
*/
buttonChangedMask: { [key: number]: boolean };
/**
* Analog inputs
*
* -32768 to 32767
*
* @generated from field: optional int32 left_stick_x = 6;
*/
leftStickX?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 left_stick_y = 7;
*/
leftStickY?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 right_stick_x = 8;
*/
rightStickX?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 right_stick_y = 9;
*/
rightStickY?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 left_trigger = 10;
*/
leftTrigger?: number;
/**
* -32768 to 32767
*
* @generated from field: optional int32 right_trigger = 11;
*/
rightTrigger?: number;
/**
* -1, 0, or 1
*
* @generated from field: optional int32 dpad_x = 12;
*/
dpadX?: number;
/**
* -1, 0, or 1
*
* @generated from field: optional int32 dpad_y = 13;
*/
dpadY?: number;
/**
* Bitmask indicating which fields have changed
* Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
*
* @generated from field: optional uint32 changed_fields = 14;
*/
changedFields?: number;
};
/**
* Describes the message proto.ProtoControllerStateBatch.
* Use `create(ProtoControllerStateBatchSchema)` to create a new message.
*/
export const ProtoControllerStateBatchSchema: GenMessage<ProtoControllerStateBatch> = /*@__PURE__*/
messageDesc(file_types, 10);
/**
* @generated from enum proto.ProtoControllerStateBatch.UpdateType
*/
export enum ProtoControllerStateBatch_UpdateType {
/**
* Complete controller state
*
* @generated from enum value: FULL_STATE = 0;
*/
FULL_STATE = 0,
/**
* Only changed fields
*
* @generated from enum value: DELTA = 1;
*/
DELTA = 1,
}
/**
* Describes the enum proto.ProtoControllerStateBatch.UpdateType.
*/
export const ProtoControllerStateBatch_UpdateTypeSchema: GenEnum<ProtoControllerStateBatch_UpdateType> = /*@__PURE__*/
enumDesc(file_types, 10, 0);
/** /**
* @generated from message proto.RTCIceCandidateInit * @generated from message proto.RTCIceCandidateInit
@@ -477,7 +440,7 @@ export type RTCIceCandidateInit = Message<"proto.RTCIceCandidateInit"> & {
* Use `create(RTCIceCandidateInitSchema)` to create a new message. * Use `create(RTCIceCandidateInitSchema)` to create a new message.
*/ */
export const RTCIceCandidateInitSchema: GenMessage<RTCIceCandidateInit> = /*@__PURE__*/ export const RTCIceCandidateInitSchema: GenMessage<RTCIceCandidateInit> = /*@__PURE__*/
messageDesc(file_types, 14); messageDesc(file_types, 11);
/** /**
* @generated from message proto.RTCSessionDescriptionInit * @generated from message proto.RTCSessionDescriptionInit
@@ -499,7 +462,7 @@ export type RTCSessionDescriptionInit = Message<"proto.RTCSessionDescriptionInit
* Use `create(RTCSessionDescriptionInitSchema)` to create a new message. * Use `create(RTCSessionDescriptionInitSchema)` to create a new message.
*/ */
export const RTCSessionDescriptionInitSchema: GenMessage<RTCSessionDescriptionInit> = /*@__PURE__*/ export const RTCSessionDescriptionInitSchema: GenMessage<RTCSessionDescriptionInit> = /*@__PURE__*/
messageDesc(file_types, 15); messageDesc(file_types, 12);
/** /**
* ProtoICE message * ProtoICE message
@@ -518,7 +481,7 @@ export type ProtoICE = Message<"proto.ProtoICE"> & {
* Use `create(ProtoICESchema)` to create a new message. * Use `create(ProtoICESchema)` to create a new message.
*/ */
export const ProtoICESchema: GenMessage<ProtoICE> = /*@__PURE__*/ export const ProtoICESchema: GenMessage<ProtoICE> = /*@__PURE__*/
messageDesc(file_types, 16); messageDesc(file_types, 13);
/** /**
* ProtoSDP message * ProtoSDP message
@@ -537,7 +500,7 @@ export type ProtoSDP = Message<"proto.ProtoSDP"> & {
* Use `create(ProtoSDPSchema)` to create a new message. * Use `create(ProtoSDPSchema)` to create a new message.
*/ */
export const ProtoSDPSchema: GenMessage<ProtoSDP> = /*@__PURE__*/ export const ProtoSDPSchema: GenMessage<ProtoSDP> = /*@__PURE__*/
messageDesc(file_types, 17); messageDesc(file_types, 14);
/** /**
* ProtoRaw message * ProtoRaw message
@@ -556,7 +519,7 @@ export type ProtoRaw = Message<"proto.ProtoRaw"> & {
* Use `create(ProtoRawSchema)` to create a new message. * Use `create(ProtoRawSchema)` to create a new message.
*/ */
export const ProtoRawSchema: GenMessage<ProtoRaw> = /*@__PURE__*/ export const ProtoRawSchema: GenMessage<ProtoRaw> = /*@__PURE__*/
messageDesc(file_types, 18); messageDesc(file_types, 15);
/** /**
* ProtoClientRequestRoomStream message * ProtoClientRequestRoomStream message
@@ -580,7 +543,7 @@ export type ProtoClientRequestRoomStream = Message<"proto.ProtoClientRequestRoom
* Use `create(ProtoClientRequestRoomStreamSchema)` to create a new message. * Use `create(ProtoClientRequestRoomStreamSchema)` to create a new message.
*/ */
export const ProtoClientRequestRoomStreamSchema: GenMessage<ProtoClientRequestRoomStream> = /*@__PURE__*/ export const ProtoClientRequestRoomStreamSchema: GenMessage<ProtoClientRequestRoomStream> = /*@__PURE__*/
messageDesc(file_types, 19); messageDesc(file_types, 16);
/** /**
* ProtoClientDisconnected message * ProtoClientDisconnected message
@@ -604,7 +567,7 @@ export type ProtoClientDisconnected = Message<"proto.ProtoClientDisconnected"> &
* Use `create(ProtoClientDisconnectedSchema)` to create a new message. * Use `create(ProtoClientDisconnectedSchema)` to create a new message.
*/ */
export const ProtoClientDisconnectedSchema: GenMessage<ProtoClientDisconnected> = /*@__PURE__*/ export const ProtoClientDisconnectedSchema: GenMessage<ProtoClientDisconnected> = /*@__PURE__*/
messageDesc(file_types, 20); messageDesc(file_types, 17);
/** /**
* ProtoServerPushStream message * ProtoServerPushStream message
@@ -623,5 +586,5 @@ export type ProtoServerPushStream = Message<"proto.ProtoServerPushStream"> & {
* Use `create(ProtoServerPushStreamSchema)` to create a new message. * Use `create(ProtoServerPushStreamSchema)` to create a new message.
*/ */
export const ProtoServerPushStreamSchema: GenMessage<ProtoServerPushStream> = /*@__PURE__*/ export const ProtoServerPushStreamSchema: GenMessage<ProtoServerPushStream> = /*@__PURE__*/
messageDesc(file_types, 21); messageDesc(file_types, 18);

View File

@@ -9,8 +9,8 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/node": "^9.4.2", "@astrojs/node": "9.5.0",
"@nestri/input": "*", "@nestri/input": "*",
"astro": "5.14.5" "astro": "5.15.1"
} }
} }

View File

@@ -10,7 +10,7 @@ require (
github.com/oklog/ulid/v2 v2.1.1 github.com/oklog/ulid/v2 v2.1.1
github.com/pion/ice/v4 v4.0.10 github.com/pion/ice/v4 v4.0.10
github.com/pion/interceptor v0.1.41 github.com/pion/interceptor v0.1.41
github.com/pion/rtp v1.8.24 github.com/pion/rtp v1.8.25
github.com/pion/webrtc/v4 v4.1.6 github.com/pion/webrtc/v4 v4.1.6
github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang v1.23.2
google.golang.org/protobuf v1.36.10 google.golang.org/protobuf v1.36.10
@@ -30,7 +30,7 @@ require (
github.com/gorilla/websocket v1.5.3 // indirect github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.3.0 // indirect github.com/huin/goupnp v1.3.0 // indirect
github.com/ipfs/go-cid v0.5.0 // indirect github.com/ipfs/go-cid v0.6.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.18.1 // indirect github.com/klauspost/compress v1.18.1 // indirect
@@ -40,7 +40,7 @@ require (
github.com/libp2p/go-flow-metrics v0.3.0 // indirect github.com/libp2p/go-flow-metrics v0.3.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-netroute v0.3.0 // indirect github.com/libp2p/go-netroute v0.4.0 // indirect
github.com/libp2p/go-yamux/v5 v5.1.0 // indirect github.com/libp2p/go-yamux/v5 v5.1.0 // indirect
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
@@ -71,13 +71,13 @@ require (
github.com/pion/sdp/v3 v3.0.16 // indirect github.com/pion/sdp/v3 v3.0.16 // indirect
github.com/pion/srtp/v3 v3.0.8 // indirect github.com/pion/srtp/v3 v3.0.8 // indirect
github.com/pion/stun v0.6.1 // indirect github.com/pion/stun v0.6.1 // indirect
github.com/pion/stun/v3 v3.0.0 // indirect github.com/pion/stun/v3 v3.0.1 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.8 // indirect github.com/pion/transport/v3 v3.0.8 // indirect
github.com/pion/turn/v4 v4.1.1 // indirect github.com/pion/turn/v4 v4.1.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.1 // indirect github.com/prometheus/common v0.67.2 // indirect
github.com/prometheus/procfs v0.17.0 // indirect github.com/prometheus/procfs v0.19.2 // indirect
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect github.com/quic-go/quic-go v0.55.0 // indirect
github.com/quic-go/webtransport-go v0.9.0 // indirect github.com/quic-go/webtransport-go v0.9.0 // indirect
@@ -91,12 +91,12 @@ require (
go.uber.org/zap v1.27.0 // indirect go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/crypto v0.43.0 // indirect golang.org/x/crypto v0.43.0 // indirect
golang.org/x/exp v0.0.0-20251017212417-90e834f514db // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/mod v0.29.0 // indirect golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect golang.org/x/net v0.46.0 // indirect
golang.org/x/sync v0.17.0 // indirect golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect golang.org/x/sys v0.37.0 // indirect
golang.org/x/telemetry v0.0.0-20251014153721-24f779f6aaef // indirect golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 // indirect
golang.org/x/text v0.30.0 // indirect golang.org/x/text v0.30.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.38.0 // indirect golang.org/x/tools v0.38.0 // indirect

View File

@@ -71,8 +71,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= github.com/ipfs/go-cid v0.6.0 h1:DlOReBV1xhHBhhfy/gBNNTSyfOM6rLiIx9J7A4DGf30=
github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= github.com/ipfs/go-cid v0.6.0/go.mod h1:NC4kS1LZjzfhK40UGmpXv5/qD2kcMzACYJNntCUiDhQ=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
@@ -113,8 +113,8 @@ github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUI
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q=
github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA=
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/libp2p/go-yamux/v5 v5.1.0 h1:8Qlxj4E9JGJAQVW6+uj2o7mqkqsIVlSUGmTWhlXzoHE= github.com/libp2p/go-yamux/v5 v5.1.0 h1:8Qlxj4E9JGJAQVW6+uj2o7mqkqsIVlSUGmTWhlXzoHE=
@@ -199,8 +199,8 @@ github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo= github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo=
github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo= github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo=
github.com/pion/rtp v1.8.24 h1:+ICyZXUQDv95EsHN70RrA4XKJf5MGWyC6QQc1u6/ynI= github.com/pion/rtp v1.8.25 h1:b8+y44GNbwOJTYWuVan7SglX/hMlicVCAtL50ztyZHw=
github.com/pion/rtp v1.8.24/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM= github.com/pion/rtp v1.8.25/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM=
github.com/pion/sctp v1.8.40 h1:bqbgWYOrUhsYItEnRObUYZuzvOMsVplS3oNgzedBlG8= github.com/pion/sctp v1.8.40 h1:bqbgWYOrUhsYItEnRObUYZuzvOMsVplS3oNgzedBlG8=
github.com/pion/sctp v1.8.40/go.mod h1:SPBBUENXE6ThkEksN5ZavfAhFYll+h+66ZiG6IZQuzo= github.com/pion/sctp v1.8.40/go.mod h1:SPBBUENXE6ThkEksN5ZavfAhFYll+h+66ZiG6IZQuzo=
github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo= github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo=
@@ -209,16 +209,16 @@ github.com/pion/srtp/v3 v3.0.8 h1:RjRrjcIeQsilPzxvdaElN0CpuQZdMvcl9VZ5UY9suUM=
github.com/pion/srtp/v3 v3.0.8/go.mod h1:2Sq6YnDH7/UDCvkSoHSDNDeyBcFgWL0sAVycVbAsXFg= github.com/pion/srtp/v3 v3.0.8/go.mod h1:2Sq6YnDH7/UDCvkSoHSDNDeyBcFgWL0sAVycVbAsXFg=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= github.com/pion/stun/v3 v3.0.1 h1:jx1uUq6BdPihF0yF33Jj2mh+C9p0atY94IkdnW174kA=
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= github.com/pion/stun/v3 v3.0.1/go.mod h1:RHnvlKFg+qHgoKIqtQWMOJF52wsImCAf/Jh5GjX+4Tw=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
github.com/pion/transport/v3 v3.0.8 h1:oI3myyYnTKUSTthu/NZZ8eu2I5sHbxbUNNFW62olaYc= github.com/pion/transport/v3 v3.0.8 h1:oI3myyYnTKUSTthu/NZZ8eu2I5sHbxbUNNFW62olaYc=
github.com/pion/transport/v3 v3.0.8/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ= github.com/pion/transport/v3 v3.0.8/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ=
github.com/pion/turn/v4 v4.1.1 h1:9UnY2HB99tpDyz3cVVZguSxcqkJ1DsTSZ+8TGruh4fc= github.com/pion/turn/v4 v4.1.2 h1:Em2svpl6aBFa88dLhxypMUzaLjC79kWZWx8FIov01cc=
github.com/pion/turn/v4 v4.1.1/go.mod h1:2123tHk1O++vmjI5VSD0awT50NywDAq5A2NNNU4Jjs8= github.com/pion/turn/v4 v4.1.2/go.mod h1:ISYWfZYy0Z3tXzRpyYZHTL+U23yFQIspfxogdQ8pn9Y=
github.com/pion/webrtc/v4 v4.1.6 h1:srHH2HwvCGwPba25EYJgUzgLqCQoXl1VCUnrGQMSzUw= github.com/pion/webrtc/v4 v4.1.6 h1:srHH2HwvCGwPba25EYJgUzgLqCQoXl1VCUnrGQMSzUw=
github.com/pion/webrtc/v4 v4.1.6/go.mod h1:wKecGRlkl3ox/As/MYghJL+b/cVXMEhoPMJWPuGQFhU= github.com/pion/webrtc/v4 v4.1.6/go.mod h1:wKecGRlkl3ox/As/MYghJL+b/cVXMEhoPMJWPuGQFhU=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -231,11 +231,11 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI= github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q= github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
@@ -323,8 +323,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20251017212417-90e834f514db h1:by6IehL4BH5k3e3SJmcoNbOobMey2SLpAF79iPOEBvw= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
golang.org/x/exp v0.0.0-20251017212417-90e834f514db/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -396,8 +396,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20251014153721-24f779f6aaef h1:5xFtU4tmJMJSxSeDlr1dgBff2tDXrq0laLdS1EA3LYw= golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 h1:DwMAzqwLj2rVin75cRFh1kfhwQY3hyHrU1oCEDZXPmQ=
golang.org/x/telemetry v0.0.0-20251014153721-24f779f6aaef/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

View File

@@ -10,7 +10,6 @@ import (
"os" "os"
"relay/internal/common" "relay/internal/common"
"relay/internal/shared" "relay/internal/shared"
"time"
"github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
@@ -38,16 +37,6 @@ var globalRelay *Relay
// -- Structs -- // -- Structs --
// ClientSession tracks browser client connections
type ClientSession struct {
PeerID peer.ID
SessionID string
RoomName string
ConnectedAt time.Time
LastActivity time.Time
ControllerSlots []int32 // Track which controller slots this client owns
}
// Relay structure enhanced with metrics and state // Relay structure enhanced with metrics and state
type Relay struct { type Relay struct {
*PeerInfo *PeerInfo
@@ -59,7 +48,6 @@ type Relay struct {
// Local // Local
LocalRooms *common.SafeMap[ulid.ULID, *shared.Room] // room ID -> local Room struct (hosted by this relay) LocalRooms *common.SafeMap[ulid.ULID, *shared.Room] // room ID -> local Room struct (hosted by this relay)
LocalMeshConnections *common.SafeMap[peer.ID, *webrtc.PeerConnection] // peer ID -> PeerConnection (connected to this relay) LocalMeshConnections *common.SafeMap[peer.ID, *webrtc.PeerConnection] // peer ID -> PeerConnection (connected to this relay)
ClientSessions *common.SafeMap[peer.ID, *ClientSession] // peer ID -> ClientSession
// Protocols // Protocols
ProtocolRegistry ProtocolRegistry
@@ -156,7 +144,6 @@ func NewRelay(ctx context.Context, port int, identityKey crypto.PrivKey) (*Relay
PingService: pingSvc, PingService: pingSvc,
LocalRooms: common.NewSafeMap[ulid.ULID, *shared.Room](), LocalRooms: common.NewSafeMap[ulid.ULID, *shared.Room](),
LocalMeshConnections: common.NewSafeMap[peer.ID, *webrtc.PeerConnection](), LocalMeshConnections: common.NewSafeMap[peer.ID, *webrtc.PeerConnection](),
ClientSessions: common.NewSafeMap[peer.ID, *ClientSession](),
} }
// Add network notifier after relay is initialized // Add network notifier after relay is initialized

View File

@@ -11,7 +11,6 @@ import (
"relay/internal/common" "relay/internal/common"
"relay/internal/connections" "relay/internal/connections"
"relay/internal/shared" "relay/internal/shared"
"time"
gen "relay/internal/proto" gen "relay/internal/proto"
@@ -111,16 +110,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
sessionID = ulid.String() sessionID = ulid.String()
} }
session := &ClientSession{ slog.Info("Client session requested room stream", "session", sessionID, "room", reqMsg.RoomName)
PeerID: stream.Conn().RemotePeer(),
SessionID: sessionID,
RoomName: reqMsg.RoomName,
ConnectedAt: time.Now(),
LastActivity: time.Now(),
}
sp.relay.ClientSessions.Set(stream.Conn().RemotePeer(), session)
slog.Info("Client session established", "peer", session.PeerID, "session", sessionID, "room", reqMsg.RoomName)
// Send session ID back to client // Send session ID back to client
sesMsg, err := common.CreateMessage( sesMsg, err := common.CreateMessage(
@@ -177,7 +167,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
// Create participant for this viewer // Create participant for this viewer
participant, err := shared.NewParticipant( participant, err := shared.NewParticipant(
"", sessionID,
stream.Conn().RemotePeer(), stream.Conn().RemotePeer(),
) )
if err != nil { if err != nil {
@@ -185,11 +175,6 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
continue continue
} }
// If this is a client session, link it
if session, ok := sp.relay.ClientSessions.Get(stream.Conn().RemotePeer()); ok {
participant.SessionID = session.SessionID
}
// Assign peer connection // Assign peer connection
participant.PeerConnection = pc participant.PeerConnection = pc
@@ -265,57 +250,9 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
// Track controller input separately // Track controller input separately
ndc.RegisterMessageCallback("controllerInput", func(data []byte) { ndc.RegisterMessageCallback("controllerInput", func(data []byte) {
// Parse the message to track controller slots for client sessions // Parse the message to track controller slots for client sessions
var msgWrapper gen.ProtoMessage var controllerMsgWrapper gen.ProtoMessage
if err = proto.Unmarshal(data, &msgWrapper); err != nil { if err = proto.Unmarshal(data, &controllerMsgWrapper); err != nil {
slog.Error("Failed to unmarshal controller input", "err", err) slog.Error("Failed to unmarshal controller input", "err", err)
} else if msgWrapper.Payload != nil {
// Get the peer ID for this connection
peerID := stream.Conn().RemotePeer()
// Check if it's a controller attach with assigned slot
if attach := msgWrapper.GetControllerAttach(); attach != nil && attach.SessionSlot >= 0 {
if session, ok := sp.relay.ClientSessions.Get(peerID); ok {
// Check if slot already tracked
hasSlot := false
for _, slot := range session.ControllerSlots {
if slot == attach.SessionSlot {
hasSlot = true
break
}
}
if !hasSlot {
session.ControllerSlots = append(session.ControllerSlots, attach.SessionSlot)
session.LastActivity = time.Now()
slog.Info("Controller slot assigned to client session",
"session", session.SessionID,
"slot", attach.SessionSlot,
"total_slots", len(session.ControllerSlots))
}
}
}
// Check if it's a controller detach
if detach := msgWrapper.GetControllerDetach(); detach != nil && detach.SessionSlot >= 0 {
if session, ok := sp.relay.ClientSessions.Get(peerID); ok {
newSlots := make([]int32, 0, len(session.ControllerSlots))
for _, slot := range session.ControllerSlots {
if slot != detach.SessionSlot {
newSlots = append(newSlots, slot)
}
}
session.ControllerSlots = newSlots
session.LastActivity = time.Now()
slog.Info("Controller slot removed from client session",
"session", session.SessionID,
"slot", detach.SessionSlot,
"remaining_slots", len(session.ControllerSlots))
}
}
// Update last activity on any controller input
if session, ok := sp.relay.ClientSessions.Get(peerID); ok {
session.LastActivity = time.Now()
}
} }
// Forward to upstream room // Forward to upstream room
@@ -609,9 +546,14 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
roomMap.Range(func(peerID peer.ID, conn *StreamConnection) bool { roomMap.Range(func(peerID peer.ID, conn *StreamConnection) bool {
if conn.ndc != nil { if conn.ndc != nil {
if err = conn.ndc.SendBinary(data); err != nil { if err = conn.ndc.SendBinary(data); err != nil {
if errors.Is(err, io.ErrClosedPipe) {
slog.Warn("Failed to forward controller input to viewer, treating as disconnected", "err", err)
sp.relay.onPeerDisconnected(peerID)
} else {
slog.Error("Failed to forward controller input from pushed stream to viewer", "room", room.Name, "peer", peerID, "err", err) slog.Error("Failed to forward controller input from pushed stream to viewer", "room", room.Name, "peer", peerID, "err", err)
} }
} }
}
return true return true
}) })
} }

View File

@@ -5,14 +5,9 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"log/slog" "log/slog"
"relay/internal/common"
"relay/internal/shared" "relay/internal/shared"
"time" "time"
gen "relay/internal/proto"
"google.golang.org/protobuf/proto"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
@@ -134,46 +129,6 @@ func (r *Relay) onPeerConnected(peerID peer.ID) {
// onPeerDisconnected marks a peer as disconnected in our status view and removes latency info // onPeerDisconnected marks a peer as disconnected in our status view and removes latency info
func (r *Relay) onPeerDisconnected(peerID peer.ID) { func (r *Relay) onPeerDisconnected(peerID peer.ID) {
// Check if this was a client session disconnect
if session, ok := r.ClientSessions.Get(peerID); ok {
slog.Info("Client session disconnected",
"peer", peerID,
"session", session.SessionID,
"room", session.RoomName,
"controller_slots", session.ControllerSlots)
// Send cleanup message to nestri-server if client had active controllers
if len(session.ControllerSlots) > 0 {
room := r.GetRoomByName(session.RoomName)
if room != nil && room.DataChannel != nil {
// Create disconnect notification
disconnectMsg, err := common.CreateMessage(&gen.ProtoClientDisconnected{
SessionId: session.SessionID,
ControllerSlots: session.ControllerSlots,
}, "client-disconnected", nil)
if err != nil {
slog.Error("Failed to create client disconnect message", "err", err)
}
disMarshal, err := proto.Marshal(disconnectMsg)
if err != nil {
slog.Error("Failed to marshal client disconnect message", "err", err)
} else {
if err = room.DataChannel.SendBinary(disMarshal); err != nil {
slog.Error("Failed to send client disconnect notification", "err", err)
} else {
slog.Info("Sent controller cleanup notification to nestri-server",
"session", session.SessionID,
"slots", session.ControllerSlots)
}
}
}
}
r.ClientSessions.Delete(peerID)
return
}
// Relay peer disconnect handling // Relay peer disconnect handling
slog.Info("Mesh peer disconnected, deleting from local peer map", "peer", peerID) slog.Info("Mesh peer disconnected, deleting from local peer map", "peer", peerID)
if r.Peers.Has(peerID) { if r.Peers.Has(peerID) {

View File

@@ -87,11 +87,8 @@ type ProtoMessage struct {
// *ProtoMessage_KeyUp // *ProtoMessage_KeyUp
// *ProtoMessage_ControllerAttach // *ProtoMessage_ControllerAttach
// *ProtoMessage_ControllerDetach // *ProtoMessage_ControllerDetach
// *ProtoMessage_ControllerButton
// *ProtoMessage_ControllerTrigger
// *ProtoMessage_ControllerStick
// *ProtoMessage_ControllerAxis
// *ProtoMessage_ControllerRumble // *ProtoMessage_ControllerRumble
// *ProtoMessage_ControllerStateBatch
// *ProtoMessage_Ice // *ProtoMessage_Ice
// *ProtoMessage_Sdp // *ProtoMessage_Sdp
// *ProtoMessage_Raw // *ProtoMessage_Raw
@@ -228,42 +225,6 @@ func (x *ProtoMessage) GetControllerDetach() *ProtoControllerDetach {
return nil return nil
} }
func (x *ProtoMessage) GetControllerButton() *ProtoControllerButton {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerButton); ok {
return x.ControllerButton
}
}
return nil
}
func (x *ProtoMessage) GetControllerTrigger() *ProtoControllerTrigger {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerTrigger); ok {
return x.ControllerTrigger
}
}
return nil
}
func (x *ProtoMessage) GetControllerStick() *ProtoControllerStick {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerStick); ok {
return x.ControllerStick
}
}
return nil
}
func (x *ProtoMessage) GetControllerAxis() *ProtoControllerAxis {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerAxis); ok {
return x.ControllerAxis
}
}
return nil
}
func (x *ProtoMessage) GetControllerRumble() *ProtoControllerRumble { func (x *ProtoMessage) GetControllerRumble() *ProtoControllerRumble {
if x != nil { if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerRumble); ok { if x, ok := x.Payload.(*ProtoMessage_ControllerRumble); ok {
@@ -273,6 +234,15 @@ func (x *ProtoMessage) GetControllerRumble() *ProtoControllerRumble {
return nil return nil
} }
func (x *ProtoMessage) GetControllerStateBatch() *ProtoControllerStateBatch {
if x != nil {
if x, ok := x.Payload.(*ProtoMessage_ControllerStateBatch); ok {
return x.ControllerStateBatch
}
}
return nil
}
func (x *ProtoMessage) GetIce() *ProtoICE { func (x *ProtoMessage) GetIce() *ProtoICE {
if x != nil { if x != nil {
if x, ok := x.Payload.(*ProtoMessage_Ice); ok { if x, ok := x.Payload.(*ProtoMessage_Ice); ok {
@@ -361,6 +331,7 @@ type ProtoMessage_KeyUp struct {
} }
type ProtoMessage_ControllerAttach struct { type ProtoMessage_ControllerAttach struct {
// Controller input types
ControllerAttach *ProtoControllerAttach `protobuf:"bytes,9,opt,name=controller_attach,json=controllerAttach,proto3,oneof"` ControllerAttach *ProtoControllerAttach `protobuf:"bytes,9,opt,name=controller_attach,json=controllerAttach,proto3,oneof"`
} }
@@ -368,24 +339,12 @@ type ProtoMessage_ControllerDetach struct {
ControllerDetach *ProtoControllerDetach `protobuf:"bytes,10,opt,name=controller_detach,json=controllerDetach,proto3,oneof"` ControllerDetach *ProtoControllerDetach `protobuf:"bytes,10,opt,name=controller_detach,json=controllerDetach,proto3,oneof"`
} }
type ProtoMessage_ControllerButton struct {
ControllerButton *ProtoControllerButton `protobuf:"bytes,11,opt,name=controller_button,json=controllerButton,proto3,oneof"`
}
type ProtoMessage_ControllerTrigger struct {
ControllerTrigger *ProtoControllerTrigger `protobuf:"bytes,12,opt,name=controller_trigger,json=controllerTrigger,proto3,oneof"`
}
type ProtoMessage_ControllerStick struct {
ControllerStick *ProtoControllerStick `protobuf:"bytes,13,opt,name=controller_stick,json=controllerStick,proto3,oneof"`
}
type ProtoMessage_ControllerAxis struct {
ControllerAxis *ProtoControllerAxis `protobuf:"bytes,14,opt,name=controller_axis,json=controllerAxis,proto3,oneof"`
}
type ProtoMessage_ControllerRumble struct { type ProtoMessage_ControllerRumble struct {
ControllerRumble *ProtoControllerRumble `protobuf:"bytes,15,opt,name=controller_rumble,json=controllerRumble,proto3,oneof"` ControllerRumble *ProtoControllerRumble `protobuf:"bytes,11,opt,name=controller_rumble,json=controllerRumble,proto3,oneof"`
}
type ProtoMessage_ControllerStateBatch struct {
ControllerStateBatch *ProtoControllerStateBatch `protobuf:"bytes,12,opt,name=controller_state_batch,json=controllerStateBatch,proto3,oneof"`
} }
type ProtoMessage_Ice struct { type ProtoMessage_Ice struct {
@@ -431,16 +390,10 @@ func (*ProtoMessage_ControllerAttach) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerDetach) isProtoMessage_Payload() {} func (*ProtoMessage_ControllerDetach) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerButton) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerTrigger) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerStick) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerAxis) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerRumble) isProtoMessage_Payload() {} func (*ProtoMessage_ControllerRumble) isProtoMessage_Payload() {}
func (*ProtoMessage_ControllerStateBatch) isProtoMessage_Payload() {}
func (*ProtoMessage_Ice) isProtoMessage_Payload() {} func (*ProtoMessage_Ice) isProtoMessage_Payload() {}
func (*ProtoMessage_Sdp) isProtoMessage_Payload() {} func (*ProtoMessage_Sdp) isProtoMessage_Payload() {}
@@ -460,8 +413,7 @@ const file_messages_proto_rawDesc = "" +
"\x0emessages.proto\x12\x05proto\x1a\vtypes.proto\x1a\x15latency_tracker.proto\"k\n" + "\x0emessages.proto\x12\x05proto\x1a\vtypes.proto\x1a\x15latency_tracker.proto\"k\n" +
"\x10ProtoMessageBase\x12!\n" + "\x10ProtoMessageBase\x12!\n" +
"\fpayload_type\x18\x01 \x01(\tR\vpayloadType\x124\n" + "\fpayload_type\x18\x01 \x01(\tR\vpayloadType\x124\n" +
"\alatency\x18\x02 \x01(\v2\x1a.proto.ProtoLatencyTrackerR\alatency\"\xef\n" + "\alatency\x18\x02 \x01(\v2\x1a.proto.ProtoLatencyTrackerR\alatency\"\x9b\t\n" +
"\n" +
"\fProtoMessage\x12:\n" + "\fProtoMessage\x12:\n" +
"\fmessage_base\x18\x01 \x01(\v2\x17.proto.ProtoMessageBaseR\vmessageBase\x126\n" + "\fmessage_base\x18\x01 \x01(\v2\x17.proto.ProtoMessageBaseR\vmessageBase\x126\n" +
"\n" + "\n" +
@@ -477,11 +429,8 @@ const file_messages_proto_rawDesc = "" +
"\x11controller_attach\x18\t \x01(\v2\x1c.proto.ProtoControllerAttachH\x00R\x10controllerAttach\x12K\n" + "\x11controller_attach\x18\t \x01(\v2\x1c.proto.ProtoControllerAttachH\x00R\x10controllerAttach\x12K\n" +
"\x11controller_detach\x18\n" + "\x11controller_detach\x18\n" +
" \x01(\v2\x1c.proto.ProtoControllerDetachH\x00R\x10controllerDetach\x12K\n" + " \x01(\v2\x1c.proto.ProtoControllerDetachH\x00R\x10controllerDetach\x12K\n" +
"\x11controller_button\x18\v \x01(\v2\x1c.proto.ProtoControllerButtonH\x00R\x10controllerButton\x12N\n" + "\x11controller_rumble\x18\v \x01(\v2\x1c.proto.ProtoControllerRumbleH\x00R\x10controllerRumble\x12X\n" +
"\x12controller_trigger\x18\f \x01(\v2\x1d.proto.ProtoControllerTriggerH\x00R\x11controllerTrigger\x12H\n" + "\x16controller_state_batch\x18\f \x01(\v2 .proto.ProtoControllerStateBatchH\x00R\x14controllerStateBatch\x12#\n" +
"\x10controller_stick\x18\r \x01(\v2\x1b.proto.ProtoControllerStickH\x00R\x0fcontrollerStick\x12E\n" +
"\x0fcontroller_axis\x18\x0e \x01(\v2\x1a.proto.ProtoControllerAxisH\x00R\x0econtrollerAxis\x12K\n" +
"\x11controller_rumble\x18\x0f \x01(\v2\x1c.proto.ProtoControllerRumbleH\x00R\x10controllerRumble\x12#\n" +
"\x03ice\x18\x14 \x01(\v2\x0f.proto.ProtoICEH\x00R\x03ice\x12#\n" + "\x03ice\x18\x14 \x01(\v2\x0f.proto.ProtoICEH\x00R\x03ice\x12#\n" +
"\x03sdp\x18\x15 \x01(\v2\x0f.proto.ProtoSDPH\x00R\x03sdp\x12#\n" + "\x03sdp\x18\x15 \x01(\v2\x0f.proto.ProtoSDPH\x00R\x03sdp\x12#\n" +
"\x03raw\x18\x16 \x01(\v2\x0f.proto.ProtoRawH\x00R\x03raw\x12b\n" + "\x03raw\x18\x16 \x01(\v2\x0f.proto.ProtoRawH\x00R\x03raw\x12b\n" +
@@ -516,17 +465,14 @@ var file_messages_proto_goTypes = []any{
(*ProtoKeyUp)(nil), // 9: proto.ProtoKeyUp (*ProtoKeyUp)(nil), // 9: proto.ProtoKeyUp
(*ProtoControllerAttach)(nil), // 10: proto.ProtoControllerAttach (*ProtoControllerAttach)(nil), // 10: proto.ProtoControllerAttach
(*ProtoControllerDetach)(nil), // 11: proto.ProtoControllerDetach (*ProtoControllerDetach)(nil), // 11: proto.ProtoControllerDetach
(*ProtoControllerButton)(nil), // 12: proto.ProtoControllerButton (*ProtoControllerRumble)(nil), // 12: proto.ProtoControllerRumble
(*ProtoControllerTrigger)(nil), // 13: proto.ProtoControllerTrigger (*ProtoControllerStateBatch)(nil), // 13: proto.ProtoControllerStateBatch
(*ProtoControllerStick)(nil), // 14: proto.ProtoControllerStick (*ProtoICE)(nil), // 14: proto.ProtoICE
(*ProtoControllerAxis)(nil), // 15: proto.ProtoControllerAxis (*ProtoSDP)(nil), // 15: proto.ProtoSDP
(*ProtoControllerRumble)(nil), // 16: proto.ProtoControllerRumble (*ProtoRaw)(nil), // 16: proto.ProtoRaw
(*ProtoICE)(nil), // 17: proto.ProtoICE (*ProtoClientRequestRoomStream)(nil), // 17: proto.ProtoClientRequestRoomStream
(*ProtoSDP)(nil), // 18: proto.ProtoSDP (*ProtoClientDisconnected)(nil), // 18: proto.ProtoClientDisconnected
(*ProtoRaw)(nil), // 19: proto.ProtoRaw (*ProtoServerPushStream)(nil), // 19: proto.ProtoServerPushStream
(*ProtoClientRequestRoomStream)(nil), // 20: proto.ProtoClientRequestRoomStream
(*ProtoClientDisconnected)(nil), // 21: proto.ProtoClientDisconnected
(*ProtoServerPushStream)(nil), // 22: proto.ProtoServerPushStream
} }
var file_messages_proto_depIdxs = []int32{ var file_messages_proto_depIdxs = []int32{
2, // 0: proto.ProtoMessageBase.latency:type_name -> proto.ProtoLatencyTracker 2, // 0: proto.ProtoMessageBase.latency:type_name -> proto.ProtoLatencyTracker
@@ -540,22 +486,19 @@ var file_messages_proto_depIdxs = []int32{
9, // 8: proto.ProtoMessage.key_up:type_name -> proto.ProtoKeyUp 9, // 8: proto.ProtoMessage.key_up:type_name -> proto.ProtoKeyUp
10, // 9: proto.ProtoMessage.controller_attach:type_name -> proto.ProtoControllerAttach 10, // 9: proto.ProtoMessage.controller_attach:type_name -> proto.ProtoControllerAttach
11, // 10: proto.ProtoMessage.controller_detach:type_name -> proto.ProtoControllerDetach 11, // 10: proto.ProtoMessage.controller_detach:type_name -> proto.ProtoControllerDetach
12, // 11: proto.ProtoMessage.controller_button:type_name -> proto.ProtoControllerButton 12, // 11: proto.ProtoMessage.controller_rumble:type_name -> proto.ProtoControllerRumble
13, // 12: proto.ProtoMessage.controller_trigger:type_name -> proto.ProtoControllerTrigger 13, // 12: proto.ProtoMessage.controller_state_batch:type_name -> proto.ProtoControllerStateBatch
14, // 13: proto.ProtoMessage.controller_stick:type_name -> proto.ProtoControllerStick 14, // 13: proto.ProtoMessage.ice:type_name -> proto.ProtoICE
15, // 14: proto.ProtoMessage.controller_axis:type_name -> proto.ProtoControllerAxis 15, // 14: proto.ProtoMessage.sdp:type_name -> proto.ProtoSDP
16, // 15: proto.ProtoMessage.controller_rumble:type_name -> proto.ProtoControllerRumble 16, // 15: proto.ProtoMessage.raw:type_name -> proto.ProtoRaw
17, // 16: proto.ProtoMessage.ice:type_name -> proto.ProtoICE 17, // 16: proto.ProtoMessage.client_request_room_stream:type_name -> proto.ProtoClientRequestRoomStream
18, // 17: proto.ProtoMessage.sdp:type_name -> proto.ProtoSDP 18, // 17: proto.ProtoMessage.client_disconnected:type_name -> proto.ProtoClientDisconnected
19, // 18: proto.ProtoMessage.raw:type_name -> proto.ProtoRaw 19, // 18: proto.ProtoMessage.server_push_stream:type_name -> proto.ProtoServerPushStream
20, // 19: proto.ProtoMessage.client_request_room_stream:type_name -> proto.ProtoClientRequestRoomStream 19, // [19:19] is the sub-list for method output_type
21, // 20: proto.ProtoMessage.client_disconnected:type_name -> proto.ProtoClientDisconnected 19, // [19:19] is the sub-list for method input_type
22, // 21: proto.ProtoMessage.server_push_stream:type_name -> proto.ProtoServerPushStream 19, // [19:19] is the sub-list for extension type_name
22, // [22:22] is the sub-list for method output_type 19, // [19:19] is the sub-list for extension extendee
22, // [22:22] is the sub-list for method input_type 0, // [0:19] is the sub-list for field type_name
22, // [22:22] is the sub-list for extension type_name
22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
} }
func init() { file_messages_proto_init() } func init() { file_messages_proto_init() }
@@ -575,11 +518,8 @@ func file_messages_proto_init() {
(*ProtoMessage_KeyUp)(nil), (*ProtoMessage_KeyUp)(nil),
(*ProtoMessage_ControllerAttach)(nil), (*ProtoMessage_ControllerAttach)(nil),
(*ProtoMessage_ControllerDetach)(nil), (*ProtoMessage_ControllerDetach)(nil),
(*ProtoMessage_ControllerButton)(nil),
(*ProtoMessage_ControllerTrigger)(nil),
(*ProtoMessage_ControllerStick)(nil),
(*ProtoMessage_ControllerAxis)(nil),
(*ProtoMessage_ControllerRumble)(nil), (*ProtoMessage_ControllerRumble)(nil),
(*ProtoMessage_ControllerStateBatch)(nil),
(*ProtoMessage_Ice)(nil), (*ProtoMessage_Ice)(nil),
(*ProtoMessage_Sdp)(nil), (*ProtoMessage_Sdp)(nil),
(*ProtoMessage_Raw)(nil), (*ProtoMessage_Raw)(nil),

View File

@@ -21,6 +21,52 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
type ProtoControllerStateBatch_UpdateType int32
const (
ProtoControllerStateBatch_FULL_STATE ProtoControllerStateBatch_UpdateType = 0 // Complete controller state
ProtoControllerStateBatch_DELTA ProtoControllerStateBatch_UpdateType = 1 // Only changed fields
)
// Enum value maps for ProtoControllerStateBatch_UpdateType.
var (
ProtoControllerStateBatch_UpdateType_name = map[int32]string{
0: "FULL_STATE",
1: "DELTA",
}
ProtoControllerStateBatch_UpdateType_value = map[string]int32{
"FULL_STATE": 0,
"DELTA": 1,
}
)
func (x ProtoControllerStateBatch_UpdateType) Enum() *ProtoControllerStateBatch_UpdateType {
p := new(ProtoControllerStateBatch_UpdateType)
*p = x
return p
}
func (x ProtoControllerStateBatch_UpdateType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ProtoControllerStateBatch_UpdateType) Descriptor() protoreflect.EnumDescriptor {
return file_types_proto_enumTypes[0].Descriptor()
}
func (ProtoControllerStateBatch_UpdateType) Type() protoreflect.EnumType {
return &file_types_proto_enumTypes[0]
}
func (x ProtoControllerStateBatch_UpdateType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ProtoControllerStateBatch_UpdateType.Descriptor instead.
func (ProtoControllerStateBatch_UpdateType) EnumDescriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{10, 0}
}
// MouseMove message // MouseMove message
type ProtoMouseMove struct { type ProtoMouseMove struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@@ -474,290 +520,6 @@ func (x *ProtoControllerDetach) GetSessionId() string {
return "" return ""
} }
// ControllerButton message
type ProtoControllerButton struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Button int32 `protobuf:"varint,3,opt,name=button,proto3" json:"button,omitempty"` // Button code (linux input event code)
Pressed bool `protobuf:"varint,4,opt,name=pressed,proto3" json:"pressed,omitempty"` // true if pressed, false if released
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerButton) Reset() {
*x = ProtoControllerButton{}
mi := &file_types_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerButton) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerButton) ProtoMessage() {}
func (x *ProtoControllerButton) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerButton.ProtoReflect.Descriptor instead.
func (*ProtoControllerButton) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{9}
}
func (x *ProtoControllerButton) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerButton) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerButton) GetButton() int32 {
if x != nil {
return x.Button
}
return 0
}
func (x *ProtoControllerButton) GetPressed() bool {
if x != nil {
return x.Pressed
}
return false
}
// ControllerTriggers message
type ProtoControllerTrigger struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Trigger int32 `protobuf:"varint,3,opt,name=trigger,proto3" json:"trigger,omitempty"` // Trigger number (0 for left, 1 for right)
Value int32 `protobuf:"varint,4,opt,name=value,proto3" json:"value,omitempty"` // trigger value (-32768 to 32767)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerTrigger) Reset() {
*x = ProtoControllerTrigger{}
mi := &file_types_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerTrigger) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerTrigger) ProtoMessage() {}
func (x *ProtoControllerTrigger) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerTrigger.ProtoReflect.Descriptor instead.
func (*ProtoControllerTrigger) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{10}
}
func (x *ProtoControllerTrigger) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerTrigger) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerTrigger) GetTrigger() int32 {
if x != nil {
return x.Trigger
}
return 0
}
func (x *ProtoControllerTrigger) GetValue() int32 {
if x != nil {
return x.Value
}
return 0
}
// ControllerSticks message
type ProtoControllerStick struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Stick int32 `protobuf:"varint,3,opt,name=stick,proto3" json:"stick,omitempty"` // Stick number (0 for left, 1 for right)
X int32 `protobuf:"varint,4,opt,name=x,proto3" json:"x,omitempty"` // X axis value (-32768 to 32767)
Y int32 `protobuf:"varint,5,opt,name=y,proto3" json:"y,omitempty"` // Y axis value (-32768 to 32767)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerStick) Reset() {
*x = ProtoControllerStick{}
mi := &file_types_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerStick) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerStick) ProtoMessage() {}
func (x *ProtoControllerStick) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerStick.ProtoReflect.Descriptor instead.
func (*ProtoControllerStick) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{11}
}
func (x *ProtoControllerStick) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerStick) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerStick) GetStick() int32 {
if x != nil {
return x.Stick
}
return 0
}
func (x *ProtoControllerStick) GetX() int32 {
if x != nil {
return x.X
}
return 0
}
func (x *ProtoControllerStick) GetY() int32 {
if x != nil {
return x.Y
}
return 0
}
// ControllerAxis message
type ProtoControllerAxis struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
Axis int32 `protobuf:"varint,3,opt,name=axis,proto3" json:"axis,omitempty"` // Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
Value int32 `protobuf:"varint,4,opt,name=value,proto3" json:"value,omitempty"` // axis value (-1 to 1)
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerAxis) Reset() {
*x = ProtoControllerAxis{}
mi := &file_types_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerAxis) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerAxis) ProtoMessage() {}
func (x *ProtoControllerAxis) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerAxis.ProtoReflect.Descriptor instead.
func (*ProtoControllerAxis) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{12}
}
func (x *ProtoControllerAxis) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerAxis) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerAxis) GetAxis() int32 {
if x != nil {
return x.Axis
}
return 0
}
func (x *ProtoControllerAxis) GetValue() int32 {
if x != nil {
return x.Value
}
return 0
}
// ControllerRumble message // ControllerRumble message
type ProtoControllerRumble struct { type ProtoControllerRumble struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@@ -772,7 +534,7 @@ type ProtoControllerRumble struct {
func (x *ProtoControllerRumble) Reset() { func (x *ProtoControllerRumble) Reset() {
*x = ProtoControllerRumble{} *x = ProtoControllerRumble{}
mi := &file_types_proto_msgTypes[13] mi := &file_types_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -784,7 +546,7 @@ func (x *ProtoControllerRumble) String() string {
func (*ProtoControllerRumble) ProtoMessage() {} func (*ProtoControllerRumble) ProtoMessage() {}
func (x *ProtoControllerRumble) ProtoReflect() protoreflect.Message { func (x *ProtoControllerRumble) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[13] mi := &file_types_proto_msgTypes[9]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -797,7 +559,7 @@ func (x *ProtoControllerRumble) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoControllerRumble.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoControllerRumble.ProtoReflect.Descriptor instead.
func (*ProtoControllerRumble) Descriptor() ([]byte, []int) { func (*ProtoControllerRumble) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{13} return file_types_proto_rawDescGZIP(), []int{9}
} }
func (x *ProtoControllerRumble) GetSessionSlot() int32 { func (x *ProtoControllerRumble) GetSessionSlot() int32 {
@@ -835,6 +597,160 @@ func (x *ProtoControllerRumble) GetDuration() int32 {
return 0 return 0
} }
// ControllerStateBatch - single message containing full or partial controller state
type ProtoControllerStateBatch struct {
state protoimpl.MessageState `protogen:"open.v1"`
SessionSlot int32 `protobuf:"varint,1,opt,name=session_slot,json=sessionSlot,proto3" json:"session_slot,omitempty"` // Session specific slot number (0-3)
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Session ID of the client
UpdateType ProtoControllerStateBatch_UpdateType `protobuf:"varint,3,opt,name=update_type,json=updateType,proto3,enum=proto.ProtoControllerStateBatch_UpdateType" json:"update_type,omitempty"`
// Sequence number for packet loss detection
Sequence uint32 `protobuf:"varint,4,opt,name=sequence,proto3" json:"sequence,omitempty"`
// Button state map (Linux event codes)
ButtonChangedMask map[int32]bool `protobuf:"bytes,5,rep,name=button_changed_mask,json=buttonChangedMask,proto3" json:"button_changed_mask,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
// Analog inputs
LeftStickX *int32 `protobuf:"varint,6,opt,name=left_stick_x,json=leftStickX,proto3,oneof" json:"left_stick_x,omitempty"` // -32768 to 32767
LeftStickY *int32 `protobuf:"varint,7,opt,name=left_stick_y,json=leftStickY,proto3,oneof" json:"left_stick_y,omitempty"` // -32768 to 32767
RightStickX *int32 `protobuf:"varint,8,opt,name=right_stick_x,json=rightStickX,proto3,oneof" json:"right_stick_x,omitempty"` // -32768 to 32767
RightStickY *int32 `protobuf:"varint,9,opt,name=right_stick_y,json=rightStickY,proto3,oneof" json:"right_stick_y,omitempty"` // -32768 to 32767
LeftTrigger *int32 `protobuf:"varint,10,opt,name=left_trigger,json=leftTrigger,proto3,oneof" json:"left_trigger,omitempty"` // -32768 to 32767
RightTrigger *int32 `protobuf:"varint,11,opt,name=right_trigger,json=rightTrigger,proto3,oneof" json:"right_trigger,omitempty"` // -32768 to 32767
DpadX *int32 `protobuf:"varint,12,opt,name=dpad_x,json=dpadX,proto3,oneof" json:"dpad_x,omitempty"` // -1, 0, or 1
DpadY *int32 `protobuf:"varint,13,opt,name=dpad_y,json=dpadY,proto3,oneof" json:"dpad_y,omitempty"` // -1, 0, or 1
// Bitmask indicating which fields have changed
// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
ChangedFields *uint32 `protobuf:"varint,14,opt,name=changed_fields,json=changedFields,proto3,oneof" json:"changed_fields,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProtoControllerStateBatch) Reset() {
*x = ProtoControllerStateBatch{}
mi := &file_types_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ProtoControllerStateBatch) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProtoControllerStateBatch) ProtoMessage() {}
func (x *ProtoControllerStateBatch) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProtoControllerStateBatch.ProtoReflect.Descriptor instead.
func (*ProtoControllerStateBatch) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{10}
}
func (x *ProtoControllerStateBatch) GetSessionSlot() int32 {
if x != nil {
return x.SessionSlot
}
return 0
}
func (x *ProtoControllerStateBatch) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
func (x *ProtoControllerStateBatch) GetUpdateType() ProtoControllerStateBatch_UpdateType {
if x != nil {
return x.UpdateType
}
return ProtoControllerStateBatch_FULL_STATE
}
func (x *ProtoControllerStateBatch) GetSequence() uint32 {
if x != nil {
return x.Sequence
}
return 0
}
func (x *ProtoControllerStateBatch) GetButtonChangedMask() map[int32]bool {
if x != nil {
return x.ButtonChangedMask
}
return nil
}
func (x *ProtoControllerStateBatch) GetLeftStickX() int32 {
if x != nil && x.LeftStickX != nil {
return *x.LeftStickX
}
return 0
}
func (x *ProtoControllerStateBatch) GetLeftStickY() int32 {
if x != nil && x.LeftStickY != nil {
return *x.LeftStickY
}
return 0
}
func (x *ProtoControllerStateBatch) GetRightStickX() int32 {
if x != nil && x.RightStickX != nil {
return *x.RightStickX
}
return 0
}
func (x *ProtoControllerStateBatch) GetRightStickY() int32 {
if x != nil && x.RightStickY != nil {
return *x.RightStickY
}
return 0
}
func (x *ProtoControllerStateBatch) GetLeftTrigger() int32 {
if x != nil && x.LeftTrigger != nil {
return *x.LeftTrigger
}
return 0
}
func (x *ProtoControllerStateBatch) GetRightTrigger() int32 {
if x != nil && x.RightTrigger != nil {
return *x.RightTrigger
}
return 0
}
func (x *ProtoControllerStateBatch) GetDpadX() int32 {
if x != nil && x.DpadX != nil {
return *x.DpadX
}
return 0
}
func (x *ProtoControllerStateBatch) GetDpadY() int32 {
if x != nil && x.DpadY != nil {
return *x.DpadY
}
return 0
}
func (x *ProtoControllerStateBatch) GetChangedFields() uint32 {
if x != nil && x.ChangedFields != nil {
return *x.ChangedFields
}
return 0
}
type RTCIceCandidateInit struct { type RTCIceCandidateInit struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Candidate string `protobuf:"bytes,1,opt,name=candidate,proto3" json:"candidate,omitempty"` Candidate string `protobuf:"bytes,1,opt,name=candidate,proto3" json:"candidate,omitempty"`
@@ -847,7 +763,7 @@ type RTCIceCandidateInit struct {
func (x *RTCIceCandidateInit) Reset() { func (x *RTCIceCandidateInit) Reset() {
*x = RTCIceCandidateInit{} *x = RTCIceCandidateInit{}
mi := &file_types_proto_msgTypes[14] mi := &file_types_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -859,7 +775,7 @@ func (x *RTCIceCandidateInit) String() string {
func (*RTCIceCandidateInit) ProtoMessage() {} func (*RTCIceCandidateInit) ProtoMessage() {}
func (x *RTCIceCandidateInit) ProtoReflect() protoreflect.Message { func (x *RTCIceCandidateInit) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[14] mi := &file_types_proto_msgTypes[11]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -872,7 +788,7 @@ func (x *RTCIceCandidateInit) ProtoReflect() protoreflect.Message {
// Deprecated: Use RTCIceCandidateInit.ProtoReflect.Descriptor instead. // Deprecated: Use RTCIceCandidateInit.ProtoReflect.Descriptor instead.
func (*RTCIceCandidateInit) Descriptor() ([]byte, []int) { func (*RTCIceCandidateInit) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{14} return file_types_proto_rawDescGZIP(), []int{11}
} }
func (x *RTCIceCandidateInit) GetCandidate() string { func (x *RTCIceCandidateInit) GetCandidate() string {
@@ -913,7 +829,7 @@ type RTCSessionDescriptionInit struct {
func (x *RTCSessionDescriptionInit) Reset() { func (x *RTCSessionDescriptionInit) Reset() {
*x = RTCSessionDescriptionInit{} *x = RTCSessionDescriptionInit{}
mi := &file_types_proto_msgTypes[15] mi := &file_types_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -925,7 +841,7 @@ func (x *RTCSessionDescriptionInit) String() string {
func (*RTCSessionDescriptionInit) ProtoMessage() {} func (*RTCSessionDescriptionInit) ProtoMessage() {}
func (x *RTCSessionDescriptionInit) ProtoReflect() protoreflect.Message { func (x *RTCSessionDescriptionInit) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[15] mi := &file_types_proto_msgTypes[12]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -938,7 +854,7 @@ func (x *RTCSessionDescriptionInit) ProtoReflect() protoreflect.Message {
// Deprecated: Use RTCSessionDescriptionInit.ProtoReflect.Descriptor instead. // Deprecated: Use RTCSessionDescriptionInit.ProtoReflect.Descriptor instead.
func (*RTCSessionDescriptionInit) Descriptor() ([]byte, []int) { func (*RTCSessionDescriptionInit) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{15} return file_types_proto_rawDescGZIP(), []int{12}
} }
func (x *RTCSessionDescriptionInit) GetSdp() string { func (x *RTCSessionDescriptionInit) GetSdp() string {
@@ -965,7 +881,7 @@ type ProtoICE struct {
func (x *ProtoICE) Reset() { func (x *ProtoICE) Reset() {
*x = ProtoICE{} *x = ProtoICE{}
mi := &file_types_proto_msgTypes[16] mi := &file_types_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -977,7 +893,7 @@ func (x *ProtoICE) String() string {
func (*ProtoICE) ProtoMessage() {} func (*ProtoICE) ProtoMessage() {}
func (x *ProtoICE) ProtoReflect() protoreflect.Message { func (x *ProtoICE) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[16] mi := &file_types_proto_msgTypes[13]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -990,7 +906,7 @@ func (x *ProtoICE) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoICE.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoICE.ProtoReflect.Descriptor instead.
func (*ProtoICE) Descriptor() ([]byte, []int) { func (*ProtoICE) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{16} return file_types_proto_rawDescGZIP(), []int{13}
} }
func (x *ProtoICE) GetCandidate() *RTCIceCandidateInit { func (x *ProtoICE) GetCandidate() *RTCIceCandidateInit {
@@ -1010,7 +926,7 @@ type ProtoSDP struct {
func (x *ProtoSDP) Reset() { func (x *ProtoSDP) Reset() {
*x = ProtoSDP{} *x = ProtoSDP{}
mi := &file_types_proto_msgTypes[17] mi := &file_types_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1022,7 +938,7 @@ func (x *ProtoSDP) String() string {
func (*ProtoSDP) ProtoMessage() {} func (*ProtoSDP) ProtoMessage() {}
func (x *ProtoSDP) ProtoReflect() protoreflect.Message { func (x *ProtoSDP) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[17] mi := &file_types_proto_msgTypes[14]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1035,7 +951,7 @@ func (x *ProtoSDP) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoSDP.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoSDP.ProtoReflect.Descriptor instead.
func (*ProtoSDP) Descriptor() ([]byte, []int) { func (*ProtoSDP) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{17} return file_types_proto_rawDescGZIP(), []int{14}
} }
func (x *ProtoSDP) GetSdp() *RTCSessionDescriptionInit { func (x *ProtoSDP) GetSdp() *RTCSessionDescriptionInit {
@@ -1055,7 +971,7 @@ type ProtoRaw struct {
func (x *ProtoRaw) Reset() { func (x *ProtoRaw) Reset() {
*x = ProtoRaw{} *x = ProtoRaw{}
mi := &file_types_proto_msgTypes[18] mi := &file_types_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1067,7 +983,7 @@ func (x *ProtoRaw) String() string {
func (*ProtoRaw) ProtoMessage() {} func (*ProtoRaw) ProtoMessage() {}
func (x *ProtoRaw) ProtoReflect() protoreflect.Message { func (x *ProtoRaw) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[18] mi := &file_types_proto_msgTypes[15]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1080,7 +996,7 @@ func (x *ProtoRaw) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoRaw.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoRaw.ProtoReflect.Descriptor instead.
func (*ProtoRaw) Descriptor() ([]byte, []int) { func (*ProtoRaw) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{18} return file_types_proto_rawDescGZIP(), []int{15}
} }
func (x *ProtoRaw) GetData() string { func (x *ProtoRaw) GetData() string {
@@ -1101,7 +1017,7 @@ type ProtoClientRequestRoomStream struct {
func (x *ProtoClientRequestRoomStream) Reset() { func (x *ProtoClientRequestRoomStream) Reset() {
*x = ProtoClientRequestRoomStream{} *x = ProtoClientRequestRoomStream{}
mi := &file_types_proto_msgTypes[19] mi := &file_types_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1113,7 +1029,7 @@ func (x *ProtoClientRequestRoomStream) String() string {
func (*ProtoClientRequestRoomStream) ProtoMessage() {} func (*ProtoClientRequestRoomStream) ProtoMessage() {}
func (x *ProtoClientRequestRoomStream) ProtoReflect() protoreflect.Message { func (x *ProtoClientRequestRoomStream) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[19] mi := &file_types_proto_msgTypes[16]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1126,7 +1042,7 @@ func (x *ProtoClientRequestRoomStream) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoClientRequestRoomStream.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoClientRequestRoomStream.ProtoReflect.Descriptor instead.
func (*ProtoClientRequestRoomStream) Descriptor() ([]byte, []int) { func (*ProtoClientRequestRoomStream) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{19} return file_types_proto_rawDescGZIP(), []int{16}
} }
func (x *ProtoClientRequestRoomStream) GetRoomName() string { func (x *ProtoClientRequestRoomStream) GetRoomName() string {
@@ -1154,7 +1070,7 @@ type ProtoClientDisconnected struct {
func (x *ProtoClientDisconnected) Reset() { func (x *ProtoClientDisconnected) Reset() {
*x = ProtoClientDisconnected{} *x = ProtoClientDisconnected{}
mi := &file_types_proto_msgTypes[20] mi := &file_types_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1166,7 +1082,7 @@ func (x *ProtoClientDisconnected) String() string {
func (*ProtoClientDisconnected) ProtoMessage() {} func (*ProtoClientDisconnected) ProtoMessage() {}
func (x *ProtoClientDisconnected) ProtoReflect() protoreflect.Message { func (x *ProtoClientDisconnected) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[20] mi := &file_types_proto_msgTypes[17]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1179,7 +1095,7 @@ func (x *ProtoClientDisconnected) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoClientDisconnected.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoClientDisconnected.ProtoReflect.Descriptor instead.
func (*ProtoClientDisconnected) Descriptor() ([]byte, []int) { func (*ProtoClientDisconnected) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{20} return file_types_proto_rawDescGZIP(), []int{17}
} }
func (x *ProtoClientDisconnected) GetSessionId() string { func (x *ProtoClientDisconnected) GetSessionId() string {
@@ -1206,7 +1122,7 @@ type ProtoServerPushStream struct {
func (x *ProtoServerPushStream) Reset() { func (x *ProtoServerPushStream) Reset() {
*x = ProtoServerPushStream{} *x = ProtoServerPushStream{}
mi := &file_types_proto_msgTypes[21] mi := &file_types_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -1218,7 +1134,7 @@ func (x *ProtoServerPushStream) String() string {
func (*ProtoServerPushStream) ProtoMessage() {} func (*ProtoServerPushStream) ProtoMessage() {}
func (x *ProtoServerPushStream) ProtoReflect() protoreflect.Message { func (x *ProtoServerPushStream) ProtoReflect() protoreflect.Message {
mi := &file_types_proto_msgTypes[21] mi := &file_types_proto_msgTypes[18]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -1231,7 +1147,7 @@ func (x *ProtoServerPushStream) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtoServerPushStream.ProtoReflect.Descriptor instead. // Deprecated: Use ProtoServerPushStream.ProtoReflect.Descriptor instead.
func (*ProtoServerPushStream) Descriptor() ([]byte, []int) { func (*ProtoServerPushStream) Descriptor() ([]byte, []int) {
return file_types_proto_rawDescGZIP(), []int{21} return file_types_proto_rawDescGZIP(), []int{18}
} }
func (x *ProtoServerPushStream) GetRoomName() string { func (x *ProtoServerPushStream) GetRoomName() string {
@@ -1272,39 +1188,51 @@ const file_types_proto_rawDesc = "" +
"\x15ProtoControllerDetach\x12!\n" + "\x15ProtoControllerDetach\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" + "\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" + "\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\"\x8b\x01\n" + "session_id\x18\x02 \x01(\tR\tsessionId\"\xc1\x01\n" +
"\x15ProtoControllerButton\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x16\n" +
"\x06button\x18\x03 \x01(\x05R\x06button\x12\x18\n" +
"\apressed\x18\x04 \x01(\bR\apressed\"\x8a\x01\n" +
"\x16ProtoControllerTrigger\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x18\n" +
"\atrigger\x18\x03 \x01(\x05R\atrigger\x12\x14\n" +
"\x05value\x18\x04 \x01(\x05R\x05value\"\x8a\x01\n" +
"\x14ProtoControllerStick\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x14\n" +
"\x05stick\x18\x03 \x01(\x05R\x05stick\x12\f\n" +
"\x01x\x18\x04 \x01(\x05R\x01x\x12\f\n" +
"\x01y\x18\x05 \x01(\x05R\x01y\"\x81\x01\n" +
"\x13ProtoControllerAxis\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12\x12\n" +
"\x04axis\x18\x03 \x01(\x05R\x04axis\x12\x14\n" +
"\x05value\x18\x04 \x01(\x05R\x05value\"\xc1\x01\n" +
"\x15ProtoControllerRumble\x12!\n" + "\x15ProtoControllerRumble\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" + "\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" + "\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12#\n" + "session_id\x18\x02 \x01(\tR\tsessionId\x12#\n" +
"\rlow_frequency\x18\x03 \x01(\x05R\flowFrequency\x12%\n" + "\rlow_frequency\x18\x03 \x01(\x05R\flowFrequency\x12%\n" +
"\x0ehigh_frequency\x18\x04 \x01(\x05R\rhighFrequency\x12\x1a\n" + "\x0ehigh_frequency\x18\x04 \x01(\x05R\rhighFrequency\x12\x1a\n" +
"\bduration\x18\x05 \x01(\x05R\bduration\"\xde\x01\n" + "\bduration\x18\x05 \x01(\x05R\bduration\"\x87\a\n" +
"\x19ProtoControllerStateBatch\x12!\n" +
"\fsession_slot\x18\x01 \x01(\x05R\vsessionSlot\x12\x1d\n" +
"\n" +
"session_id\x18\x02 \x01(\tR\tsessionId\x12L\n" +
"\vupdate_type\x18\x03 \x01(\x0e2+.proto.ProtoControllerStateBatch.UpdateTypeR\n" +
"updateType\x12\x1a\n" +
"\bsequence\x18\x04 \x01(\rR\bsequence\x12g\n" +
"\x13button_changed_mask\x18\x05 \x03(\v27.proto.ProtoControllerStateBatch.ButtonChangedMaskEntryR\x11buttonChangedMask\x12%\n" +
"\fleft_stick_x\x18\x06 \x01(\x05H\x00R\n" +
"leftStickX\x88\x01\x01\x12%\n" +
"\fleft_stick_y\x18\a \x01(\x05H\x01R\n" +
"leftStickY\x88\x01\x01\x12'\n" +
"\rright_stick_x\x18\b \x01(\x05H\x02R\vrightStickX\x88\x01\x01\x12'\n" +
"\rright_stick_y\x18\t \x01(\x05H\x03R\vrightStickY\x88\x01\x01\x12&\n" +
"\fleft_trigger\x18\n" +
" \x01(\x05H\x04R\vleftTrigger\x88\x01\x01\x12(\n" +
"\rright_trigger\x18\v \x01(\x05H\x05R\frightTrigger\x88\x01\x01\x12\x1a\n" +
"\x06dpad_x\x18\f \x01(\x05H\x06R\x05dpadX\x88\x01\x01\x12\x1a\n" +
"\x06dpad_y\x18\r \x01(\x05H\aR\x05dpadY\x88\x01\x01\x12*\n" +
"\x0echanged_fields\x18\x0e \x01(\rH\bR\rchangedFields\x88\x01\x01\x1aD\n" +
"\x16ButtonChangedMaskEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\x05R\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\bR\x05value:\x028\x01\"'\n" +
"\n" +
"UpdateType\x12\x0e\n" +
"\n" +
"FULL_STATE\x10\x00\x12\t\n" +
"\x05DELTA\x10\x01B\x0f\n" +
"\r_left_stick_xB\x0f\n" +
"\r_left_stick_yB\x10\n" +
"\x0e_right_stick_xB\x10\n" +
"\x0e_right_stick_yB\x0f\n" +
"\r_left_triggerB\x10\n" +
"\x0e_right_triggerB\t\n" +
"\a_dpad_xB\t\n" +
"\a_dpad_yB\x11\n" +
"\x0f_changed_fields\"\xde\x01\n" +
"\x13RTCIceCandidateInit\x12\x1c\n" + "\x13RTCIceCandidateInit\x12\x1c\n" +
"\tcandidate\x18\x01 \x01(\tR\tcandidate\x12)\n" + "\tcandidate\x18\x01 \x01(\tR\tcandidate\x12)\n" +
"\rsdpMLineIndex\x18\x02 \x01(\rH\x00R\rsdpMLineIndex\x88\x01\x01\x12\x1b\n" + "\rsdpMLineIndex\x18\x02 \x01(\rH\x00R\rsdpMLineIndex\x88\x01\x01\x12\x1b\n" +
@@ -1345,39 +1273,41 @@ func file_types_proto_rawDescGZIP() []byte {
return file_types_proto_rawDescData return file_types_proto_rawDescData
} }
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_types_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_types_proto_goTypes = []any{ var file_types_proto_goTypes = []any{
(*ProtoMouseMove)(nil), // 0: proto.ProtoMouseMove (ProtoControllerStateBatch_UpdateType)(0), // 0: proto.ProtoControllerStateBatch.UpdateType
(*ProtoMouseMoveAbs)(nil), // 1: proto.ProtoMouseMoveAbs (*ProtoMouseMove)(nil), // 1: proto.ProtoMouseMove
(*ProtoMouseWheel)(nil), // 2: proto.ProtoMouseWheel (*ProtoMouseMoveAbs)(nil), // 2: proto.ProtoMouseMoveAbs
(*ProtoMouseKeyDown)(nil), // 3: proto.ProtoMouseKeyDown (*ProtoMouseWheel)(nil), // 3: proto.ProtoMouseWheel
(*ProtoMouseKeyUp)(nil), // 4: proto.ProtoMouseKeyUp (*ProtoMouseKeyDown)(nil), // 4: proto.ProtoMouseKeyDown
(*ProtoKeyDown)(nil), // 5: proto.ProtoKeyDown (*ProtoMouseKeyUp)(nil), // 5: proto.ProtoMouseKeyUp
(*ProtoKeyUp)(nil), // 6: proto.ProtoKeyUp (*ProtoKeyDown)(nil), // 6: proto.ProtoKeyDown
(*ProtoControllerAttach)(nil), // 7: proto.ProtoControllerAttach (*ProtoKeyUp)(nil), // 7: proto.ProtoKeyUp
(*ProtoControllerDetach)(nil), // 8: proto.ProtoControllerDetach (*ProtoControllerAttach)(nil), // 8: proto.ProtoControllerAttach
(*ProtoControllerButton)(nil), // 9: proto.ProtoControllerButton (*ProtoControllerDetach)(nil), // 9: proto.ProtoControllerDetach
(*ProtoControllerTrigger)(nil), // 10: proto.ProtoControllerTrigger (*ProtoControllerRumble)(nil), // 10: proto.ProtoControllerRumble
(*ProtoControllerStick)(nil), // 11: proto.ProtoControllerStick (*ProtoControllerStateBatch)(nil), // 11: proto.ProtoControllerStateBatch
(*ProtoControllerAxis)(nil), // 12: proto.ProtoControllerAxis (*RTCIceCandidateInit)(nil), // 12: proto.RTCIceCandidateInit
(*ProtoControllerRumble)(nil), // 13: proto.ProtoControllerRumble (*RTCSessionDescriptionInit)(nil), // 13: proto.RTCSessionDescriptionInit
(*RTCIceCandidateInit)(nil), // 14: proto.RTCIceCandidateInit (*ProtoICE)(nil), // 14: proto.ProtoICE
(*RTCSessionDescriptionInit)(nil), // 15: proto.RTCSessionDescriptionInit (*ProtoSDP)(nil), // 15: proto.ProtoSDP
(*ProtoICE)(nil), // 16: proto.ProtoICE (*ProtoRaw)(nil), // 16: proto.ProtoRaw
(*ProtoSDP)(nil), // 17: proto.ProtoSDP (*ProtoClientRequestRoomStream)(nil), // 17: proto.ProtoClientRequestRoomStream
(*ProtoRaw)(nil), // 18: proto.ProtoRaw (*ProtoClientDisconnected)(nil), // 18: proto.ProtoClientDisconnected
(*ProtoClientRequestRoomStream)(nil), // 19: proto.ProtoClientRequestRoomStream (*ProtoServerPushStream)(nil), // 19: proto.ProtoServerPushStream
(*ProtoClientDisconnected)(nil), // 20: proto.ProtoClientDisconnected nil, // 20: proto.ProtoControllerStateBatch.ButtonChangedMaskEntry
(*ProtoServerPushStream)(nil), // 21: proto.ProtoServerPushStream
} }
var file_types_proto_depIdxs = []int32{ var file_types_proto_depIdxs = []int32{
14, // 0: proto.ProtoICE.candidate:type_name -> proto.RTCIceCandidateInit 0, // 0: proto.ProtoControllerStateBatch.update_type:type_name -> proto.ProtoControllerStateBatch.UpdateType
15, // 1: proto.ProtoSDP.sdp:type_name -> proto.RTCSessionDescriptionInit 20, // 1: proto.ProtoControllerStateBatch.button_changed_mask:type_name -> proto.ProtoControllerStateBatch.ButtonChangedMaskEntry
2, // [2:2] is the sub-list for method output_type 12, // 2: proto.ProtoICE.candidate:type_name -> proto.RTCIceCandidateInit
2, // [2:2] is the sub-list for method input_type 13, // 3: proto.ProtoSDP.sdp:type_name -> proto.RTCSessionDescriptionInit
2, // [2:2] is the sub-list for extension type_name 4, // [4:4] is the sub-list for method output_type
2, // [2:2] is the sub-list for extension extendee 4, // [4:4] is the sub-list for method input_type
0, // [0:2] is the sub-list for field type_name 4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
} }
func init() { file_types_proto_init() } func init() { file_types_proto_init() }
@@ -1385,19 +1315,21 @@ func file_types_proto_init() {
if File_types_proto != nil { if File_types_proto != nil {
return return
} }
file_types_proto_msgTypes[14].OneofWrappers = []any{} file_types_proto_msgTypes[10].OneofWrappers = []any{}
file_types_proto_msgTypes[11].OneofWrappers = []any{}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)),
NumEnums: 0, NumEnums: 1,
NumMessages: 22, NumMessages: 20,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },
GoTypes: file_types_proto_goTypes, GoTypes: file_types_proto_goTypes,
DependencyIndexes: file_types_proto_depIdxs, DependencyIndexes: file_types_proto_depIdxs,
EnumInfos: file_types_proto_enumTypes,
MessageInfos: file_types_proto_msgTypes, MessageInfos: file_types_proto_msgTypes,
}.Build() }.Build()
File_types_proto = out.File File_types_proto = out.File

View File

@@ -5079,9 +5079,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "vimputti" name = "vimputti"
version = "0.1.4" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb370ee43e3ee4ca5329886e64dc5b27c83dc8cced5a63c2418777dac9a41a8" checksum = "6440b3684270f355fb89193bfb0de957686119626b8b207f21d91024a892d05c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"libc", "libc",

View File

@@ -22,7 +22,7 @@ rand = "0.9"
rustls = { version = "0.23", features = ["ring"] } rustls = { version = "0.23", features = ["ring"] }
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }
vimputti = "0.1.4" vimputti = "0.1.7"
chrono = "0.4" chrono = "0.4"
prost = "0.14" prost = "0.14"
prost-types = "0.14" prost-types = "0.14"

View File

@@ -29,10 +29,8 @@ impl ControllerInput {
client: &vimputti::client::VimputtiClient, client: &vimputti::client::VimputtiClient,
) -> Result<Self> { ) -> Result<Self> {
let config = controller_string_to_type(&controller_type)?; let config = controller_string_to_type(&controller_type)?;
Ok(Self { let device = client.create_device(config.clone()).await?;
config: config.clone(), Ok(Self { config, device })
device: client.create_device(config).await?,
})
} }
pub fn device_mut(&mut self) -> &mut vimputti::client::VirtualController { pub fn device_mut(&mut self) -> &mut vimputti::client::VirtualController {
@@ -121,9 +119,60 @@ async fn command_loop(
slot.session_id == session_id && slot.session_slot == session_slot as u32 slot.session_id == session_id && slot.session_slot == session_slot as u32
}) })
.map(|(slot_num, _)| *slot_num); .map(|(slot_num, _)| *slot_num);
let slot = existing_slot.or_else(|| get_free_slot(&controllers));
if let Some(slot) = slot { if let Some(existing_slot) = existing_slot {
if let Some(controller_slot) = controllers.get_mut(&existing_slot) {
let rumble_tx = rumble_tx.clone();
let attach_tx = attach_tx.clone();
controller_slot
.controller
.device_mut()
.on_rumble(move |strong, weak, duration_ms| {
let _ = rumble_tx.try_send((
existing_slot,
strong,
weak,
duration_ms,
data.session_id.clone(),
));
})
.await
.map_err(|e| {
tracing::warn!(
"Failed to register rumble callback for slot {}: {}",
existing_slot,
e
);
})
.ok();
// Return to attach_tx what slot was assigned
let attach_info = ProtoControllerAttach {
id: data.id.clone(),
session_slot: existing_slot as i32,
session_id: session_id.clone(),
};
match attach_tx.send(attach_info).await {
Ok(_) => {
tracing::info!(
"Controller {} re-attached to slot {} (session: {})",
data.id,
existing_slot,
session_id
);
}
Err(e) => {
tracing::error!(
"Failed to send re-attach info for slot {}: {}",
existing_slot,
e
);
}
}
}
} else if let Some(slot) = get_free_slot(&controllers) {
if let Ok(mut controller) = if let Ok(mut controller) =
ControllerInput::new(data.id.clone(), &vimputti_client).await ControllerInput::new(data.id.clone(), &vimputti_client).await
{ {
@@ -133,7 +182,13 @@ async fn command_loop(
controller controller
.device_mut() .device_mut()
.on_rumble(move |strong, weak, duration_ms| { .on_rumble(move |strong, weak, duration_ms| {
let _ = rumble_tx.try_send((slot, strong, weak, duration_ms, data.session_id.clone())); let _ = rumble_tx.try_send((
slot,
strong,
weak,
duration_ms,
data.session_id.clone(),
));
}) })
.await .await
.map_err(|e| { .map_err(|e| {
@@ -190,65 +245,10 @@ async fn command_loop(
if controllers.remove(&(data.session_slot as u32)).is_some() { if controllers.remove(&(data.session_slot as u32)).is_some() {
tracing::info!("Controller detached from slot {}", data.session_slot); tracing::info!("Controller detached from slot {}", data.session_slot);
} else { } else {
tracing::warn!("No controller found in slot {} to detach", data.session_slot); tracing::warn!(
} "No controller found in slot {} to detach",
} data.session_slot
Payload::ControllerButton(data) => { );
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
if let Some(button) = vimputti::Button::from_ev_code(data.button as u16) {
let device = controller.controller.device();
device.button(button, data.pressed);
device.sync();
}
} else {
tracing::warn!("Controller slot {} not found for button event", data.session_slot);
}
}
Payload::ControllerStick(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
if data.stick == 0 {
// Left stick
device.axis(vimputti::Axis::LeftStickX, data.x);
device.sync();
device.axis(vimputti::Axis::LeftStickY, data.y);
} else if data.stick == 1 {
// Right stick
device.axis(vimputti::Axis::RightStickX, data.x);
device.sync();
device.axis(vimputti::Axis::RightStickY, data.y);
}
device.sync();
} else {
tracing::warn!("Controller slot {} not found for stick event", data.session_slot);
}
}
Payload::ControllerTrigger(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
if data.trigger == 0 {
// Left trigger
device.axis(vimputti::Axis::LowerLeftTrigger, data.value);
} else if data.trigger == 1 {
// Right trigger
device.axis(vimputti::Axis::LowerRightTrigger, data.value);
}
device.sync();
} else {
tracing::warn!("Controller slot {} not found for trigger event", data.session_slot);
}
}
Payload::ControllerAxis(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
if data.axis == 0 {
// dpad x
device.axis(vimputti::Axis::DPadX, data.value);
} else if data.axis == 1 {
// dpad y
device.axis(vimputti::Axis::DPadY, data.value);
}
device.sync();
} }
} }
Payload::ClientDisconnected(data) => { Payload::ClientDisconnected(data) => {
@@ -274,6 +274,125 @@ async fn command_loop(
} }
} }
} }
Payload::ControllerStateBatch(data) => {
if let Some(controller) = controllers.get(&(data.session_slot as u32)) {
let device = controller.controller.device();
// Handle inputs based on update type
if data.update_type == 0 {
// FULL_STATE: Update all values
let _ = device.sync().await;
for (btn_code, pressed) in data.button_changed_mask {
if let Some(button) = vimputti::Button::from_ev_code(btn_code as u16) {
let _ = device.button(button, pressed).await;
let _ = device.sync().await;
}
}
if let Some(x) = data.left_stick_x {
let _ = device.axis(vimputti::Axis::LeftStickX, x).await;
let _ = device.sync().await;
}
if let Some(y) = data.left_stick_y {
let _ = device.axis(vimputti::Axis::LeftStickY, y).await;
let _ = device.sync().await;
}
if let Some(x) = data.right_stick_x {
let _ = device.axis(vimputti::Axis::RightStickX, x).await;
let _ = device.sync().await;
}
if let Some(y) = data.right_stick_y {
let _ = device.axis(vimputti::Axis::RightStickY, y).await;
let _ = device.sync().await;
}
if let Some(value) = data.left_trigger {
let _ = device.axis(vimputti::Axis::LowerLeftTrigger, value).await;
let _ = device.sync().await;
}
if let Some(value) = data.right_trigger {
let _ = device.axis(vimputti::Axis::LowerRightTrigger, value).await;
let _ = device.sync().await;
}
if let Some(x) = data.dpad_x {
let _ = device.axis(vimputti::Axis::DPadX, x).await;
let _ = device.sync().await;
}
if let Some(y) = data.dpad_y {
let _ = device.axis(vimputti::Axis::DPadY, y).await;
let _ = device.sync().await;
}
} else {
// DELTA: Only update changed values
if let Some(changed_fields) = data.changed_fields {
let _ = device.sync().await;
if (changed_fields & (1 << 0)) != 0 {
for (btn_code, pressed) in data.button_changed_mask {
if let Some(button) =
vimputti::Button::from_ev_code(btn_code as u16)
{
let _ = device.button(button, pressed).await;
let _ = device.sync().await;
}
}
}
if (changed_fields & (1 << 1)) != 0 {
if let Some(x) = data.left_stick_x {
let _ = device.axis(vimputti::Axis::LeftStickX, x).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 2)) != 0 {
if let Some(y) = data.left_stick_y {
let _ = device.axis(vimputti::Axis::LeftStickY, y).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 3)) != 0 {
if let Some(x) = data.right_stick_x {
let _ = device.axis(vimputti::Axis::RightStickX, x).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 4)) != 0 {
if let Some(y) = data.right_stick_y {
let _ = device.axis(vimputti::Axis::RightStickY, y).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 5)) != 0 {
if let Some(value) = data.left_trigger {
let _ =
device.axis(vimputti::Axis::LowerLeftTrigger, value).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 6)) != 0 {
if let Some(value) = data.right_trigger {
let _ =
device.axis(vimputti::Axis::LowerRightTrigger, value).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 7)) != 0 {
if let Some(x) = data.dpad_x {
let _ = device.axis(vimputti::Axis::DPadX, x).await;
let _ = device.sync().await;
}
}
if (changed_fields & (1 << 8)) != 0 {
if let Some(y) = data.dpad_y {
let _ = device.axis(vimputti::Axis::DPadY, y).await;
let _ = device.sync().await;
}
}
}
}
} else {
tracing::warn!(
"Controller slot {} not found for state batch event",
data.session_slot
);
}
}
_ => { _ => {
//no-op //no-op
} }

View File

@@ -102,77 +102,6 @@ pub struct ProtoControllerDetach {
#[prost(string, tag="2")] #[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String, pub session_id: ::prost::alloc::string::String,
} }
/// ControllerButton message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerButton {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Button code (linux input event code)
#[prost(int32, tag="3")]
pub button: i32,
/// true if pressed, false if released
#[prost(bool, tag="4")]
pub pressed: bool,
}
/// ControllerTriggers message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerTrigger {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Trigger number (0 for left, 1 for right)
#[prost(int32, tag="3")]
pub trigger: i32,
/// trigger value (-32768 to 32767)
#[prost(int32, tag="4")]
pub value: i32,
}
/// ControllerSticks message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerStick {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Stick number (0 for left, 1 for right)
#[prost(int32, tag="3")]
pub stick: i32,
/// X axis value (-32768 to 32767)
#[prost(int32, tag="4")]
pub x: i32,
/// Y axis value (-32768 to 32767)
#[prost(int32, tag="5")]
pub y: i32,
}
/// ControllerAxis message
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerAxis {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
/// Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
#[prost(int32, tag="3")]
pub axis: i32,
/// axis value (-1 to 1)
#[prost(int32, tag="4")]
pub value: i32,
}
/// ControllerRumble message /// ControllerRumble message
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
@@ -193,6 +122,86 @@ pub struct ProtoControllerRumble {
#[prost(int32, tag="5")] #[prost(int32, tag="5")]
pub duration: i32, pub duration: i32,
} }
/// ControllerStateBatch - single message containing full or partial controller state
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ProtoControllerStateBatch {
/// Session specific slot number (0-3)
#[prost(int32, tag="1")]
pub session_slot: i32,
/// Session ID of the client
#[prost(string, tag="2")]
pub session_id: ::prost::alloc::string::String,
#[prost(enumeration="proto_controller_state_batch::UpdateType", tag="3")]
pub update_type: i32,
/// Sequence number for packet loss detection
#[prost(uint32, tag="4")]
pub sequence: u32,
/// Button state map (Linux event codes)
#[prost(map="int32, bool", tag="5")]
pub button_changed_mask: ::std::collections::HashMap<i32, bool>,
/// Analog inputs
///
/// -32768 to 32767
#[prost(int32, optional, tag="6")]
pub left_stick_x: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="7")]
pub left_stick_y: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="8")]
pub right_stick_x: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="9")]
pub right_stick_y: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="10")]
pub left_trigger: ::core::option::Option<i32>,
/// -32768 to 32767
#[prost(int32, optional, tag="11")]
pub right_trigger: ::core::option::Option<i32>,
/// -1, 0, or 1
#[prost(int32, optional, tag="12")]
pub dpad_x: ::core::option::Option<i32>,
/// -1, 0, or 1
#[prost(int32, optional, tag="13")]
pub dpad_y: ::core::option::Option<i32>,
/// Bitmask indicating which fields have changed
/// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
#[prost(uint32, optional, tag="14")]
pub changed_fields: ::core::option::Option<u32>,
}
/// Nested message and enum types in `ProtoControllerStateBatch`.
pub mod proto_controller_state_batch {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum UpdateType {
/// Complete controller state
FullState = 0,
/// Only changed fields
Delta = 1,
}
impl UpdateType {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
UpdateType::FullState => "FULL_STATE",
UpdateType::Delta => "DELTA",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"FULL_STATE" => Some(Self::FullState),
"DELTA" => Some(Self::Delta),
_ => None,
}
}
}
}
// WebRTC + signaling // WebRTC + signaling
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
@@ -274,7 +283,7 @@ pub struct ProtoMessageBase {
pub struct ProtoMessage { pub struct ProtoMessage {
#[prost(message, optional, tag="1")] #[prost(message, optional, tag="1")]
pub message_base: ::core::option::Option<ProtoMessageBase>, pub message_base: ::core::option::Option<ProtoMessageBase>,
#[prost(oneof="proto_message::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 25")] #[prost(oneof="proto_message::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22, 23, 24, 25")]
pub payload: ::core::option::Option<proto_message::Payload>, pub payload: ::core::option::Option<proto_message::Payload>,
} }
/// Nested message and enum types in `ProtoMessage`. /// Nested message and enum types in `ProtoMessage`.
@@ -297,20 +306,15 @@ pub mod proto_message {
KeyDown(super::ProtoKeyDown), KeyDown(super::ProtoKeyDown),
#[prost(message, tag="8")] #[prost(message, tag="8")]
KeyUp(super::ProtoKeyUp), KeyUp(super::ProtoKeyUp),
/// Controller input types
#[prost(message, tag="9")] #[prost(message, tag="9")]
ControllerAttach(super::ProtoControllerAttach), ControllerAttach(super::ProtoControllerAttach),
#[prost(message, tag="10")] #[prost(message, tag="10")]
ControllerDetach(super::ProtoControllerDetach), ControllerDetach(super::ProtoControllerDetach),
#[prost(message, tag="11")] #[prost(message, tag="11")]
ControllerButton(super::ProtoControllerButton),
#[prost(message, tag="12")]
ControllerTrigger(super::ProtoControllerTrigger),
#[prost(message, tag="13")]
ControllerStick(super::ProtoControllerStick),
#[prost(message, tag="14")]
ControllerAxis(super::ProtoControllerAxis),
#[prost(message, tag="15")]
ControllerRumble(super::ProtoControllerRumble), ControllerRumble(super::ProtoControllerRumble),
#[prost(message, tag="12")]
ControllerStateBatch(super::ProtoControllerStateBatch),
/// Signaling types /// Signaling types
#[prost(message, tag="20")] #[prost(message, tag="20")]
Ice(super::ProtoIce), Ice(super::ProtoIce),

View File

@@ -23,13 +23,12 @@ message ProtoMessage {
ProtoMouseKeyUp mouse_key_up = 6; ProtoMouseKeyUp mouse_key_up = 6;
ProtoKeyDown key_down = 7; ProtoKeyDown key_down = 7;
ProtoKeyUp key_up = 8; ProtoKeyUp key_up = 8;
// Controller input types
ProtoControllerAttach controller_attach = 9; ProtoControllerAttach controller_attach = 9;
ProtoControllerDetach controller_detach = 10; ProtoControllerDetach controller_detach = 10;
ProtoControllerButton controller_button = 11; ProtoControllerRumble controller_rumble = 11;
ProtoControllerTrigger controller_trigger = 12; ProtoControllerStateBatch controller_state_batch = 12;
ProtoControllerStick controller_stick = 13;
ProtoControllerAxis controller_axis = 14;
ProtoControllerRumble controller_rumble = 15;
// Signaling types // Signaling types
ProtoICE ice = 20; ProtoICE ice = 20;

View File

@@ -61,39 +61,6 @@ message ProtoControllerDetach {
string session_id = 2; // Session ID of the client string session_id = 2; // Session ID of the client
} }
// ControllerButton message
message ProtoControllerButton {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 button = 3; // Button code (linux input event code)
bool pressed = 4; // true if pressed, false if released
}
// ControllerTriggers message
message ProtoControllerTrigger {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 trigger = 3; // Trigger number (0 for left, 1 for right)
int32 value = 4; // trigger value (-32768 to 32767)
}
// ControllerSticks message
message ProtoControllerStick {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 stick = 3; // Stick number (0 for left, 1 for right)
int32 x = 4; // X axis value (-32768 to 32767)
int32 y = 5; // Y axis value (-32768 to 32767)
}
// ControllerAxis message
message ProtoControllerAxis {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
int32 axis = 3; // Axis number (0 for d-pad horizontal, 1 for d-pad vertical)
int32 value = 4; // axis value (-1 to 1)
}
// ControllerRumble message // ControllerRumble message
message ProtoControllerRumble { message ProtoControllerRumble {
int32 session_slot = 1; // Session specific slot number (0-3) int32 session_slot = 1; // Session specific slot number (0-3)
@@ -103,6 +70,38 @@ message ProtoControllerRumble {
int32 duration = 5; // Duration in milliseconds int32 duration = 5; // Duration in milliseconds
} }
// ControllerStateBatch - single message containing full or partial controller state
message ProtoControllerStateBatch {
int32 session_slot = 1; // Session specific slot number (0-3)
string session_id = 2; // Session ID of the client
enum UpdateType {
FULL_STATE = 0; // Complete controller state
DELTA = 1; // Only changed fields
}
UpdateType update_type = 3;
// Sequence number for packet loss detection
uint32 sequence = 4;
// Button state map (Linux event codes)
map<int32, bool> button_changed_mask = 5;
// Analog inputs
optional int32 left_stick_x = 6; // -32768 to 32767
optional int32 left_stick_y = 7; // -32768 to 32767
optional int32 right_stick_x = 8; // -32768 to 32767
optional int32 right_stick_y = 9; // -32768 to 32767
optional int32 left_trigger = 10; // -32768 to 32767
optional int32 right_trigger = 11; // -32768 to 32767
optional int32 dpad_x = 12; // -1, 0, or 1
optional int32 dpad_y = 13; // -1, 0, or 1
// Bitmask indicating which fields have changed
// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
optional uint32 changed_fields = 14;
}
/* WebRTC + signaling */ /* WebRTC + signaling */
message RTCIceCandidateInit { message RTCIceCandidateInit {