Game Host Adapter
The GameHostAdapter library is a utility library used to help bootstrap dedicated server allocations across multiple vendors. It is a required part of the integration in order to utilize our server allocation scheme.
The library is publicly available on Github at https://github.com/RallyHereInteractive/game-host-adapter, with the most recent release being at https://github.com/RallyHereInteractive/game-host-adapter/releases/latest.
NOTE: A version of the library comes pre-integrated into the Unreal Integration plugins. We suggest referencing it as an example integration.
C/C++ Library
To integrate the library, you will need the files from the include/game-host-adapter
folder in the Github release, plus the library binaries. Note that the Windows binaries package has some additional libraries required to run, that are also included.
The adapter is provided as a dynamic library to be loaded. A static wrapping library may be provided in future releases or for specific platforms.
Library API
When including the library, you should only need to include c_api.h
, which should include the other files. This file defines a set of C functions that can be looked up and bound after the library is loaded.
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
The dynamic library can be loaded through standard means. However, if your program includes OpenSSL and is running on Linux, we recommend using the (RTLD_LAZY | RTLD_DEEPBIND)
flags when loading it to prevent conflicts.
Once the library is loaded and functions bound, it must be initialized by calling rallyhere_global_init()
. Before unloading the library, you must call rallyhere_global_cleanup()
.
Note that for fleet maintainance and extensibility reasons, we require that the library path be able to be overridden by -gamehostadapterlibpath=<path>
on the commandline. This allows us to deploy updates to the library without needing to know your program’s folder structure.
Creating an Adapter Context
To utilize the library, you will need to create an adapter context object once the library is loaded and initialized. This can be done by calling one of the following functions:
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 n
variants of the function allows for an arguments_length
to be specified.
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.
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_healthy
function must be called routinely (every frame is fine, but at least once every few seconds), as it informs the adapter layer that the server is still in a healthy state.
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:
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.
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
Using the Unreal Integration
Information on utilizing the pre-integrated implementation of Game Host Adapter in the Unreal Integration can be found at the Unreal Integration Dedicated Server Bootstrapping documentation