Unify config loading in net and video subsystems.feature/data-structs
@@ -65,29 +65,44 @@ void IZ_AppTeardown(struct IZ_App* app) { | |||
SDL_Quit(); | |||
} | |||
void IZ_AppPrintHelpOptions() { | |||
printf("\n"); | |||
printf("Options:\n"); | |||
printf("\n"); | |||
printf( | |||
"\n" | |||
"Options:\n" | |||
"\n" | |||
" -c <path> Specifies the path to the config file. (default: \"./config-game.ini\")\n" | |||
" -f <value> Specifies the frames per second. (default: 30)\n" | |||
" -h Displays this help screen.\n" | |||
" -i <value> Specifies the interval of sending packets (default: 200)\n" | |||
" in milliseconds.\n" | |||
); | |||
} | |||
void IZ_AppPrintHelpUsage() { | |||
printf("\n"); | |||
printf("Usage:"); | |||
printf(" %s [options]\n", "game.exe"); | |||
} | |||
void IZ_AppPrintHelpHeader() { | |||
printf("\n"); | |||
printf("%s - %s\n", IZ_APP_NAME, IZ_APP_DESCRIPTION); | |||
} | |||
void IZ_AppPrintHelp() { | |||
IZ_AppPrintHelpHeader(); | |||
IZ_AppPrintHelpUsage(); | |||
IZ_AppPrintHelpOptions(); | |||
} | |||
IZ_ProcedureResult IZ_AppRun(struct IZ_App* app, u8 argc, const char* argv[]) { | |||
// TODO have a config subsystem that handles these. | |||
if (IZ_ConfigGetCommandlineOption(argc, argv, "-h")) { | |||
printf( | |||
( | |||
"\n" | |||
"%s - %s\n" | |||
"\n" | |||
"Usage:\n" | |||
"\n" | |||
" %s [options]\n" | |||
"\n" | |||
"Options:\n" | |||
"\n" | |||
" -c <path> Specifies the path to the config file. (default: \"./config-game.ini\")\n" | |||
" -f <value> Specifies the frames per second. (default: 30)\n" | |||
" -h Displays this help file.\n" | |||
" -i <value> Specifies the interval of sending packets (default: 200)\n" | |||
" in milliseconds.\n" | |||
), | |||
IZ_APP_NAME, | |||
IZ_APP_DESCRIPTION, | |||
"game.exe" | |||
); | |||
IZ_AppPrintHelp(); | |||
return IZ_APP_RUN_RESULT_OK; | |||
} | |||
@@ -33,3 +33,238 @@ const char* IZ_ConfigGetCommandlineOption(u8 argc, const char* argv[], const cha | |||
return NULL; | |||
} | |||
typedef bool IZ_ConfigLoadParamsStringValidator(const char*); | |||
typedef bool IZ_ConfigLoadParamsU16Validator(u16); | |||
typedef bool IZ_ConfigLoadParamsU8Validator(u8); | |||
void IZ_ConfigEnsureValidString(IZ_ConfigItem item, char* buffer) { | |||
char dest[item.dest_size]; | |||
if (item.validator) { | |||
IZ_ConfigLoadParamsStringValidator* validator = item.validator; | |||
if (validator(buffer)) { | |||
memcpy_s(dest, item.dest_size, buffer, item.dest_size); | |||
item.dest = &dest; | |||
return; | |||
} | |||
memcpy_s(dest, item.dest_size, item.default_value, item.dest_size); | |||
item.dest = &dest; | |||
return; | |||
} | |||
memcpy_s(dest, item.dest_size, buffer, item.dest_size); | |||
item.dest = &dest; | |||
} | |||
void IZ_ConfigLoadString(IZ_ConfigItem item, const char* config_path) { | |||
char buffer[item.dest_size]; | |||
ini_gets(item.section, item.key, item.default_value, buffer, item.dest_size, config_path); | |||
IZ_ConfigEnsureValidString(item, buffer); | |||
} | |||
void IZ_ConfigEnsureValidU8(IZ_ConfigItem item, u8 raw_value, u8 default_value) { | |||
if (item.validator) { | |||
IZ_ConfigLoadParamsU8Validator* validator = item.validator; | |||
if (validator(raw_value)) { | |||
item.dest = &raw_value; | |||
return; | |||
} | |||
item.dest = &default_value; | |||
return; | |||
} | |||
item.dest = &raw_value; | |||
} | |||
void IZ_ConfigLoadU8(IZ_ConfigItem item, const char* config_path) { | |||
static u8 raw_value; | |||
static u8 default_value; | |||
default_value = *((u8*) item.default_value); | |||
raw_value = ini_getl(item.section, item.key, default_value, config_path); | |||
IZ_ConfigEnsureValidU8(item, raw_value, default_value); | |||
} | |||
void IZ_ConfigEnsureValidU16(IZ_ConfigItem item, u16 raw_value, u16 default_value) { | |||
if (item.validator) { | |||
IZ_ConfigLoadParamsU16Validator* validator = item.validator; | |||
if (validator(raw_value)) { | |||
item.dest = &raw_value; | |||
return; | |||
} | |||
item.dest = &default_value; | |||
return; | |||
} | |||
item.dest = &raw_value; | |||
} | |||
void IZ_ConfigLoadU16(IZ_ConfigItem item, const char* config_path) { | |||
static u16 raw_value; | |||
static u16 default_value; | |||
default_value = *((u16*) item.default_value); | |||
raw_value = ini_getl(item.section, item.key, default_value, config_path); | |||
IZ_ConfigEnsureValidU16(item, raw_value, default_value); | |||
} | |||
void IZ_ConfigLoad(IZ_ConfigItem item[], const char* config_path) { | |||
u8 i; | |||
for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) { | |||
switch (item[i].type) { | |||
case IZ_CONFIG_TYPE_STRING: | |||
IZ_ConfigLoadString(item[i], config_path); | |||
break; | |||
case IZ_CONFIG_TYPE_U8: | |||
IZ_ConfigLoadU8(item[i], config_path); | |||
break; | |||
case IZ_CONFIG_TYPE_U16: | |||
IZ_ConfigLoadU16(item[i], config_path); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
} | |||
IZ_ProcedureResult IZ_ConfigSaveU8(IZ_ConfigItem item, const char* config_path) { | |||
u8 dest = *((u8*) item.dest); | |||
if (item.validator) { | |||
IZ_ConfigLoadParamsU8Validator* validator = item.validator; | |||
if (!validator(dest)) { | |||
dest = *((const u8*) item.default_value); | |||
} | |||
} | |||
if (!ini_putl(item.section, item.key, dest, config_path)) { | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
IZ_ProcedureResult IZ_ConfigSaveU16(IZ_ConfigItem item, const char* config_path) { | |||
u16 dest = *((u16*) item.dest); | |||
if (item.validator) { | |||
IZ_ConfigLoadParamsU8Validator* validator = item.validator; | |||
if (!validator(dest)) { | |||
dest = *((const u16*) item.default_value); | |||
} | |||
} | |||
if (!ini_putl(item.section, item.key, dest, config_path)) { | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
IZ_ProcedureResult IZ_ConfigSaveString(IZ_ConfigItem item, const char* config_path) { | |||
const char* dest = (const char*) item.dest; | |||
if (item.validator) { | |||
IZ_ConfigLoadParamsStringValidator* validator = item.validator; | |||
if (!validator(dest)) { | |||
dest = (const char*) item.default_value; | |||
} | |||
} | |||
if (!ini_puts(item.section, item.key, dest, config_path)) { | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
IZ_ProcedureResult IZ_ConfigSave(IZ_ConfigItem item[], const char* config_path) { | |||
u8 i; | |||
u16 problems = 0; | |||
for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) { | |||
switch (item[i].type) { | |||
case IZ_CONFIG_TYPE_STRING: | |||
IZ_ConfigSaveString(item[i], config_path); | |||
break; | |||
case IZ_CONFIG_TYPE_U8: | |||
IZ_ConfigSaveU8(item[i], config_path); | |||
break; | |||
case IZ_CONFIG_TYPE_U16: | |||
IZ_ConfigSaveU16(item[i], config_path); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
return -problems; | |||
} | |||
void IZ_ConfigOverrideU8(IZ_ConfigItem item, u8 argc, const char* argv[]) { | |||
if (!item.cmdline_option) { | |||
return; | |||
} | |||
const char* cmdline_buffer; | |||
char* rest_of_string; | |||
static u8 dest; | |||
static u8 default_value; | |||
default_value = *((u16*) item.default_value); | |||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, item.cmdline_option))) { | |||
dest = strtol(cmdline_buffer, &rest_of_string, 10); | |||
if (strcmp(cmdline_buffer, rest_of_string) != 0) { | |||
IZ_ConfigEnsureValidU8(item, dest, default_value); | |||
return; | |||
} | |||
item.dest = &default_value; | |||
} | |||
} | |||
void IZ_ConfigOverrideU16(IZ_ConfigItem item, u8 argc, const char* argv[]) { | |||
if (!item.cmdline_option) { | |||
return; | |||
} | |||
const char* cmdline_buffer; | |||
char* rest_of_string; | |||
static u16 dest; | |||
static u16 default_value; | |||
default_value = *((u16*) item.default_value); | |||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, item.cmdline_option))) { | |||
dest = strtol(cmdline_buffer, &rest_of_string, 10); | |||
if (strcmp(cmdline_buffer, rest_of_string) != 0) { | |||
IZ_ConfigEnsureValidU16(item, dest, default_value); | |||
return; | |||
} | |||
item.dest = &default_value; | |||
} | |||
} | |||
void IZ_ConfigOverrideString(IZ_ConfigItem item, u8 argc, const char* argv[]) { | |||
if (!item.cmdline_option) { | |||
return; | |||
} | |||
const char* cmdline_buffer; | |||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, item.cmdline_option))) { | |||
IZ_ConfigEnsureValidString(item, cmdline_buffer); | |||
} | |||
} | |||
void IZ_ConfigOverride(IZ_ConfigItem item[], u8 argc, const char* argv[]) { | |||
u8 i; | |||
for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) { | |||
switch (item[i].type) { | |||
case IZ_CONFIG_TYPE_U8: | |||
IZ_ConfigOverrideU8(item[i], argc, argv); | |||
break; | |||
case IZ_CONFIG_TYPE_U16: | |||
IZ_ConfigOverrideU16(item[i], argc, argv); | |||
break; | |||
case IZ_CONFIG_TYPE_STRING: | |||
IZ_ConfigOverrideString(item[i], argc, argv); | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
} | |||
void IZ_ConfigInit(IZ_ConfigItem item[], const char* config_path, u8 argc, const char* argv[]) { | |||
IZ_ConfigLoad(item, config_path); | |||
if (IZ_ConfigSave(item, config_path)) { | |||
// TODO log errors in saving | |||
} | |||
IZ_ConfigOverride(item, argc, argv); | |||
} |
@@ -3,11 +3,34 @@ | |||
#include <SDL_filesystem.h> | |||
#include <string.h> | |||
#include <minIni.h> | |||
#include <stdlib.h> | |||
#include "IZ_common.h" | |||
// TODO unify loading of config from cmdline and config file | |||
typedef enum { | |||
IZ_CONFIG_TYPE_VOID, | |||
IZ_CONFIG_TYPE_STRING, | |||
IZ_CONFIG_TYPE_U8, | |||
IZ_CONFIG_TYPE_U16 | |||
} IZ_ConfigType; | |||
typedef struct { | |||
IZ_ConfigType type; | |||
size_t dest_size; | |||
const char* section; | |||
const char* key; | |||
const char* cmdline_option; | |||
const void* default_value; | |||
void* validator; | |||
void* dest; | |||
} IZ_ConfigItem; | |||
void IZ_ConfigGetDefaultPath(const char*, size_t); | |||
const char* IZ_ConfigGetCommandlineOption(u8, const char**, const char*); | |||
void IZ_ConfigInit(IZ_ConfigItem[], const char*, u8, const char**); | |||
IZ_ProcedureResult IZ_ConfigSave(IZ_ConfigItem[], const char*); | |||
#endif |
@@ -1,57 +1,66 @@ | |||
#include "IZ_net.h" | |||
void IZ_NetLoadConfig(IZ_NetState* state, const char* config_path) { | |||
char buffer[32]; | |||
ini_gets("Network", "Username", IZ_NET_DEFAULT_STATE.config.username, buffer, 32, config_path); | |||
memcpy_s(state->config.username, 32, buffer, 32); | |||
state->config.packet_interval_ms = ini_getl("Network", "PacketIntervalMs", IZ_NET_DEFAULT_STATE.config.packet_interval_ms, config_path); | |||
if (!(100 <= state->config.packet_interval_ms && state->config.packet_interval_ms <= 500)) { | |||
state->config.packet_interval_ms = IZ_NET_DEFAULT_STATE.config.packet_interval_ms; | |||
} | |||
state->config.max_reconnect_retries = ini_getl("Network", "MaxReconnectRetries", IZ_NET_DEFAULT_STATE.config.max_reconnect_retries, config_path); | |||
if (!(0 <= state->config.max_reconnect_retries && state->config.max_reconnect_retries <= 8)) { | |||
state->config.max_reconnect_retries = IZ_NET_DEFAULT_STATE.config.max_reconnect_retries; | |||
} | |||
state->config.reconnect_interval_secs = ini_getl("Network", "ReconnectIntervalSeconds", IZ_NET_DEFAULT_STATE.config.reconnect_interval_secs, config_path); | |||
if (!(3 <= state->config.reconnect_interval_secs && state->config.reconnect_interval_secs <= 10)) { | |||
state->config.reconnect_interval_secs = IZ_NET_DEFAULT_STATE.config.reconnect_interval_secs; | |||
} | |||
bool IZ_NetIsValidPacketIntervalMs(long packet_interval_ms) { | |||
return (100 <= packet_interval_ms && packet_interval_ms <= 500); | |||
} | |||
IZ_ProcedureResult IZ_NetSaveConfig(IZ_NetState* state, const char* config_path) { | |||
if (!ini_puts("Network", "Username", state->config.username, config_path)) { | |||
return -1; | |||
} | |||
if (!ini_putl("Network", "PacketIntervalMs", state->config.packet_interval_ms, config_path)) { | |||
return -1; | |||
} | |||
if (!ini_putl("Network", "MaxReconnectRetries", state->config.max_reconnect_retries, config_path)) { | |||
return -1; | |||
} | |||
bool IZ_NetIsValidMaxReconnectRetries(long max_reconnect_retries) { | |||
return (0 <= max_reconnect_retries && max_reconnect_retries <= 8); | |||
} | |||
if (!ini_putl("Network", "ReconnectIntervalSeconds", state->config.reconnect_interval_secs, config_path)) { | |||
return -1; | |||
} | |||
bool IZ_NetIsValidReconnectIntervalSeconds(long reconnect_interval_secs) { | |||
return (3 <= reconnect_interval_secs && reconnect_interval_secs <= 10); | |||
} | |||
return 0; | |||
static IZ_ConfigItem net_config_items[] = { | |||
{ | |||
IZ_CONFIG_TYPE_STRING, | |||
32, | |||
"Network", | |||
"Username", | |||
NULL, | |||
&IZ_NET_DEFAULT_STATE.config.username, | |||
NULL | |||
}, | |||
{ | |||
IZ_CONFIG_TYPE_U16, | |||
sizeof(u16), | |||
"Network", | |||
"PacketIntervalMs", | |||
"-i", | |||
&IZ_NET_DEFAULT_STATE.config.packet_interval_ms, | |||
IZ_NetIsValidPacketIntervalMs, | |||
}, | |||
{ | |||
IZ_CONFIG_TYPE_U8, | |||
sizeof(u8), | |||
"Network", | |||
"MaxReconnectRetries", | |||
NULL, | |||
&IZ_NET_DEFAULT_STATE.config.max_reconnect_retries, | |||
IZ_NetIsValidMaxReconnectRetries, | |||
}, | |||
{ | |||
IZ_CONFIG_TYPE_U8, | |||
sizeof(u8), | |||
"Network", | |||
"ReconnectIntervalSeconds", | |||
NULL, | |||
&IZ_NET_DEFAULT_STATE.config.reconnect_interval_secs, | |||
IZ_NetIsValidReconnectIntervalSeconds, | |||
}, | |||
}; | |||
void IZ_NetBindStateToConfig(IZ_NetState* state, IZ_ConfigItem config_items[]) { | |||
config_items[0].dest = &state->config.username; | |||
config_items[1].dest = &state->config.packet_interval_ms; | |||
config_items[2].dest = &state->config.max_reconnect_retries; | |||
config_items[3].dest = &state->config.reconnect_interval_secs; | |||
} | |||
void IZ_NetOverrideConfig(IZ_NetState* state, u8 argc, const char* argv[]) { | |||
const char* cmdline_buffer; | |||
char* rest_of_string; | |||
u16 packet_interval_ms; | |||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-i"))) { | |||
packet_interval_ms = strtol(cmdline_buffer, &rest_of_string, 10); | |||
if (strcmp(cmdline_buffer, rest_of_string) != 0) { | |||
state->config.packet_interval_ms = packet_interval_ms; | |||
} | |||
} | |||
IZ_ProcedureResult IZ_NetSaveConfig(IZ_NetState* state, const char* config_path) { | |||
IZ_NetBindStateToConfig(state, net_config_items); | |||
return IZ_ConfigSave(net_config_items, config_path); | |||
} | |||
IZ_ProcedureResult IZ_NetInitialize( | |||
@@ -63,11 +72,8 @@ IZ_ProcedureResult IZ_NetInitialize( | |||
const char* argv[] | |||
) { | |||
memcpy_s(state, sizeof(IZ_NetState), &IZ_NET_DEFAULT_STATE, sizeof(IZ_NetState)); | |||
IZ_NetLoadConfig(state, config_path); | |||
if (IZ_NetSaveConfig(state, config_path) < 0) { | |||
return -1; | |||
} | |||
IZ_NetOverrideConfig(state, argc, argv); | |||
IZ_NetBindStateToConfig(state, net_config_items); | |||
IZ_ConfigInit(net_config_items, config_path, argc, argv); | |||
if (!user_data) { | |||
return -2; | |||
} | |||
@@ -1,45 +1,64 @@ | |||
#include "IZ_video.h" | |||
IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoState* state, const char* config_path) { | |||
if (!ini_putl("Video", "Width", state->config.width, config_path)) { | |||
return -1; | |||
} | |||
if (!ini_putl("Video", "Height", state->config.height, config_path)) { | |||
return -1; | |||
} | |||
if (!ini_putl("Video", "MaxFps", state->config.max_fps, config_path)) { | |||
return -1; | |||
} | |||
bool IZ_VideoIsValidWidth(u16 width) { | |||
// TODO check screen size | |||
return (320 <= width && width <= 16384); | |||
} | |||
return 0; | |||
bool IZ_VideoIsValidHeight(u16 height) { | |||
// TODO check screen size | |||
return (240 <= height && height <= 8192); | |||
} | |||
void IZ_VideoLoadConfig(IZ_VideoState* state, const char* config_path) { | |||
state->config.width = ini_getl("Video", "Width", IZ_DEFAULT_VIDEO_STATE.config.width, config_path); | |||
state->config.height = ini_getl("Video", "Height", IZ_DEFAULT_VIDEO_STATE.config.height, config_path); | |||
state->config.max_fps = ini_getl("Video", "MaxFps", IZ_DEFAULT_VIDEO_STATE.config.max_fps, config_path); | |||
bool IZ_VideoIsValidMaxFPS(u8 max_fps) { | |||
return (10 <= max_fps && max_fps <= 200); | |||
} | |||
void IZ_VideoOverrideConfig(IZ_VideoState* state, u8 argc, const char* argv[]) { | |||
const char* cmdline_buffer; | |||
char* rest_of_string; | |||
u8 max_fps; | |||
if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, "-f"))) { | |||
max_fps = strtol(cmdline_buffer, &rest_of_string, 10); | |||
if (strcmp(cmdline_buffer, rest_of_string) != 0) { | |||
state->config.max_fps = max_fps; | |||
} | |||
} | |||
static IZ_ConfigItem video_config_items[] = { | |||
{ | |||
IZ_CONFIG_TYPE_U16, | |||
sizeof(u16), | |||
"Video", | |||
"Width", | |||
NULL, | |||
&IZ_VIDEO_DEFAULT_STATE.config.width, | |||
IZ_VideoIsValidWidth, | |||
}, | |||
{ | |||
IZ_CONFIG_TYPE_U16, | |||
sizeof(u16), | |||
"Video", | |||
"Height", | |||
NULL, | |||
&IZ_VIDEO_DEFAULT_STATE.config.height, | |||
IZ_VideoIsValidHeight, | |||
}, | |||
{ | |||
IZ_CONFIG_TYPE_U8, | |||
sizeof(u8), | |||
"Video", | |||
"MaxFps", | |||
"-f", | |||
&IZ_VIDEO_DEFAULT_STATE.config.max_fps, | |||
IZ_VideoIsValidMaxFPS, | |||
}, | |||
}; | |||
void IZ_VideoBindStateToConfig(IZ_VideoState* state, IZ_ConfigItem config_items[]) { | |||
config_items[0].dest = &state->config.width; | |||
config_items[1].dest = &state->config.height; | |||
config_items[2].dest = &state->config.max_fps; | |||
} | |||
IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState* state, void* user_data, const char* config_path, u8 argc, const char* argv[]) { | |||
SDL_memcpy(state, &IZ_DEFAULT_VIDEO_STATE, sizeof(IZ_VideoState)); | |||
IZ_ProcedureResult IZ_VideoSaveConfig(IZ_VideoState* state, const char* config_path) { | |||
IZ_VideoBindStateToConfig(state, video_config_items); | |||
return IZ_ConfigSave(video_config_items, config_path); | |||
} | |||
IZ_VideoLoadConfig(state, config_path); | |||
if (IZ_VideoSaveConfig(state, config_path)) { | |||
// fprintf_s(stderr, "Error committing video config.\n"); | |||
} | |||
IZ_VideoOverrideConfig(state, argc, argv); | |||
IZ_ProcedureResult IZ_VideoInitialize(IZ_VideoState* state, void* user_data, const char* config_path, u8 argc, const char* argv[]) { | |||
SDL_memcpy(state, &IZ_VIDEO_DEFAULT_STATE, sizeof(IZ_VideoState)); | |||
IZ_VideoBindStateToConfig(state, video_config_items); | |||
IZ_ConfigInit(video_config_items, config_path, argc, argv); | |||
state->last_update_at = 0u; | |||
state->user_data = user_data; | |||
@@ -30,7 +30,7 @@ typedef struct { | |||
IZ_Sprite active_sprites[MAX_ACTIVE_SPRITES]; | |||
} IZ_VideoState; | |||
static const IZ_VideoState IZ_DEFAULT_VIDEO_STATE = { | |||
static const IZ_VideoState IZ_VIDEO_DEFAULT_STATE = { | |||
.user_data = NULL, | |||
.config = { | |||
.width = 320u, | |||
@@ -41,31 +41,45 @@ void IZ_AppTeardown(IZ_App* app) { | |||
lwsl_user("Server closed. Bye!\n"); | |||
} | |||
void IZ_AppPrintHelpOptions() { | |||
printf("\n"); | |||
printf("Options:\n"); | |||
printf("\n"); | |||
printf( | |||
"\n" | |||
"Options:\n" | |||
"\n" | |||
" -c <path> Specifies the path to the config file. (default: \"./config-server.ini\")\n" | |||
" -d <path> Specifies the path to the database. (default: \"./db.sqlite\")\n" | |||
" -h Displays this help screen.\n" | |||
" -m <value> Specifies the message of the day. (default: \"\")\n" | |||
" -n <value> Specifies the name of the server. (default: \"%s\")\n" | |||
" -p <value> Specifies the port where the server runs. (default: 42069)\n", | |||
IZ_APP_NAME | |||
); | |||
} | |||
void IZ_AppPrintHelpUsage() { | |||
printf("\n"); | |||
printf("Usage:"); | |||
printf(" %s [options]\n", "server.exe"); | |||
} | |||
void IZ_AppPrintHelpHeader() { | |||
printf("\n"); | |||
printf("%s - %s\n", IZ_APP_NAME, IZ_APP_SERVER_DESCRIPTION); | |||
} | |||
void IZ_AppPrintHelp() { | |||
IZ_AppPrintHelpHeader(); | |||
IZ_AppPrintHelpUsage(); | |||
IZ_AppPrintHelpOptions(); | |||
} | |||
IZ_ProcedureResult IZ_AppRun(IZ_App *app, u8 argc, const char **argv) { | |||
// TODO have a config subsystem that handles these. | |||
if (IZ_ConfigGetCommandlineOption(argc, argv, "-h")) { | |||
printf( | |||
( | |||
"\n" | |||
"%s - %s\n" | |||
"\n" | |||
"Usage:\n" | |||
"\n" | |||
" %s [options]\n" | |||
"\n" | |||
"Options:\n" | |||
"\n" | |||
" -c <path> Specifies the path to the config file. (default: \"./config-server.ini\")\n" | |||
" -d <path> Specifies the path to the database. (default: \"./db.sqlite\")\n" | |||
" -h Displays this help file.\n" | |||
" -m <value> Specifies the message of the day. (default: \"\")\n" | |||
" -n <value> Specifies the name of the server. (default: \"%s\")\n" | |||
" -p <value> Specifies the port where the server runs. (default: 42069)\n" | |||
), | |||
IZ_APP_NAME, | |||
IZ_APP_SERVER_DESCRIPTION, | |||
"server.exe", | |||
IZ_APP_NAME | |||
); | |||
IZ_AppPrintHelp(); | |||
return 0; | |||
} | |||