Game Host Adapter
The GameHostAdapter library is a utility library used to help bootstrap server allocations across multiple vendors. It is a required part of the integration in order to utilize our server allocation scheme.
A developer version of the library can be provided as needed, and is included in the Unreal Integration.
C/C++ Library
The C/C++ integration contains 3 files of note: RH_GameHostAdapter.h, RH_GameHostAdapterFwd.h, and RH_GameHostAdapter.cpp
- RH_GameHostAdapter.h contains the public interface for the library
- RH_GameHostAdapterFwd.h contains forward declarations for the library for use in header files
- RH_GameHostAdapter.cpp contains the implementation of the library
Library API
The library API is defined in RH_GameHostAdapter.h. The API is defined as a set of C functions that are exported from the library.
Note that most calls in the library provide a RallyHereStatusCode
enum value in their responses. Generally, you can check this with rallyhere_is_error(<code>)
to determine if it is an error. Additionally, you can get a printable version of the error using rallyhere_status_text(<code>)
.
Loading the Library
To load the library and initialize it, call static bool GameHostAdapterImporter::Import()
. This will attempt to load the library file, including handling path based overrides on the commandline. By default, it will look for the library in the same directory as the executable.
If the library is not found, or fails to load, the function will return false.
Creating an Adapter Context
To utilize the library, you will need to create an adapter context object once it is loaded. This can be done by calling one of the following functions:
extern RallyHereStatusCode (*rallyhere_create_game_instance_adapter)(void* adapter, const char* arguments);
extern RallyHereStatusCode (*rallyhere_create_game_instance_adapter_with_logger)(RallyHereGameInstanceAdapterPtr* adapter,
const char* arguments,
RallyHereLogCallback callback,
void* user_data);
The adapter
passed in is an out pointer to the resulting adapter. It is valid if the RallyHereStatusCode
returned passes a rallyhere_is_error(<return_code>)
check.
The arguments
passed in must contain the commandline arguments string (though additional argments can be added as needed).
The callback
passed in is a function pointer that will be called when the library needs to log something. The user_data
passed in will be passed back to the callback function.
Required Adapter Functions
To utilize the adapter, you will need to implement calls to the following functions, and relevant callbacks.
extern void (*rallyhere_on_soft_stop_callback)(RallyHereGameInstanceAdapterPtr adapter,
void (*callback)(const RallyHereStatusCode& code, void* user_data),
void* user_data);
extern RallyHereStatusCode (*rallyhere_tick)(RallyHereGameInstanceAdapterPtr adapter);
extern RallyHereStatusCode (*rallyhere_stats_base)(RallyHereGameInstanceAdapterPtr adapter,
const RallyHereStatsBase* stats,
const RallyHereStatsBaseProvided *provided,
void (*callback)(const RallyHereStatusCode& code, void* user_data),
void* user_data);
The rallyhere_on_soft_stop_callback
registers a callback that is triggered when a soft stop is requested by the hosting provider. This does not mean an exit must happen immediately, but does hint that the server should shutdown as soon as possible.
The rallyhere_tick
function must be called routinely (generally every frame), as it is used to process any pending requests from the library and to do health checks. Most callbacks generated are dispatched during this function call on the thread making the call. Some callbacks may be called during the initial function call which used them, or when rallyhere_destroy_game_instance_adapter
is called.
The rallyhere_stats_base
is used to set some of the basic stats provided by the game. The callback is triggered when the hosting provider accepts these basic stats about the server. In the case of an error there was something wrong with the format of the stats or the hosting provider rejected them. Once the callback is successful all external systems which monitor for these stats should see the newly set values.
Additional stats can be provided using the rallyhere_set_additional_info
, rallyhere_stats_gauge
, and rallyhere_stats_gauge_with_labels
functions.
Destroying an Adapter Context
To destroy an adapter context, call the following function:
extern void (*rallyhere_destroy_game_instance_adapter)(RallyHereGameInstanceAdapterPtr adapter);
Requested Allocation Flow
This flow supports servers that are fielded via requests to the allocation service, such as via matchmaking. These servers spin up and then wait for allocation data from the hosting provider.
The Requested Allocation Flow utilizes the following functions in the following order. These functions are all asynchronous, and upon completion will call the provided callback function. The status code should be checked with rallyhere_is_error(<code>)
before using the results and calling the next function, except as noted below
rallyhere_connect
-> (callback as passed in)rallyhere_on_allocated_callback
to register callback for allocation completerallyhere_ready
-> (callback as passed in)- callback from
rallyhere_on_allocated_callback
as registered above
The callback response from rallyhere_on_allocated_callback
has some additional recommended checks from the status code:
rallyhere_is_cancelled(<code>)
- this is a special code indicating that any resources associated with this callback should be freed and that the callback won’t be used again. This is usually called duringrallyhere_destory_game_instance_adapter
to give the user a chance to free anyuser_data
.rallyhere_is_error(<code>)
- as normal, this is an error.
If the result is not an error, then the allocation_info is a string map containing the following keys:
allocation_id
- the allocation id from the hosting providerpublic_host
- the public hostname or ip that the hosting provider will use for clients to connect to this serverpublic_port
- the public port the hosting provider will use for clients to connect to this server
These can be retrieved from the map with the rallyhere_string_map_get
function, which takes the map pointer, the key, and has an out pointer to the resulting value (a UTF8 character array) and the length of the value.
Note that the callback should destroy the allocation_info object with rallyhere_string_map_destroy
once complete, or memory will be leaked.
Self-Hosted Allocation Flow With No Fallback
This flow supports servers that are designed to self-allocate, such as for fixed-capacity open world servers, or third party hosted servers. These servers will mark themselves as allocated, and provide functionality immediately upon spinning up rather than waiting on a request.
The Self-Hosted Allocation Flow With No Fallback utilizes the following functions in the following order. These functions are all asynchronous, and upon completion will call the provided callback function. The status code should be checked with rallyhere_is_error(<code>)
before using the results and calling the next function, except as noted below
rallyhere_connect
-> (callback as passed in)rallyhere_reserve_unconditional
-> (callback as passed in)- Server completes its self initialization and enters its running state
rallyhere_allocate
-> (callback as passed in)
The callback response from rallyhere_allocate
has some additional recommended checks from the status code:
rallyhere_is_cancelled(<code>)
- this is a special code indicating that any resources associated with this callback should be freed and that the callback won’t be used again. This is usually called duringrallyhere_destory_game_instance_adapter
to give the user a chance to free anyuser_data
.rallyhere_is_error(<code>)
- as normal, this is an error.
If you have registered a callback via rallyhere_on_allocated_callback
, it will also be called as a result of the rallyhere_allocate
call. In this situation the allocation_info map will be nullptr
, as the server is assumed to provide it itself.
Self-Hosted Allocation Flow With Fallback Timeout
This flow supports servers that are designed to self-allocate, such as for fixed-capacity open world servers, or third party hosted servers. These servers will mark themselves as allocated, and provide functionality immediately upon spinning up rather than waiting on a request. A timeout is provided so that if this doesn’t happen within a certain amount of time the requested allocation flow will be used instead. This can be a way to handle the situation where third parties are able to launch instances, but need to return to the normal flow if no players connect after a certain amount of time.
The Self-Hosted Allocation Flow With Fallback utilizes the following functions in the following order. These functions are all asynchronous, and upon completion will call the provided callback function. The status code should be checked with rallyhere_is_error(<code>)
before using the results and calling the next function, except as noted below
rallyhere_connect
-> (callback as passed in)rallyhere_on_allocated_callback
to register callback for allocation completerallyhere_reserve
-> pass in a timeout, a callback for when the reservation is accepted, and a callback to use if the requested allocation flow is used- Server completes its self initialization and enters its running state
rallyhere_allocate
-> (callback as passed in)
The callback response from rallyhere_allocate
has some additional recommended checks from the status code:
rallyhere_is_cancelled(<code>)
- this is a special code indicating that any resources associated with this callback should be freed and that the callback won’t be used again. This is usually called duringrallyhere_destory_game_instance_adapter
to give the user a chance to free anyuser_data
.rallyhere_is_error(<code>)
- as normal, this is an error.
If you have registered a callback via rallyhere_on_allocated_callback
, it will also be called as a result of the rallyhere_allocate
call. In this situation the allocation_info map will be nullptr
, as the server is assumed to provide it itself.
In the case where an amount of seconds greater than the timeout happens between rallyhere_reserve
and rallyhere_allocate
, then the ready callback will be called. Once this happens you may no longer call rallyhere_allocate
and instead must wait for the callback provided to rallyhere_on_allocated_callback
to be triggered. See the Requested Allocation Flow for handling that case.
Testing
To begin, you will need a credential file. This can be provided via your RallyHere developer contact.
All tests require the following command line arguments:
-rallyhereurl=<url_to_rallyhere_api>
- This provides the URL to the RallyHere API-rhcredentialsfile=<path_to_credentials_file>
- the path to the credentials file mentioned above.-rhpublichost=<hostname_or_ip_for_connection>
- the hostname or IP to use for connecting to the server
Note for the Unreal Integration, the -rallyhereurl
argument is not required, as it is provided by the integration based on the detected baseurl and sandbox.
Running SIC Servers
This method is used to test the Self-Hosted Allocation Flow With No Fallback
You will need a SIC profile id for the sandbox you are trying to host in. This can be provided via your RallyHere developer contact.
To run in SIC mode server using the library, you will need to provide the following command line arguments (note - deployed servers will receive additional commandline arguments that the library will process):
-rhbootstrapmode=SIC
- this informs the library that it will be running in SIC mode-rhsicprofileid=<sic_profile_id>_<region_id>
- this is used by the SIC system to identify the server and register it. The <region_id> field suffix is the region the server will provide service for.-rhpublichost=<hostname_or_ip_for_connections>
- this is the hostname or IP address that clients will use to connect to the server. If not provided, it will use the local machine hostname.
Most developer environments have regions 100-200 preconfigured as developer regions.
Running in AutoCreate mode
This method is used to test the Self-Hosted Allocation Flow With Fallback Timeout
To run in this mode, use the following
-rhbootstrapmode=AutoCreate
- this informs the library that it will be running in AutoCreate mode