Skip to content

Instantly share code, notes, and snippets.

@anuar2k
Created October 4, 2018 13:46
Show Gist options
  • Save anuar2k/5048c509450b3d9ec35aef105e2b6102 to your computer and use it in GitHub Desktop.
Save anuar2k/5048c509450b3d9ec35aef105e2b6102 to your computer and use it in GitHub Desktop.
Telemetry
#define WINVER 0x0500
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include "scssdk_telemetry.h"
#include "eurotrucks2/scssdk_eut2.h"
#include "eurotrucks2/scssdk_telemetry_eut2.h"
#include "amtrucks/scssdk_ats.h"
#include "amtrucks/scssdk_telemetry_ats.h"
#define PLUGIN_VERSION 1;
#define UNUSED(x)
scs_telemetry_register_for_channel_t register_for_channel = NULL;
scs_telemetry_unregister_from_channel_t unregister_from_channel = NULL;
scs_log_t game_log = NULL;
void log_line(const scs_log_type_t type, const char *const text, ...) {
if (!game_log) {
return;
}
char formated[1000];
va_list args;
va_start(args, text);
vsnprintf_s(formated, sizeof(formated), _TRUNCATE, text, args);
formated[sizeof(formated) - 1] = 0;
va_end(args);
game_log(type, formated);
}
#pragma region Array size constants
const scs_u32_t TRUCK_WHEEL_COUNT = 8;
const scs_u32_t TRAILER_WHEEL_COUNT = 16;
const scs_u32_t FWD_GEAR_COUNT = 32;
const scs_u32_t RVS_GEAR_COUNT = 16;
const scs_u32_t STR_LEN = 64;
#pragma endregion
#pragma pack(push)
#pragma pack(1)
struct telemetry_state_t {
//>>>>>
//HEAD
//
//basic information about the structure
//>>>>>
scs_u32_t plugin_version;
scs_u32_t game;
scs_u32_t sdk_version;
scs_u8_t paused;
//>>>>>
//CHANNELS
//
//updated with every physics engine frame
//>>>>>
scs_float_t g_local_scale;
scs_u32_t g_game_time;
scs_s32_t g_next_rest_stop;
//truck:
scs_value_dplacement_t t_world_placement;
scs_value_fvector_t t_local_linear_velocity;
scs_value_fvector_t t_local_angular_velocity;
scs_value_fvector_t t_local_linear_acceleration;
scs_value_fvector_t t_local_angular_acceleration;
scs_value_fplacement_t t_cabin_offset;
scs_value_fvector_t t_cabin_angular_velocity;
scs_value_fvector_t t_cabin_angular_acceleration;
scs_value_fplacement_t t_head_offset;
scs_float_t t_speed;
scs_float_t t_engine_rpm;
scs_s32_t t_engine_gear;
scs_s32_t t_displayed_gear;
scs_float_t t_input_steering;
scs_float_t t_input_throttle;
scs_float_t t_input_brake;
scs_float_t t_input_clutch;
scs_float_t t_effective_steering;
scs_float_t t_effective_throttle;
scs_float_t t_effective_brake;
scs_float_t t_effective_clutch;
scs_float_t t_cruise_control;
scs_u32_t t_hshifter_slot;
scs_u8_t t_parking_brake;
scs_u8_t t_motor_brake;
scs_u32_t t_retarder_level;
scs_float_t t_brake_air_pressure;
scs_u8_t t_brake_air_pressure_warning;
scs_u8_t t_brake_air_pressure_emergency;
scs_float_t t_brake_temperature;
scs_float_t t_fuel;
scs_u8_t t_fuel_warning;
scs_float_t t_fuel_average_consumption;
scs_float_t t_fuel_range;
scs_float_t t_adblue;
scs_u8_t t_adblue_warning;
scs_float_t t_adblue_average_consumption;
scs_float_t t_oil_pressure;
scs_u8_t t_oil_pressure_warning;
scs_float_t t_oil_temperature;
scs_float_t t_water_temperature;
scs_u8_t t_water_temperature_warning;
scs_float_t t_battery_voltage;
scs_u8_t t_battery_voltage_warning;
scs_u8_t t_electric_enabled;
scs_u8_t t_engine_enabled;
scs_u8_t t_lblinker;
scs_u8_t t_rblinker;
scs_u8_t t_light_lblinker;
scs_u8_t t_light_rblinker;
scs_u8_t t_light_parking;
scs_u8_t t_light_low_beam;
scs_u8_t t_light_high_beam;
scs_u32_t t_light_aux_front;
scs_u32_t t_light_aux_roof;
scs_u8_t t_light_beacon;
scs_u8_t t_light_brake;
scs_u8_t t_light_reverse;
scs_u8_t t_wipers;
scs_float_t t_dashboard_backlight;
scs_float_t t_wear_engine;
scs_float_t t_wear_transmission;
scs_float_t t_wear_cabin;
scs_float_t t_wear_chassis;
scs_float_t t_wear_wheels;
scs_float_t t_odometer;
scs_float_t t_navigation_distance;
scs_float_t t_navigation_time;
scs_float_t t_navigation_speed_limit;
scs_float_t t_wheel_susp_deflection[TRUCK_WHEEL_COUNT];
scs_u8_t t_wheel_on_ground[TRUCK_WHEEL_COUNT];
scs_float_t t_wheel_velocity[TRUCK_WHEEL_COUNT];
scs_float_t t_wheel_steering[TRUCK_WHEEL_COUNT];
scs_float_t t_wheel_rotation[TRUCK_WHEEL_COUNT];
scs_float_t t_wheel_lift[TRUCK_WHEEL_COUNT];
scs_float_t t_wheel_lift_offset[TRUCK_WHEEL_COUNT];
//trailer:
scs_u8_t r_connected;
scs_value_dplacement_t r_world_placement;
scs_value_fvector_t r_local_linear_velocity;
scs_value_fvector_t r_local_angular_velocity;
scs_value_fvector_t r_local_linear_acceleration;
scs_value_fvector_t r_local_angular_acceleration;
scs_float_t r_wear_chassis;
scs_float_t r_wheel_susp_deflection[TRAILER_WHEEL_COUNT];
scs_u8_t r_wheel_on_ground[TRAILER_WHEEL_COUNT];
scs_float_t r_wheel_velocity[TRAILER_WHEEL_COUNT];
scs_float_t r_wheel_steering[TRAILER_WHEEL_COUNT];
scs_float_t r_wheel_rotation[TRAILER_WHEEL_COUNT];
//>>>>>
//CONFIGURATION DATA
//
//updated with every configation change event call
//>>>>>
//indicators
//incremented whenever truck/trailer/job dataset changes to notify the receiver, set to 0 if no data is available
scs_u8_t truck;
scs_u8_t trailer;
scs_u8_t job;
//truck:
struct {
char ct_brand_id[STR_LEN];
char ct_brand[STR_LEN];
char ct_id[STR_LEN];
char ct_name[STR_LEN];
scs_float_t ct_fuel_capacity;
scs_float_t ct_fuel_warning_factor;
scs_float_t ct_adblue_capacity;
scs_float_t ct_adblue_warning_factor;
scs_float_t ct_air_pressure_warning;
scs_float_t ct_air_pressure_emergency;
scs_float_t ct_oil_pressure_warning;
scs_float_t ct_water_temperature_warning;
scs_float_t ct_battery_voltage_warning;
scs_float_t ct_rpm_limit;
scs_u32_t ct_forward_gear_count;
scs_u32_t ct_reverse_gear_count;
scs_float_t ct_differential_ratio;
scs_u32_t ct_retarder_step_count;
scs_value_fvector_t ct_cabin_position;
scs_value_fvector_t ct_head_position;
scs_value_fvector_t ct_hook_position;
scs_u32_t ct_wheel_count;
scs_value_fvector_t ct_wheel_position[TRUCK_WHEEL_COUNT];
scs_u8_t ct_wheel_steerable[TRUCK_WHEEL_COUNT];
scs_u8_t ct_wheel_simulated[TRUCK_WHEEL_COUNT];
scs_float_t ct_wheel_radius[TRUCK_WHEEL_COUNT];
scs_u8_t ct_wheel_powered[TRUCK_WHEEL_COUNT];
scs_u8_t ct_wheel_liftable[TRUCK_WHEEL_COUNT];
scs_float_t ct_forward_ratio[FWD_GEAR_COUNT];
scs_float_t ct_reverse_ratio[RVS_GEAR_COUNT];
} truck_conf;
//trailer:
struct {
char cr_id[STR_LEN];
char cr_cargo_accessory_id[STR_LEN];
scs_value_fvector_t cr_hook_position;
scs_u32_t cr_wheel_count;
scs_value_fvector_t cr_wheel_position[TRAILER_WHEEL_COUNT];
scs_u8_t cr_wheel_steerable[TRAILER_WHEEL_COUNT];
scs_u8_t cr_wheel_simulated[TRAILER_WHEEL_COUNT];
scs_float_t cr_wheel_radius[TRAILER_WHEEL_COUNT];
scs_u8_t cr_wheel_powered[TRAILER_WHEEL_COUNT];
scs_u8_t cr_wheel_liftable[TRAILER_WHEEL_COUNT];
} trailer_conf;
//job:
struct {
char cj_cargo_id[STR_LEN];
char cj_cargo[STR_LEN];
float cj_cargo_mass;
char cj_destination_city_id[STR_LEN];
char cj_destination_city[STR_LEN];
char cj_destination_company_id[STR_LEN];
char cj_destination_company[STR_LEN];
char cj_source_city_id[STR_LEN];
char cj_source_city[STR_LEN];
char cj_source_company_id[STR_LEN];
char cj_source_company[STR_LEN];
scs_u64_t cj_income;
scs_u32_t cj_delivery_time;
} job_conf;
};
const DWORD STRUCT_SIZE = sizeof(telemetry_state_t);
const DWORD TRUCK_CONF_SIZE = sizeof(telemetry_state_t::truck_conf);
const DWORD TRAILER_CONF_SIZE = sizeof(telemetry_state_t::trailer_conf);
const DWORD JOB_CONF_SIZE = sizeof(telemetry_state_t::job_conf);
#pragma pack(pop)
HANDLE memory_mapping = NULL;
telemetry_state_t *shared_memory = NULL;
const DWORD off = offsetof(telemetry_state_t, job_conf.cj_source_company_id);
void deinitialize_shared_memory(void) {
if (shared_memory) {
UnmapViewOfFile(shared_memory);
shared_memory = NULL;
}
if (memory_mapping) {
CloseHandle(memory_mapping);
memory_mapping = NULL;
}
}
bool initialize_shared_memory(scs_u8_t game_id, scs_u32_t sdk_ver) {
memory_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, STRUCT_SIZE, "Local\\YATTS_MMF");
if (!memory_mapping) {
log_line(SCS_LOG_TYPE_error, "Unable to create shared memory %08X", GetLastError());
deinitialize_shared_memory();
return false;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
log_line(SCS_LOG_TYPE_error, "Shared memory is already in use.");
}
shared_memory = static_cast<telemetry_state_t *>(MapViewOfFile(memory_mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
if (!shared_memory) {
log_line(SCS_LOG_TYPE_error, "Unable to map the view %08X", GetLastError());
deinitialize_shared_memory();
return false;
}
memset(shared_memory, 0, STRUCT_SIZE);
shared_memory->plugin_version = PLUGIN_VERSION;
shared_memory->game = game_id;
shared_memory->sdk_version = sdk_ver;
shared_memory->paused = 1;
return true;
}
#pragma region Value storage callbacks
SCSAPI_VOID telemetry_store_bool(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_u8_t *const storage = static_cast<scs_u8_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_bool);
*storage = value->value_bool.value;
} else {
*storage = 0;
}
}
SCSAPI_VOID telemetry_store_float(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_float_t *const storage = static_cast<scs_float_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_float);
*storage = value->value_float.value;
} else {
*storage = 0.0f;
}
}
SCSAPI_VOID telemetry_store_u32(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_u32_t *const storage = static_cast<scs_u32_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_u32);
*storage = value->value_u32.value;
} else {
*storage = 0;
}
}
SCSAPI_VOID telemetry_store_s32(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_s32_t *const storage = static_cast<scs_s32_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_s32);
*storage = value->value_s32.value;
} else {
*storage = 0;
}
}
SCSAPI_VOID telemetry_store_u64(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_u64_t *const storage = static_cast<scs_u64_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_u64);
*storage = value->value_u64.value;
} else {
*storage = 0;
}
}
SCSAPI_VOID telemetry_store_orientation(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_value_euler_t *const storage = static_cast<scs_value_euler_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_euler);
*storage = value->value_euler;
} else {
storage->heading = 0.0f;
storage->pitch = 0.0f;
storage->roll = 0.0f;
}
}
SCSAPI_VOID telemetry_store_fvector(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_value_fvector_t *const storage = static_cast<scs_value_fvector_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_fvector);
*storage = value->value_fvector;
} else {
storage->x = 0.0f;
storage->y = 0.0f;
storage->z = 0.0f;
}
}
SCSAPI_VOID telemetry_store_fplacement(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_value_fplacement_t *const storage = static_cast<scs_value_fplacement_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_fplacement);
*storage = value->value_fplacement;
} else {
storage->position.x = 0.0;
storage->position.y = 0.0;
storage->position.z = 0.0;
storage->orientation.heading = 0.0f;
storage->orientation.pitch = 0.0f;
storage->orientation.roll = 0.0f;
}
}
SCSAPI_VOID telemetry_store_dplacement(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
scs_value_dplacement_t *const storage = static_cast<scs_value_dplacement_t *>(context);
if (value) {
assert(value->type == SCS_VALUE_TYPE_dplacement);
*storage = value->value_dplacement;
} else {
storage->position.x = 0.0;
storage->position.y = 0.0;
storage->position.z = 0.0;
storage->orientation.heading = 0.0f;
storage->orientation.pitch = 0.0f;
storage->orientation.roll = 0.0f;
}
}
SCSAPI_VOID telemetry_store_string(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context) {
assert(context);
char *const storage = static_cast<char *>(context);
memset(storage, 0, STR_LEN);
if (value) {
assert(value->type == SCS_VALUE_TYPE_string);
strncpy(storage, value->value_string.value, STR_LEN-1);
}
}
#pragma endregion
const scs_named_value_t *find_attribute(const scs_telemetry_configuration_t &configuration, const char *const name, const scs_u32_t index, const scs_value_type_t expected_type) {
for (const scs_named_value_t *current = configuration.attributes; current->name; ++current) {
if ((current->index != index) || (strcmp(current->name, name) != 0)) {
continue;
}
if (current->value.type == expected_type) {
return current;
}
log_line(SCS_LOG_TYPE_error, "Attribute %s has unexpected type %u", name, static_cast<unsigned>(current->value.type));
break;
}
return NULL;
}
void store_attribute(const scs_telemetry_configuration_t *const configuration, const char *const name, const scs_u32_t index, const scs_value_type_t expected_type, const scs_context_t context) {
const scs_named_value_t *const attribute = find_attribute(*configuration, name, index, expected_type);
const scs_value_t *const val = &attribute->value;
switch (expected_type) {
case SCS_VALUE_TYPE_bool:
telemetry_store_bool(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_s32:
telemetry_store_s32(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_u32:
telemetry_store_u32(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_u64:
telemetry_store_u64(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_float:
telemetry_store_float(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_fvector:
telemetry_store_fvector(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_dplacement:
telemetry_store_dplacement(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
case SCS_VALUE_TYPE_string:
telemetry_store_string(name, SCS_U32_NIL, attribute != NULL ? val : 0, context);
break;
}
}
SCSAPI_VOID telemetry_pause(const scs_event_t event, const void *const UNUSED(event_info), const scs_context_t UNUSED(context)) {
shared_memory->paused = (event == SCS_TELEMETRY_EVENT_started) ? 0 : 1;
}
void iterate_config(const scs_telemetry_configuration_t &configuration) {
log_line(SCS_LOG_TYPE_message, ">>>>>");
log_line(SCS_LOG_TYPE_message, "Config ID: %s", configuration.id);
log_line(SCS_LOG_TYPE_message, ">>>>>");
for (const scs_named_value_t *current = configuration.attributes; current->name; ++current) {
log_line(SCS_LOG_TYPE_message, "Attribute ID: %s, index: %u", current->name, current->index);
}
}
SCSAPI_VOID telemetry_configuration(const scs_event_t event, const void *const event_info, const scs_context_t UNUSED(context)) {
const struct scs_telemetry_configuration_t *const info = static_cast<const scs_telemetry_configuration_t *>(event_info);
iterate_config(*info);
#define store_attr(name, type, field) store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_##name, SCS_U32_NIL, SCS_VALUE_TYPE_##type, field);
#define store_truck_attr(name, type) store_attr(name, type, &shared_memory->truck_conf.ct_##name);
#define store_trailer_attr(name, type) store_attr(name, type, &shared_memory->trailer_conf.cr_##name);
#define store_job_attr(name, type) store_attr(name, type, &shared_memory->job_conf.cj_##name);
if (strcmp(info->id, SCS_TELEMETRY_CONFIG_truck) == 0) {
//TODO: przerobić rejestrowanie/odrejestrowanie lift i lift_offset
scs_u32_t wheel_count = 0;
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_count, SCS_U32_NIL, SCS_VALUE_TYPE_u32, &wheel_count);
while (shared_memory->truck_conf.ct_wheel_count < wheel_count) {
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_position, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_fvector, &shared_memory->truck_conf.ct_wheel_position[shared_memory->truck_conf.ct_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_steerable, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->truck_conf.ct_wheel_steerable[shared_memory->truck_conf.ct_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_simulated, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->truck_conf.ct_wheel_simulated[shared_memory->truck_conf.ct_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_radius, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, &shared_memory->truck_conf.ct_wheel_radius[shared_memory->truck_conf.ct_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_powered, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->truck_conf.ct_wheel_powered[shared_memory->truck_conf.ct_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_liftable, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->truck_conf.ct_wheel_liftable[shared_memory->truck_conf.ct_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_susp_deflection, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->t_wheel_susp_deflection[shared_memory->truck_conf.ct_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_on_ground, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_bool, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_bool, &shared_memory->t_wheel_on_ground[shared_memory->truck_conf.ct_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_velocity, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->t_wheel_velocity[shared_memory->truck_conf.ct_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_steering, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->t_wheel_steering[shared_memory->truck_conf.ct_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_rotation, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->t_wheel_rotation[shared_memory->truck_conf.ct_wheel_count]);
if (shared_memory->truck_conf.ct_wheel_liftable[shared_memory->truck_conf.ct_wheel_count]) {
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_lift, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->t_wheel_lift[shared_memory->truck_conf.ct_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_lift_offset, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->t_wheel_lift_offset[shared_memory->truck_conf.ct_wheel_count]);
}
++shared_memory->truck_conf.ct_wheel_count;
}
while (shared_memory->truck_conf.ct_wheel_count > wheel_count) {
--shared_memory->truck_conf.ct_wheel_count;
shared_memory->truck_conf.ct_wheel_position[shared_memory->truck_conf.ct_wheel_count].x = 0;
shared_memory->truck_conf.ct_wheel_position[shared_memory->truck_conf.ct_wheel_count].y = 0;
shared_memory->truck_conf.ct_wheel_position[shared_memory->truck_conf.ct_wheel_count].z = 0;
shared_memory->truck_conf.ct_wheel_steerable[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->truck_conf.ct_wheel_simulated[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->truck_conf.ct_wheel_radius[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->truck_conf.ct_wheel_powered[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->truck_conf.ct_wheel_liftable[shared_memory->truck_conf.ct_wheel_count] = 0;
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_susp_deflection, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_on_ground, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_bool);
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_velocity, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_steering, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_rotation, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_lift, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRUCK_CHANNEL_wheel_lift_offset, shared_memory->truck_conf.ct_wheel_count, SCS_VALUE_TYPE_float);
shared_memory->t_wheel_susp_deflection[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->t_wheel_on_ground[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->t_wheel_velocity[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->t_wheel_steering[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->t_wheel_rotation[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->t_wheel_lift[shared_memory->truck_conf.ct_wheel_count] = 0;
shared_memory->t_wheel_lift_offset[shared_memory->truck_conf.ct_wheel_count] = 0;
}
if (info->attributes->name) {
store_truck_attr(brand_id, string);
store_truck_attr(brand, string);
store_truck_attr(id, string);
store_truck_attr(name, string);
store_truck_attr(fuel_capacity, float);
store_truck_attr(fuel_warning_factor, float);
store_truck_attr(adblue_capacity, float);
store_truck_attr(adblue_warning_factor, float);
store_truck_attr(air_pressure_warning, float);
store_truck_attr(air_pressure_emergency, float);
store_truck_attr(oil_pressure_warning, float);
store_truck_attr(water_temperature_warning, float);
store_truck_attr(battery_voltage_warning, float);
store_truck_attr(rpm_limit, float);
store_truck_attr(differential_ratio, float);
store_truck_attr(retarder_step_count, u32);
store_truck_attr(cabin_position, fvector);
store_truck_attr(head_position, fvector);
store_truck_attr(hook_position, fvector);
store_truck_attr(forward_gear_count, u32);
if (shared_memory->truck_conf.ct_forward_gear_count > FWD_GEAR_COUNT) {
shared_memory->truck_conf.ct_forward_gear_count = FWD_GEAR_COUNT;
}
for (scs_u32_t i = 0; i < FWD_GEAR_COUNT; ++i) {
if (i < shared_memory->truck_conf.ct_forward_gear_count) {
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_forward_ratio, i, SCS_VALUE_TYPE_float, &shared_memory->truck_conf.ct_forward_ratio[i]);
} else {
shared_memory->truck_conf.ct_forward_ratio[i] = 0;
}
}
store_truck_attr(reverse_gear_count, u32);
if (shared_memory->truck_conf.ct_reverse_gear_count > RVS_GEAR_COUNT) {
shared_memory->truck_conf.ct_reverse_gear_count = RVS_GEAR_COUNT;
}
for (scs_u32_t i = 0; i < RVS_GEAR_COUNT; ++i) {
if (i < shared_memory->truck_conf.ct_reverse_gear_count) {
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_reverse_ratio, i, SCS_VALUE_TYPE_float, &shared_memory->truck_conf.ct_reverse_ratio[i]);
} else {
shared_memory->truck_conf.ct_reverse_ratio[i] = 0;
}
}
shared_memory->truck++;
if (shared_memory->truck == 0) {
shared_memory->truck = 1;
}
} else {
shared_memory->truck = 0;
memset(&shared_memory->truck_conf, 0, TRUCK_CONF_SIZE);
}
}
if (strcmp(info->id, SCS_TELEMETRY_CONFIG_trailer) == 0) {
scs_u32_t wheel_count = 0;
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_count, SCS_U32_NIL, SCS_VALUE_TYPE_u32, &wheel_count);
while (shared_memory->trailer_conf.cr_wheel_count < wheel_count) {
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_position, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_fvector, &shared_memory->trailer_conf.cr_wheel_position[shared_memory->trailer_conf.cr_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_steerable, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->trailer_conf.cr_wheel_steerable[shared_memory->trailer_conf.cr_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_simulated, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->trailer_conf.cr_wheel_simulated[shared_memory->trailer_conf.cr_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_radius, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float, &shared_memory->trailer_conf.cr_wheel_radius[shared_memory->trailer_conf.cr_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_powered, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->trailer_conf.cr_wheel_powered[shared_memory->trailer_conf.cr_wheel_count]);
store_attribute(info, SCS_TELEMETRY_CONFIG_ATTRIBUTE_wheel_liftable, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_bool, &shared_memory->trailer_conf.cr_wheel_liftable[shared_memory->trailer_conf.cr_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_susp_deflection, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->r_wheel_susp_deflection[shared_memory->trailer_conf.cr_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_on_ground, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_bool, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_bool, &shared_memory->r_wheel_on_ground[shared_memory->trailer_conf.cr_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_velocity, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->r_wheel_velocity[shared_memory->trailer_conf.cr_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_steering, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->r_wheel_steering[shared_memory->trailer_conf.cr_wheel_count]);
register_for_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_rotation, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_float, &shared_memory->r_wheel_rotation[shared_memory->trailer_conf.cr_wheel_count]);
++shared_memory->trailer_conf.cr_wheel_count;
}
while (shared_memory->trailer_conf.cr_wheel_count > wheel_count) {
--shared_memory->trailer_conf.cr_wheel_count;
shared_memory->trailer_conf.cr_wheel_position[shared_memory->trailer_conf.cr_wheel_count].x = 0;
shared_memory->trailer_conf.cr_wheel_position[shared_memory->trailer_conf.cr_wheel_count].y = 0;
shared_memory->trailer_conf.cr_wheel_position[shared_memory->trailer_conf.cr_wheel_count].z = 0;
shared_memory->trailer_conf.cr_wheel_steerable[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->trailer_conf.cr_wheel_simulated[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->trailer_conf.cr_wheel_radius[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->trailer_conf.cr_wheel_powered[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->trailer_conf.cr_wheel_liftable[shared_memory->trailer_conf.cr_wheel_count] = 0;
unregister_from_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_susp_deflection, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_on_ground, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_bool);
unregister_from_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_velocity, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_steering, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float);
unregister_from_channel(SCS_TELEMETRY_TRAILER_CHANNEL_wheel_rotation, shared_memory->trailer_conf.cr_wheel_count, SCS_VALUE_TYPE_float);
shared_memory->r_wheel_susp_deflection[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->r_wheel_on_ground[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->r_wheel_velocity[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->r_wheel_steering[shared_memory->trailer_conf.cr_wheel_count] = 0;
shared_memory->r_wheel_rotation[shared_memory->trailer_conf.cr_wheel_count] = 0;
}
if (info->attributes->name) {
store_trailer_attr(id, string);
store_trailer_attr(cargo_accessory_id, string);
store_trailer_attr(hook_position, fvector);
shared_memory->trailer++;
if (shared_memory->trailer == 0) {
shared_memory->trailer = 1;
}
} else {
shared_memory->trailer = 0;
memset(&shared_memory->trailer_conf, 0, TRAILER_CONF_SIZE);
}
}
if (strcmp(info->id, SCS_TELEMETRY_CONFIG_job) == 0) {
if (info->attributes->name) {
store_job_attr(cargo_id, string);
store_job_attr(cargo, string);
store_job_attr(cargo_mass, float);
store_job_attr(destination_city_id, string);
store_job_attr(destination_city, string);
store_job_attr(destination_company_id, string);
store_job_attr(destination_company, string);
store_job_attr(source_city_id, string);
store_job_attr(source_city, string);
store_job_attr(source_company_id, string);
store_job_attr(source_company, string);
store_job_attr(income, u64);
store_job_attr(delivery_time, u32);
shared_memory->job++;
if (shared_memory->job == 0) {
shared_memory->job = 1;
}
} else {
shared_memory->job = 0;
memset(&shared_memory->job_conf, 0, JOB_CONF_SIZE);
}
}
#undef store_job_attr
#undef store_trailer_attr
#undef store_truck_attr
#undef store_attr
}
SCSAPI_RESULT scs_telemetry_init(const scs_u32_t version, const scs_telemetry_init_params_t *const params) {
if (version != SCS_TELEMETRY_VERSION_1_00) {
return SCS_RESULT_unsupported;
}
const scs_telemetry_init_params_v100_t *const version_params = static_cast<const scs_telemetry_init_params_v100_t *>(params);
game_log = version_params->common.log;
log_line(SCS_LOG_TYPE_message, "YATTS 0.10");
log_line(SCS_LOG_TYPE_message, "Game: '%s' %u.%u", version_params->common.game_id, SCS_GET_MAJOR_VERSION(version_params->common.game_version), SCS_GET_MINOR_VERSION(version_params->common.game_version));
scs_u8_t game_id = 0;
if (strcmp(version_params->common.game_id, SCS_GAME_ID_EUT2) == 0) {
const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_CURRENT;
game_id = 1;
if (version_params->common.game_version < IMPLEMENTED_VERSION) {
log_line(SCS_LOG_TYPE_error, "TELEMETRY PLUGIN INIT FAILED: Too old version of the game; update your game or downgrade the plugin (if available)");
game_log = NULL;
return SCS_RESULT_unsupported;
}
if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
log_line(SCS_LOG_TYPE_warning, "Too new major version of the game, some features might behave incorrectly");
}
} else if (strcmp(version_params->common.game_id, SCS_GAME_ID_ATS) == 0) {
const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_ATS_GAME_VERSION_CURRENT;
game_id = 2;
if (version_params->common.game_version < IMPLEMENTED_VERSION) {
log_line(SCS_LOG_TYPE_error, "TELEMETRY PLUGIN INIT FAILED: Too old version of the game; update your game or downgrade the plugin (if available)");
game_log = NULL;
return SCS_RESULT_unsupported;
}
if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
log_line(SCS_LOG_TYPE_warning, "Too new major version of the game, some features might behave incorrectly");
}
} else {
log_line(SCS_LOG_TYPE_warning, "TELEMETRY PLUGIN INIT FAILED: Game not recognized");
game_log = NULL;
return SCS_RESULT_unsupported;
}
const bool events_registered =
(version_params->register_for_event(SCS_TELEMETRY_EVENT_paused, telemetry_pause, NULL) == SCS_RESULT_ok) &&
(version_params->register_for_event(SCS_TELEMETRY_EVENT_started, telemetry_pause, NULL) == SCS_RESULT_ok) &&
(version_params->register_for_event(SCS_TELEMETRY_EVENT_configuration, telemetry_configuration, NULL) == SCS_RESULT_ok)
;
if (!events_registered) {
log_line(SCS_LOG_TYPE_error, "Unable to register event callbacks");
game_log = NULL;
return SCS_RESULT_generic_error;
}
if (!initialize_shared_memory(game_id, version_params->common.game_version)) {
log_line(SCS_LOG_TYPE_error, "Unable to initialize shared memory");
game_log = NULL;
return SCS_RESULT_generic_error;
}
#define reg_chan(name, type, field) version_params->register_for_channel(SCS_TELEMETRY_##name, SCS_U32_NIL, SCS_VALUE_TYPE_##type, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_##type, &shared_memory->field);
#define reg_common_chan(name, type) reg_chan(CHANNEL_##name, type, g_##name)
#define reg_truck_chan(name, type) reg_chan(TRUCK_CHANNEL_##name, type, t_##name);
#define reg_trailer_chan(name, type) reg_chan(TRAILER_CHANNEL_##name, type, r_##name);
reg_common_chan(local_scale, float);
reg_common_chan(game_time, u32);
reg_common_chan(next_rest_stop, s32);
reg_truck_chan(world_placement, dplacement);
reg_truck_chan(local_linear_velocity, fvector);
reg_truck_chan(local_angular_velocity, fvector);
reg_truck_chan(local_linear_acceleration, fvector);
reg_truck_chan(local_angular_acceleration, fvector);
reg_truck_chan(cabin_offset, fplacement);
reg_truck_chan(cabin_angular_velocity, fvector);
reg_truck_chan(cabin_angular_acceleration, fvector);
reg_truck_chan(head_offset, fplacement);
reg_truck_chan(speed, float);
reg_truck_chan(engine_rpm, float);
reg_truck_chan(engine_gear, s32);
reg_truck_chan(displayed_gear, s32);
reg_truck_chan(input_steering, float);
reg_truck_chan(input_throttle, float);
reg_truck_chan(input_brake, float);
reg_truck_chan(input_clutch, float);
reg_truck_chan(effective_steering, float);
reg_truck_chan(effective_throttle, float);
reg_truck_chan(effective_brake, float);
reg_truck_chan(effective_clutch, float);
reg_truck_chan(cruise_control, float);
reg_truck_chan(hshifter_slot, u32);
reg_truck_chan(parking_brake, bool);
reg_truck_chan(motor_brake, bool);
reg_truck_chan(retarder_level, u32);
reg_truck_chan(brake_air_pressure, float);
reg_truck_chan(brake_air_pressure_warning, bool);
reg_truck_chan(brake_air_pressure_emergency, bool);
reg_truck_chan(brake_temperature, float);
reg_truck_chan(fuel, float);
reg_truck_chan(fuel_warning, bool);
reg_truck_chan(fuel_range, float);
reg_truck_chan(adblue, float);
reg_truck_chan(adblue_warning, bool);
reg_truck_chan(adblue_average_consumption, float);
reg_truck_chan(oil_pressure, float);
reg_truck_chan(oil_pressure_warning, bool);
reg_truck_chan(oil_temperature, float);
reg_truck_chan(water_temperature, float);
reg_truck_chan(water_temperature_warning, bool);
reg_truck_chan(battery_voltage, float);
reg_truck_chan(battery_voltage_warning, bool);
reg_truck_chan(electric_enabled, bool);
reg_truck_chan(engine_enabled, bool);
reg_truck_chan(lblinker, bool);
reg_truck_chan(rblinker, bool);
reg_truck_chan(light_lblinker, bool);
reg_truck_chan(light_rblinker, bool);
reg_truck_chan(light_parking, bool);
reg_truck_chan(light_low_beam, bool);
reg_truck_chan(light_high_beam, bool);
reg_truck_chan(light_aux_front, u32);
reg_truck_chan(light_aux_roof, u32);
reg_truck_chan(light_beacon, bool);
reg_truck_chan(light_brake, bool);
reg_truck_chan(light_reverse, bool);
reg_truck_chan(wipers, bool);
reg_truck_chan(dashboard_backlight, float);
reg_truck_chan(wear_engine, float);
reg_truck_chan(wear_transmission, float);
reg_truck_chan(wear_cabin, float);
reg_truck_chan(wear_chassis, float);
reg_truck_chan(wear_wheels, float);
reg_truck_chan(odometer, float);
reg_truck_chan(navigation_distance, float);
reg_truck_chan(navigation_time, float);
reg_truck_chan(navigation_speed_limit, float);
reg_trailer_chan(connected, bool);
reg_trailer_chan(world_placement, dplacement);
reg_trailer_chan(local_linear_velocity, fvector);
reg_trailer_chan(local_angular_velocity, fvector);
reg_trailer_chan(local_linear_acceleration, fvector);
reg_trailer_chan(local_angular_acceleration, fvector);
reg_trailer_chan(wear_chassis, float);
#undef reg_trailer_chan
#undef reg_truck_chan
#undef reg_common_chan
#undef reg_chan
register_for_channel = version_params->register_for_channel;
unregister_from_channel = version_params->unregister_from_channel;
log_line(SCS_LOG_TYPE_message, "Memory telemetry example initialized");
return SCS_RESULT_ok;
}
SCSAPI_VOID scs_telemetry_shutdown(void) {
deinitialize_shared_memory();
unregister_from_channel = NULL;
register_for_channel = NULL;
game_log = NULL;
}
BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, LPVOID reseved) {
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment