2023-08-09 09:39:42 +00:00
# ifndef RC_CLIENT_INTERNAL_H
# define RC_CLIENT_INTERNAL_H
# include "rc_client.h"
2023-11-30 04:06:00 +00:00
# ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
# include "rc_client_raintegration_internal.h"
# endif
# ifdef RC_CLIENT_SUPPORTS_EXTERNAL
# include "rc_client_external.h"
# endif
2023-08-09 09:39:42 +00:00
# include "rc_compat.h"
# include "rc_runtime.h"
# include "rc_runtime_types.h"
2024-01-13 04:24:04 +00:00
RC_BEGIN_C_DECLS
2023-11-06 09:41:10 +00:00
/*****************************************************************************\
| Callbacks |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-09-06 12:37:42 +00:00
struct rc_api_fetch_game_data_response_t ;
2024-01-13 04:24:04 +00:00
typedef void ( RC_CCONV * rc_client_post_process_game_data_response_t ) ( const rc_api_server_response_t * server_response ,
2023-09-06 12:37:42 +00:00
struct rc_api_fetch_game_data_response_t * game_data_response , rc_client_t * client , void * userdata ) ;
2024-01-13 04:24:04 +00:00
typedef int ( RC_CCONV * rc_client_can_submit_achievement_unlock_t ) ( uint32_t achievement_id , rc_client_t * client ) ;
typedef int ( RC_CCONV * rc_client_can_submit_leaderboard_entry_t ) ( uint32_t leaderboard_id , rc_client_t * client ) ;
typedef int ( RC_CCONV * rc_client_rich_presence_override_t ) ( rc_client_t * client , char buffer [ ] , size_t buffersize ) ;
2024-02-24 04:52:57 +00:00
typedef uint32_t ( RC_CCONV * rc_client_identify_hash_func_t ) ( uint32_t console_id , const char * hash ,
rc_client_t * client , void * callback_userdata ) ;
2023-09-06 12:37:42 +00:00
2023-08-09 09:39:42 +00:00
typedef struct rc_client_callbacks_t {
rc_client_read_memory_func_t read_memory ;
rc_client_event_handler_t event_handler ;
rc_client_server_call_t server_call ;
rc_client_message_callback_t log_call ;
2023-09-06 12:37:42 +00:00
rc_get_time_millisecs_func_t get_time_millisecs ;
2024-02-24 04:52:57 +00:00
rc_client_identify_hash_func_t identify_unknown_hash ;
2023-09-06 12:37:42 +00:00
rc_client_post_process_game_data_response_t post_process_game_data_response ;
rc_client_can_submit_achievement_unlock_t can_submit_achievement_unlock ;
rc_client_can_submit_leaderboard_entry_t can_submit_leaderboard_entry ;
2023-11-06 09:41:10 +00:00
rc_client_rich_presence_override_t rich_presence_override ;
2023-08-09 09:39:42 +00:00
void * client_data ;
} rc_client_callbacks_t ;
struct rc_client_scheduled_callback_data_t ;
2024-01-13 04:24:04 +00:00
typedef void ( RC_CCONV * rc_client_scheduled_callback_t ) ( struct rc_client_scheduled_callback_data_t * callback_data , rc_client_t * client , rc_clock_t now ) ;
2023-08-09 09:39:42 +00:00
typedef struct rc_client_scheduled_callback_data_t
{
2023-09-06 12:37:42 +00:00
rc_clock_t when ;
2023-11-06 09:41:10 +00:00
uint32_t related_id ;
2023-08-09 09:39:42 +00:00
rc_client_scheduled_callback_t callback ;
void * data ;
struct rc_client_scheduled_callback_data_t * next ;
} rc_client_scheduled_callback_data_t ;
void rc_client_schedule_callback ( rc_client_t * client , rc_client_scheduled_callback_data_t * scheduled_callback ) ;
2023-11-30 04:06:00 +00:00
struct rc_client_async_handle_t {
uint8_t aborted ;
} ;
int rc_client_async_handle_aborted ( rc_client_t * client , rc_client_async_handle_t * async_handle ) ;
2023-11-06 09:41:10 +00:00
/*****************************************************************************\
| Achievements |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
enum {
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_NONE = 0 ,
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_TRIGGERED = ( 1 < < 1 ) ,
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_SHOW = ( 1 < < 2 ) ,
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_CHALLENGE_INDICATOR_HIDE = ( 1 < < 3 ) ,
RC_CLIENT_ACHIEVEMENT_PENDING_EVENT_UPDATE = ( 1 < < 4 ) /* not a real event, just triggers update */
} ;
typedef struct rc_client_achievement_info_t {
rc_client_achievement_t public_ ;
rc_trigger_t * trigger ;
uint8_t md5 [ 16 ] ;
time_t unlock_time_hardcore ;
time_t unlock_time_softcore ;
uint8_t pending_events ;
const char * author ;
time_t created_time ;
time_t updated_time ;
} rc_client_achievement_info_t ;
2023-11-30 04:06:00 +00:00
struct rc_client_achievement_list_info_t ;
2024-01-13 04:24:04 +00:00
typedef void ( RC_CCONV * rc_client_destroy_achievement_list_func_t ) ( struct rc_client_achievement_list_info_t * list ) ;
2023-11-30 04:06:00 +00:00
typedef struct rc_client_achievement_list_info_t {
rc_client_achievement_list_t public_ ;
rc_client_destroy_achievement_list_func_t destroy_func ;
} rc_client_achievement_list_info_t ;
2023-08-09 09:39:42 +00:00
enum {
RC_CLIENT_PROGRESS_TRACKER_ACTION_NONE ,
RC_CLIENT_PROGRESS_TRACKER_ACTION_SHOW ,
RC_CLIENT_PROGRESS_TRACKER_ACTION_UPDATE ,
RC_CLIENT_PROGRESS_TRACKER_ACTION_HIDE
} ;
typedef struct rc_client_progress_tracker_t {
rc_client_achievement_info_t * achievement ;
float progress ;
rc_client_scheduled_callback_data_t * hide_callback ;
uint8_t action ;
} rc_client_progress_tracker_t ;
2023-11-06 09:41:10 +00:00
/*****************************************************************************\
| Leaderboard Trackers |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
enum {
RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_NONE = 0 ,
RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_UPDATE = ( 1 < < 1 ) ,
RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_SHOW = ( 1 < < 2 ) ,
RC_CLIENT_LEADERBOARD_TRACKER_PENDING_EVENT_HIDE = ( 1 < < 3 )
} ;
typedef struct rc_client_leaderboard_tracker_info_t {
rc_client_leaderboard_tracker_t public_ ;
struct rc_client_leaderboard_tracker_info_t * next ;
2023-11-06 09:41:10 +00:00
int32_t raw_value ;
2023-08-09 09:39:42 +00:00
uint32_t value_djb2 ;
uint8_t format ;
uint8_t pending_events ;
uint8_t reference_count ;
uint8_t value_from_hits ;
} rc_client_leaderboard_tracker_info_t ;
2023-11-06 09:41:10 +00:00
/*****************************************************************************\
| Leaderboards |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
enum {
RC_CLIENT_LEADERBOARD_PENDING_EVENT_NONE = 0 ,
RC_CLIENT_LEADERBOARD_PENDING_EVENT_STARTED = ( 1 < < 1 ) ,
RC_CLIENT_LEADERBOARD_PENDING_EVENT_FAILED = ( 1 < < 2 ) ,
RC_CLIENT_LEADERBOARD_PENDING_EVENT_SUBMITTED = ( 1 < < 3 )
} ;
typedef struct rc_client_leaderboard_info_t {
rc_client_leaderboard_t public_ ;
rc_lboard_t * lboard ;
uint8_t md5 [ 16 ] ;
rc_client_leaderboard_tracker_info_t * tracker ;
uint32_t value_djb2 ;
2023-11-06 09:41:10 +00:00
int32_t value ;
2023-08-09 09:39:42 +00:00
uint8_t format ;
uint8_t pending_events ;
uint8_t bucket ;
uint8_t hidden ;
} rc_client_leaderboard_info_t ;
2023-11-30 04:06:00 +00:00
struct rc_client_leaderboard_list_info_t ;
2024-01-13 04:24:04 +00:00
typedef void ( RC_CCONV * rc_client_destroy_leaderboard_list_func_t ) ( struct rc_client_leaderboard_list_info_t * list ) ;
2023-11-30 04:06:00 +00:00
typedef struct rc_client_leaderboard_list_info_t {
rc_client_leaderboard_list_t public_ ;
rc_client_destroy_leaderboard_list_func_t destroy_func ;
} rc_client_leaderboard_list_info_t ;
struct rc_client_leaderboard_entry_list_info_t ;
2024-01-13 04:24:04 +00:00
typedef void ( RC_CCONV * rc_client_destroy_leaderboard_entry_list_func_t ) ( struct rc_client_leaderboard_entry_list_info_t * list ) ;
2023-11-30 04:06:00 +00:00
typedef struct rc_client_leaderboard_entry_list_info_t {
rc_client_leaderboard_entry_list_t public_ ;
rc_client_destroy_leaderboard_entry_list_func_t destroy_func ;
} rc_client_leaderboard_entry_list_info_t ;
2023-11-06 09:41:10 +00:00
uint8_t rc_client_map_leaderboard_format ( int format ) ;
/*****************************************************************************\
| Subsets |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
enum {
RC_CLIENT_SUBSET_PENDING_EVENT_NONE = 0 ,
RC_CLIENT_SUBSET_PENDING_EVENT_ACHIEVEMENT = ( 1 < < 1 ) ,
RC_CLIENT_SUBSET_PENDING_EVENT_LEADERBOARD = ( 1 < < 2 )
} ;
typedef struct rc_client_subset_info_t {
rc_client_subset_t public_ ;
rc_client_achievement_info_t * achievements ;
rc_client_leaderboard_info_t * leaderboards ;
struct rc_client_subset_info_t * next ;
const char * all_label ;
const char * inactive_label ;
const char * locked_label ;
const char * unlocked_label ;
const char * unofficial_label ;
const char * unsupported_label ;
uint8_t active ;
uint8_t mastery ;
uint8_t pending_events ;
} rc_client_subset_info_t ;
2023-11-30 04:06:00 +00:00
rc_client_async_handle_t * rc_client_begin_load_subset ( rc_client_t * client , uint32_t subset_id , rc_client_callback_t callback , void * callback_userdata ) ;
2023-11-06 09:41:10 +00:00
/*****************************************************************************\
| Game |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
typedef struct rc_client_game_hash_t {
char hash [ 33 ] ;
uint32_t game_id ;
struct rc_client_game_hash_t * next ;
} rc_client_game_hash_t ;
rc_client_game_hash_t * rc_client_find_game_hash ( rc_client_t * client , const char * hash ) ;
typedef struct rc_client_media_hash_t {
rc_client_game_hash_t * game_hash ;
struct rc_client_media_hash_t * next ;
uint32_t path_djb2 ;
} rc_client_media_hash_t ;
2023-11-06 09:41:10 +00:00
enum {
RC_CLIENT_GAME_PENDING_EVENT_NONE = 0 ,
RC_CLIENT_GAME_PENDING_EVENT_LEADERBOARD_TRACKER = ( 1 < < 1 ) ,
RC_CLIENT_GAME_PENDING_EVENT_UPDATE_ACTIVE_ACHIEVEMENTS = ( 1 < < 2 ) ,
RC_CLIENT_GAME_PENDING_EVENT_PROGRESS_TRACKER = ( 1 < < 3 )
} ;
2023-08-09 09:39:42 +00:00
typedef struct rc_client_game_info_t {
rc_client_game_t public_ ;
rc_client_leaderboard_tracker_info_t * leaderboard_trackers ;
rc_client_progress_tracker_t progress_tracker ;
rc_client_subset_info_t * subsets ;
rc_client_media_hash_t * media_hash ;
rc_runtime_t runtime ;
uint32_t max_valid_address ;
uint8_t waiting_for_reset ;
uint8_t pending_events ;
2023-11-06 09:41:10 +00:00
rc_buffer_t buffer ;
2023-08-09 09:39:42 +00:00
} rc_client_game_info_t ;
2023-11-06 09:41:10 +00:00
void rc_client_update_active_achievements ( rc_client_game_info_t * game ) ;
void rc_client_update_active_leaderboards ( rc_client_game_info_t * game ) ;
/*****************************************************************************\
| Client |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
enum {
RC_CLIENT_USER_STATE_NONE ,
RC_CLIENT_USER_STATE_LOGIN_REQUESTED ,
RC_CLIENT_USER_STATE_LOGGED_IN
} ;
enum {
RC_CLIENT_MASTERY_STATE_NONE ,
RC_CLIENT_MASTERY_STATE_PENDING ,
RC_CLIENT_MASTERY_STATE_SHOWN
} ;
enum {
RC_CLIENT_SPECTATOR_MODE_OFF ,
RC_CLIENT_SPECTATOR_MODE_ON ,
RC_CLIENT_SPECTATOR_MODE_LOCKED
} ;
2023-09-06 12:37:42 +00:00
enum {
RC_CLIENT_DISCONNECT_HIDDEN = 0 ,
RC_CLIENT_DISCONNECT_VISIBLE = ( 1 < < 0 ) ,
RC_CLIENT_DISCONNECT_SHOW_PENDING = ( 1 < < 1 ) ,
RC_CLIENT_DISCONNECT_HIDE_PENDING = ( 1 < < 2 )
} ;
2023-08-09 09:39:42 +00:00
struct rc_client_load_state_t ;
typedef struct rc_client_state_t {
rc_mutex_t mutex ;
2023-11-06 09:41:10 +00:00
rc_buffer_t buffer ;
2023-08-09 09:39:42 +00:00
rc_client_scheduled_callback_data_t * scheduled_callbacks ;
2023-11-30 04:06:00 +00:00
# ifdef RC_CLIENT_SUPPORTS_EXTERNAL
rc_client_external_t * external_client ;
# endif
# ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
rc_client_raintegration_t * raintegration ;
# endif
2024-01-13 04:24:04 +00:00
uint16_t unpaused_frame_decay ;
uint16_t required_unpaused_frames ;
2023-08-09 09:39:42 +00:00
uint8_t hardcore ;
uint8_t encore_mode ;
uint8_t spectator_mode ;
uint8_t unofficial_enabled ;
uint8_t log_level ;
uint8_t user ;
2023-09-06 12:37:42 +00:00
uint8_t disconnect ;
2024-02-24 04:52:57 +00:00
uint8_t allow_leaderboards_in_softcore ;
2023-08-09 09:39:42 +00:00
struct rc_client_load_state_t * load ;
2023-11-06 09:41:10 +00:00
struct rc_client_async_handle_t * async_handles [ 4 ] ;
2023-08-09 09:39:42 +00:00
rc_memref_t * processing_memref ;
rc_peek_t legacy_peek ;
} rc_client_state_t ;
struct rc_client_t {
rc_client_game_info_t * game ;
rc_client_game_hash_t * hashes ;
rc_client_user_t user ;
rc_client_callbacks_t callbacks ;
rc_client_state_t state ;
} ;
2023-11-06 09:41:10 +00:00
/*****************************************************************************\
| Helpers |
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-08-09 09:39:42 +00:00
# ifdef RC_NO_VARIADIC_MACROS
void RC_CLIENT_LOG_ERR_FORMATTED ( const rc_client_t * client , const char * format , . . . ) ;
void RC_CLIENT_LOG_WARN_FORMATTED ( const rc_client_t * client , const char * format , . . . ) ;
void RC_CLIENT_LOG_INFO_FORMATTED ( const rc_client_t * client , const char * format , . . . ) ;
void RC_CLIENT_LOG_VERBOSE_FORMATTED ( const rc_client_t * client , const char * format , . . . ) ;
# else
void rc_client_log_message_formatted ( const rc_client_t * client , const char * format , . . . ) ;
# define RC_CLIENT_LOG_ERR_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) rc_client_log_message_formatted(client, format, __VA_ARGS__); }
# define RC_CLIENT_LOG_WARN_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) rc_client_log_message_formatted(client, format, __VA_ARGS__); }
# define RC_CLIENT_LOG_INFO_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) rc_client_log_message_formatted(client, format, __VA_ARGS__); }
# define RC_CLIENT_LOG_VERBOSE_FORMATTED(client, format, ...) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message_formatted(client, format, __VA_ARGS__); }
# endif
void rc_client_log_message ( const rc_client_t * client , const char * message ) ;
# define RC_CLIENT_LOG_ERR(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_ERROR) rc_client_log_message(client, message); }
# define RC_CLIENT_LOG_WARN(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_WARN) rc_client_log_message(client, message); }
# define RC_CLIENT_LOG_INFO(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_INFO) rc_client_log_message(client, message); }
# define RC_CLIENT_LOG_VERBOSE(client, message) { if (client->state.log_level >= RC_CLIENT_LOG_LEVEL_VERBOSE) rc_client_log_message(client, message); }
/* internals pulled from runtime.c */
2023-11-06 09:41:10 +00:00
void rc_runtime_checksum ( const char * memaddr , uint8_t * md5 ) ;
2023-08-09 09:39:42 +00:00
int rc_trigger_contains_memref ( const rc_trigger_t * trigger , const rc_memref_t * memref ) ;
int rc_value_contains_memref ( const rc_value_t * value , const rc_memref_t * memref ) ;
/* end runtime.c internals */
/* helper functions for unit tests */
2024-06-24 01:27:43 +00:00
# ifdef RC_CLIENT_SUPPORTS_HASH
2023-08-09 09:39:42 +00:00
struct rc_hash_iterator ;
struct rc_hash_iterator * rc_client_get_load_state_hash_iterator ( rc_client_t * client ) ;
2024-06-24 01:27:43 +00:00
# endif
2023-08-09 09:39:42 +00:00
/* end helper functions for unit tests */
enum {
RC_CLIENT_LEGACY_PEEK_AUTO ,
RC_CLIENT_LEGACY_PEEK_CONSTRUCTED ,
RC_CLIENT_LEGACY_PEEK_LITTLE_ENDIAN_READS
} ;
void rc_client_set_legacy_peek ( rc_client_t * client , int method ) ;
2024-02-24 04:52:57 +00:00
void rc_client_allocate_leaderboard_tracker ( rc_client_game_info_t * game , rc_client_leaderboard_info_t * leaderboard ) ;
2023-11-06 09:41:10 +00:00
void rc_client_release_leaderboard_tracker ( rc_client_game_info_t * game , rc_client_leaderboard_info_t * leaderboard ) ;
2023-08-09 09:39:42 +00:00
2024-01-13 04:24:04 +00:00
RC_END_C_DECLS
2023-08-09 09:39:42 +00:00
# endif /* RC_CLIENT_INTERNAL_H */