2D Run-and-gun shooter inspired by One Man's Doomsday, Counter-Strike, and Metal Slug.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

213 regels
5.9 KiB

  1. #include "IZ_net_client.h"
  2. bool IZ_NetClientIsValidPacketIntervalMs(long packet_interval_ms) {
  3. return (100 <= packet_interval_ms && packet_interval_ms <= 500);
  4. }
  5. bool IZ_NetClientIsValidMaxReconnectRetries(long max_reconnect_retries) {
  6. return (0 <= max_reconnect_retries && max_reconnect_retries <= 8);
  7. }
  8. bool IZ_NetClientIsValidReconnectIntervalSeconds(long reconnect_interval_secs) {
  9. return (3 <= reconnect_interval_secs && reconnect_interval_secs <= 10);
  10. }
  11. static INI_ConfigItem net_client_config_items[IZ_PLAYERS + 3 + 1];
  12. void IZ_NetClientInitializeConfigItems(INI_ConfigItem config_items[]) {
  13. config_items[0] = (INI_ConfigItem) {
  14. INI_CONFIG_TYPE_U16,
  15. "Network",
  16. "PacketIntervalMs",
  17. "-i",
  18. &IZ_NET_CLIENT_DEFAULT_STATE.config.packet_interval_ms,
  19. IZ_NetClientIsValidPacketIntervalMs,
  20. INI_CONFIG_TRANSFORMER_NONE,
  21. NULL,
  22. };
  23. config_items[1] = (INI_ConfigItem) {
  24. INI_CONFIG_TYPE_U8,
  25. "Network",
  26. "MaxReconnectRetries",
  27. NULL,
  28. &IZ_NET_CLIENT_DEFAULT_STATE.config.max_reconnect_retries,
  29. IZ_NetClientIsValidMaxReconnectRetries,
  30. INI_CONFIG_TRANSFORMER_NONE,
  31. NULL,
  32. };
  33. config_items[2] = (INI_ConfigItem) {
  34. INI_CONFIG_TYPE_U8,
  35. "Network",
  36. "ReconnectIntervalSeconds",
  37. NULL,
  38. &IZ_NET_CLIENT_DEFAULT_STATE.config.reconnect_interval_secs,
  39. IZ_NetClientIsValidReconnectIntervalSeconds,
  40. INI_CONFIG_TRANSFORMER_NONE,
  41. NULL,
  42. };
  43. u8 player_index;
  44. char* main_section_name;
  45. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  46. main_section_name = malloc(sizeof(char) * 64);
  47. sprintf(main_section_name, "Network.%d", player_index);
  48. config_items[3 + player_index] = (INI_ConfigItem) {
  49. INI_CONFIG_TYPE_STRING(32),
  50. main_section_name,
  51. "Username",
  52. NULL,
  53. &IZ_NET_CLIENT_DEFAULT_STATE.config.usernames[player_index],
  54. NULL,
  55. INI_CONFIG_TRANSFORMER_NONE,
  56. NULL,
  57. };
  58. }
  59. config_items[3 + IZ_PLAYERS] = INI_CONFIG_ITEM_NULL;
  60. }
  61. void IZ_NetClientBindStateToConfig(IZ_NetClientState* state, INI_ConfigItem config_items[]) {
  62. config_items[0].dest = &state->config.packet_interval_ms;
  63. config_items[1].dest = &state->config.max_reconnect_retries;
  64. config_items[2].dest = &state->config.reconnect_interval_secs;
  65. u8 player_index;
  66. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  67. config_items[3 + player_index].dest = &state->config.usernames[player_index];
  68. }
  69. }
  70. IZ_ProcedureResult IZ_NetClientSaveConfig(IZ_NetClientState* state, const char* config_path) {
  71. IZ_NetClientBindStateToConfig(state, net_client_config_items);
  72. return INI_ConfigSave(net_client_config_items, config_path);
  73. }
  74. IZ_ProcedureResult IZ_NetClientInitializeConfig(
  75. IZ_NetClientState* state,
  76. const char* config_path,
  77. u8 argc,
  78. const char* argv[]
  79. ) {
  80. IZ_NetClientInitializeConfigItems(net_client_config_items);
  81. IZ_NetClientBindStateToConfig(state, net_client_config_items);
  82. if (INI_ConfigInitialize(net_client_config_items, config_path, argc, argv) < 0) {
  83. return -1;
  84. }
  85. return 0;
  86. }
  87. IZ_ProcedureResult IZ_NetClientInitialize(
  88. IZ_NetClientState* state,
  89. void* user_data,
  90. void* callback,
  91. const char* config_path,
  92. u8 argc,
  93. const char* argv[]
  94. ) {
  95. if (!user_data) {
  96. return -1;
  97. }
  98. IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "net", "Setting up...");
  99. IZ_memcpy(state, sizeof(IZ_NetClientState), &IZ_NET_CLIENT_DEFAULT_STATE, sizeof(IZ_NetClientState));
  100. if (IZ_NetClientInitializeConfig(state, config_path, argc, argv) < 0) {
  101. return -2;
  102. }
  103. state->binding.user_data = user_data;
  104. state->callback = callback;
  105. state->retries = state->config.max_reconnect_retries;
  106. u8 player_index;
  107. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  108. state->action[player_index] = 0;
  109. }
  110. return 0;
  111. }
  112. void IZ_NetClientTeardown(IZ_NetClientState* state) {
  113. IZ_LogInfo(IZ_LOG_CATEGORY_GLOBAL, "net", "Shutting down...");
  114. IZ_NetClientDisconnect(state);
  115. }
  116. void IZ_NetClientConnect(IZ_NetClientState* state, IZ_WSClientInitializeParams params) {
  117. if (!state->callback) {
  118. return;
  119. }
  120. if (state->status == IZ_NET_CLIENT_STATUS_CONNECTED) {
  121. return;
  122. }
  123. if (state->status == IZ_NET_CLIENT_STATUS_CONNECTING) {
  124. return;
  125. }
  126. if (state->retries < state->config.max_reconnect_retries) {
  127. return;
  128. }
  129. state->retries = 0;
  130. state->params = params;
  131. state->thread = SDL_CreateThread(state->callback, "networking", state->binding.user_data);
  132. SDL_DetachThread(state->thread);
  133. }
  134. void IZ_NetClientDisconnect(IZ_NetClientState* state) {
  135. if (state->status == IZ_NET_CLIENT_STATUS_PRISTINE) {
  136. return;
  137. }
  138. if (state->binding.connection) {
  139. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  140. lws_get_vhost(state->binding.connection),
  141. lws_get_protocol(state->binding.connection)
  142. );
  143. if (vhd) {
  144. lws_sul_cancel(&vhd->sul);
  145. }
  146. }
  147. state->retries = state->config.max_reconnect_retries;
  148. IZ_WSClientCancelService(&state->binding);
  149. }
  150. void IZ_NetClientSendBinaryMessage(IZ_NetClientState* state, void* in, size_t len) {
  151. if (state->status != IZ_NET_CLIENT_STATUS_CONNECTED) {
  152. return;
  153. }
  154. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  155. lws_get_vhost(state->binding.connection),
  156. lws_get_protocol(state->binding.connection)
  157. );
  158. IZ_WebsocketMessage amsg;
  159. i32 result;
  160. result = IZ_WebsocketCreateBinaryMessage(state->binding.connection, &amsg, in, len);
  161. if (result < 0) {
  162. return;
  163. }
  164. lws_ring_insert(vhd->ring, &amsg, 1);
  165. lws_callback_on_writable(state->binding.connection);
  166. }
  167. void IZ_NetClientSendTextMessage(IZ_NetClientState* state, char* in, size_t len) {
  168. if (state->status != IZ_NET_CLIENT_STATUS_CONNECTED) {
  169. return;
  170. }
  171. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  172. lws_get_vhost(state->binding.connection),
  173. lws_get_protocol(state->binding.connection)
  174. );
  175. IZ_WebsocketMessage amsg;
  176. i32 result;
  177. result = IZ_WebsocketCreateTextMessage(state->binding.connection, &amsg, in, len);
  178. if (result < 0) {
  179. return;
  180. }
  181. lws_ring_insert(vhd->ring, &amsg, 1);
  182. lws_callback_on_writable(state->binding.connection);
  183. }