mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 15:00:27 +02:00
A hosted game gets an 8-character join code (Crockford base 32) besides its invite link, shown under the lobby's buttons. On the system link list, X opens the game's keyboard to type a code in; the code's topic and key come from a slow PBKDF2 derivation, the host answers an ask on that topic through the signalling brokers with its invite sealed with the key, and the joiner joins as with the link. Codes in join_link.txt work too. Also: the clipboard text last seen is kept from run to run, so a run's own invite is not joined again at the next start; in menus a held stick repeats after 350 ms and then every 90 ms, and its threshold is 70%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
440 lines
11 KiB
C
440 lines
11 KiB
C
/*
|
|
EVENT_MANAGER.C
|
|
|
|
symbols in this file:
|
|
000CB700 0030:
|
|
_event_manager_initialize (0000)
|
|
000CB730 0020:
|
|
_event_manager_dispose (0000)
|
|
000CB750 0020:
|
|
_event_manager_flush (0000)
|
|
000CB770 0010:
|
|
_event_manager_suppress (0000)
|
|
000CB780 00c0:
|
|
_get_next_event (0000)
|
|
000CB840 0010:
|
|
_event_manager_time_of_last_event (0000)
|
|
000CB850 0300:
|
|
_code_000cb850 (0000)
|
|
000CBB50 0110:
|
|
_event_manager_update (0000)
|
|
002706D8 0066:
|
|
??_C@_0GG@GKBBBOFI@event?5?$CG?$CG?5?$CI?$CIlocal_player_index?$DO?$DN0@ (0000)
|
|
00270740 0029:
|
|
??_C@_0CJ@HBEODFJG@c?3?2halo?2SOURCE?2interface?2event_m@ (0000)
|
|
00453B60 0168:
|
|
_event_manager_globals (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries.h"
|
|
#include "cseries_windows.h"
|
|
#include "event_manager.h"
|
|
#include "input.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
_event_type_null,
|
|
_event_type_left_stick,
|
|
_event_type_right_stick,
|
|
_event_type_button,
|
|
|
|
#ifdef HALO_ANDROID
|
|
/* (the VR port's: a headset's controllers' thumbsticks are pushed as
|
|
far less readily than a gamepad's) */
|
|
STICK_EVENT_THRESHOLD = 22937,
|
|
#else
|
|
STICK_EVENT_THRESHOLD = 29490,
|
|
#endif
|
|
STICK_EVENT_REPEAT_MILLISECONDS = 250
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
struct event_manager_state
|
|
{
|
|
boolean initialized;
|
|
boolean suppressed;
|
|
short __unknown2;
|
|
unsigned long time_of_last_event;
|
|
struct event_record events[MAXIMUM_GAMEPADS][8];
|
|
};
|
|
|
|
struct event_manager_globals
|
|
{
|
|
struct event_manager_state state;
|
|
unsigned long stick_event_times[NUMBER_OF_GAMEPAD_STICKS][MAXIMUM_GAMEPADS];
|
|
long previous_stick_axes[NUMBER_OF_GAMEPAD_STICKS][2][MAXIMUM_GAMEPADS];
|
|
};
|
|
|
|
typedef char verify_event_manager_state_size[
|
|
sizeof(struct event_manager_state) == 0x108 ? 1 : -1];
|
|
typedef char verify_event_manager_globals_size[
|
|
sizeof(struct event_manager_globals) == 0x168 ? 1 : -1];
|
|
|
|
#ifdef HALO_ANDROID
|
|
/* The VR port's: a stick held moves on once after a pause, then quickly,
|
|
as menus do now (the Xbox's moved on every quarter second, which in a
|
|
headset, with the keyboard's letters to cross, is slow going). */
|
|
enum
|
|
{
|
|
STICK_REPEAT_FIRST_MILLISECONDS = 350,
|
|
STICK_REPEAT_MILLISECONDS = 90,
|
|
};
|
|
|
|
static short stick_repeats[NUMBER_OF_GAMEPAD_STICKS][MAXIMUM_GAMEPADS];
|
|
|
|
#define STICK_REPEAT_INTERVAL(stick, controller_index) \
|
|
(stick_repeats[stick][controller_index] ? STICK_REPEAT_MILLISECONDS : STICK_REPEAT_FIRST_MILLISECONDS)
|
|
#else
|
|
#define STICK_REPEAT_INTERVAL(stick, controller_index) STICK_EVENT_REPEAT_MILLISECONDS
|
|
#endif
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static void queue_event(
|
|
struct event_record *event,
|
|
short controller_index);
|
|
|
|
/* ---------- globals */
|
|
|
|
struct event_manager_globals event_manager_globals = { 0 };
|
|
|
|
/* ---------- public code */
|
|
|
|
#ifdef HALO_ANDROID
|
|
/* an event the stick posts: a fresh push (it was within the threshold on
|
|
that axis) starts the count of repeats again */
|
|
static void stick_note_event(
|
|
short stick,
|
|
short controller_index,
|
|
long x,
|
|
long y,
|
|
unsigned long time)
|
|
{
|
|
boolean fresh =
|
|
(ABS(x) >= STICK_EVENT_THRESHOLD &&
|
|
ABS(event_manager_globals.previous_stick_axes[stick][0][controller_index]) < STICK_EVENT_THRESHOLD) ||
|
|
(ABS(y) >= STICK_EVENT_THRESHOLD &&
|
|
ABS(event_manager_globals.previous_stick_axes[stick][1][controller_index]) < STICK_EVENT_THRESHOLD);
|
|
|
|
(void)time;
|
|
if (fresh)
|
|
stick_repeats[stick][controller_index] = 0;
|
|
else if (stick_repeats[stick][controller_index] < SHORT_MAX)
|
|
stick_repeats[stick][controller_index]++;
|
|
}
|
|
|
|
#endif
|
|
void event_manager_initialize(
|
|
void)
|
|
{
|
|
csmemset(&event_manager_globals.state, 0, sizeof(event_manager_globals.state));
|
|
event_manager_globals.state.time_of_last_event = system_milliseconds();
|
|
event_manager_globals.state.initialized = TRUE;
|
|
return;
|
|
}
|
|
|
|
void event_manager_dispose(
|
|
void)
|
|
{
|
|
csmemset(&event_manager_globals.state, 0, sizeof(event_manager_globals.state));
|
|
return;
|
|
}
|
|
|
|
void event_manager_flush(
|
|
void)
|
|
{
|
|
csmemset(event_manager_globals.state.events, 0, sizeof(event_manager_globals.state.events));
|
|
return;
|
|
}
|
|
|
|
void event_manager_suppress(
|
|
boolean suppress)
|
|
{
|
|
event_manager_globals.state.suppressed = suppress;
|
|
return;
|
|
}
|
|
|
|
boolean get_next_event(
|
|
struct event_record *event,
|
|
short local_player_index)
|
|
{
|
|
boolean result = FALSE;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\interface\\event_manager.c",
|
|
211,
|
|
event && ((local_player_index>=0 && local_player_index<MAXIMUM_GAMEPADS) || local_player_index==NONE));
|
|
|
|
if (event_manager_globals.state.initialized)
|
|
{
|
|
if (local_player_index == NONE)
|
|
{
|
|
local_player_index = 0;
|
|
while (!result)
|
|
{
|
|
if (local_player_index >= MAXIMUM_GAMEPADS)
|
|
break;
|
|
result = get_next_event(event, local_player_index);
|
|
local_player_index++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long event_index;
|
|
|
|
for (event_index = 7; event_index >= 0; event_index--)
|
|
{
|
|
if (event_manager_globals.state.events[local_player_index][event_index].type != 0)
|
|
{
|
|
*event = event_manager_globals.state.events[local_player_index][event_index];
|
|
event_manager_globals.state.events[local_player_index][event_index].type = 0;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
unsigned long event_manager_time_of_last_event(
|
|
void)
|
|
{
|
|
return event_manager_globals.state.time_of_last_event;
|
|
}
|
|
|
|
void event_manager_post_button(
|
|
short controller_index,
|
|
short button_index)
|
|
{
|
|
struct event_record event = {0};
|
|
|
|
if (!event_manager_globals.state.initialized ||
|
|
controller_index < 0 ||
|
|
controller_index >= MAXIMUM_GAMEPADS)
|
|
{
|
|
return;
|
|
}
|
|
event.type = _event_type_button;
|
|
event.data.button.index = (byte)button_index;
|
|
event.data.button.value = 1;
|
|
queue_event(&event, controller_index);
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static void queue_event(
|
|
struct event_record *event,
|
|
short controller_index)
|
|
{
|
|
unsigned long time;
|
|
boolean post = TRUE;
|
|
|
|
if (event_manager_globals.state.suppressed)
|
|
return;
|
|
|
|
time = system_milliseconds();
|
|
|
|
if (event->type == _event_type_left_stick)
|
|
{
|
|
long x = event->data.stick.x;
|
|
long y = event->data.stick.y;
|
|
|
|
if (ABS(x) < STICK_EVENT_THRESHOLD && ABS(y) < STICK_EVENT_THRESHOLD)
|
|
{
|
|
post = FALSE;
|
|
}
|
|
else if (!((ABS(x) >= STICK_EVENT_THRESHOLD &&
|
|
ABS(event_manager_globals.previous_stick_axes[_gamepad_stick_left][0][controller_index]) < STICK_EVENT_THRESHOLD) ||
|
|
(ABS(y) >= STICK_EVENT_THRESHOLD &&
|
|
ABS(event_manager_globals.previous_stick_axes[_gamepad_stick_left][1][controller_index]) < STICK_EVENT_THRESHOLD) ||
|
|
time - event_manager_globals.stick_event_times[_gamepad_stick_left][controller_index] >=
|
|
STICK_REPEAT_INTERVAL(_gamepad_stick_left, controller_index)))
|
|
{
|
|
post = FALSE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef HALO_ANDROID
|
|
stick_note_event(_gamepad_stick_left, controller_index, x, y, time);
|
|
#endif
|
|
event_manager_globals.stick_event_times[_gamepad_stick_left][controller_index] = time;
|
|
post = TRUE;
|
|
|
|
if (ABS(x) >= STICK_EVENT_THRESHOLD)
|
|
{
|
|
switch (x >= 0 ? 1 : -1)
|
|
{
|
|
case 1:
|
|
x = event->data.stick.x = 32767;
|
|
break;
|
|
case -1:
|
|
x = event->data.stick.x = -32768;
|
|
break;
|
|
}
|
|
}
|
|
if (ABS(y) >= STICK_EVENT_THRESHOLD)
|
|
{
|
|
switch (y >= 0 ? 1 : -1)
|
|
{
|
|
case 1:
|
|
y = event->data.stick.y = 32767;
|
|
break;
|
|
case -1:
|
|
y = event->data.stick.y = -32768;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
event_manager_globals.previous_stick_axes[_gamepad_stick_left][0][controller_index] = x;
|
|
event_manager_globals.previous_stick_axes[_gamepad_stick_left][1][controller_index] = y;
|
|
}
|
|
else if (event->type == _event_type_right_stick)
|
|
{
|
|
long x = event->data.stick.x;
|
|
long y = event->data.stick.y;
|
|
|
|
if (ABS(x) < STICK_EVENT_THRESHOLD && ABS(y) < STICK_EVENT_THRESHOLD)
|
|
{
|
|
post = FALSE;
|
|
}
|
|
else if (!((ABS(x) >= STICK_EVENT_THRESHOLD &&
|
|
ABS(event_manager_globals.previous_stick_axes[_gamepad_stick_right][0][controller_index]) < STICK_EVENT_THRESHOLD) ||
|
|
(ABS(y) >= STICK_EVENT_THRESHOLD &&
|
|
ABS(event_manager_globals.previous_stick_axes[_gamepad_stick_right][1][controller_index]) < STICK_EVENT_THRESHOLD) ||
|
|
time - event_manager_globals.stick_event_times[_gamepad_stick_right][controller_index] >=
|
|
STICK_REPEAT_INTERVAL(_gamepad_stick_right, controller_index)))
|
|
{
|
|
post = FALSE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef HALO_ANDROID
|
|
stick_note_event(_gamepad_stick_right, controller_index, x, y, time);
|
|
#endif
|
|
event_manager_globals.stick_event_times[_gamepad_stick_right][controller_index] = time;
|
|
post = TRUE;
|
|
|
|
if (ABS(x) >= STICK_EVENT_THRESHOLD)
|
|
{
|
|
switch (x >= 0 ? 1 : -1)
|
|
{
|
|
case 1:
|
|
x = event->data.stick.x = 32767;
|
|
break;
|
|
case -1:
|
|
x = event->data.stick.x = -32768;
|
|
break;
|
|
}
|
|
}
|
|
if (ABS(y) >= STICK_EVENT_THRESHOLD)
|
|
{
|
|
switch (y >= 0 ? 1 : -1)
|
|
{
|
|
case 1:
|
|
y = event->data.stick.y = 32767;
|
|
break;
|
|
case -1:
|
|
y = event->data.stick.y = -32768;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
event_manager_globals.previous_stick_axes[_gamepad_stick_right][0][controller_index] = x;
|
|
event_manager_globals.previous_stick_axes[_gamepad_stick_right][1][controller_index] = y;
|
|
}
|
|
|
|
if (post)
|
|
{
|
|
event->controller_index = controller_index;
|
|
csmemmove(
|
|
event_manager_globals.state.events[controller_index],
|
|
&event_manager_globals.state.events[controller_index][1],
|
|
sizeof(event_manager_globals.state.events[controller_index]) - sizeof(struct event_record));
|
|
event_manager_globals.state.events[controller_index][0] = *event;
|
|
if (event->type != _event_type_null)
|
|
{
|
|
event_manager_globals.state.time_of_last_event = time;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void event_manager_update(
|
|
void)
|
|
{
|
|
short gamepad_index;
|
|
|
|
if (!event_manager_globals.state.initialized)
|
|
return;
|
|
|
|
for (gamepad_index = 0; gamepad_index < MAXIMUM_GAMEPADS; gamepad_index++)
|
|
{
|
|
boolean posted = FALSE;
|
|
|
|
if (input_has_gamepad(gamepad_index))
|
|
{
|
|
struct gamepad_state const *state = input_get_gamepad_state(gamepad_index);
|
|
|
|
if (state)
|
|
{
|
|
struct event_record event;
|
|
short button_index;
|
|
|
|
if (state->sticks[_gamepad_stick_left].x != 0 ||
|
|
state->sticks[_gamepad_stick_left].y != 0)
|
|
{
|
|
event.type = _event_type_left_stick;
|
|
event.data.stick = state->sticks[_gamepad_stick_left];
|
|
queue_event(&event, gamepad_index);
|
|
posted = TRUE;
|
|
}
|
|
|
|
if (state->sticks[_gamepad_stick_right].x != 0 ||
|
|
state->sticks[_gamepad_stick_right].y != 0)
|
|
{
|
|
event.type = _event_type_right_stick;
|
|
event.data.stick = state->sticks[_gamepad_stick_right];
|
|
queue_event(&event, gamepad_index);
|
|
posted = TRUE;
|
|
}
|
|
|
|
for (button_index = 0; button_index < NUMBER_OF_GAMEPAD_BUTTONS; button_index++)
|
|
{
|
|
byte value = state->buttons[button_index];
|
|
|
|
if (value)
|
|
{
|
|
event.type = _event_type_button;
|
|
event.data.button.index = (byte)button_index;
|
|
event.data.button.value = value;
|
|
queue_event(&event, gamepad_index);
|
|
posted = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!posted)
|
|
{
|
|
struct event_record event = {0};
|
|
|
|
queue_event(&event, gamepad_index);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|