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.
 
 
 
 
 
 

174 lines
4.5 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 IZ_ConfigItem net_config_items[] = {
  12. {
  13. IZ_CONFIG_TYPE_STRING,
  14. 32,
  15. "Network",
  16. "Username",
  17. NULL,
  18. &IZ_NET_CLIENT_DEFAULT_STATE.config.username,
  19. NULL
  20. },
  21. {
  22. IZ_CONFIG_TYPE_U16,
  23. sizeof(u16),
  24. "Network",
  25. "PacketIntervalMs",
  26. "-i",
  27. &IZ_NET_CLIENT_DEFAULT_STATE.config.packet_interval_ms,
  28. IZ_NetClientIsValidPacketIntervalMs,
  29. },
  30. {
  31. IZ_CONFIG_TYPE_U8,
  32. sizeof(u8),
  33. "Network",
  34. "MaxReconnectRetries",
  35. NULL,
  36. &IZ_NET_CLIENT_DEFAULT_STATE.config.max_reconnect_retries,
  37. IZ_NetClientIsValidMaxReconnectRetries,
  38. },
  39. {
  40. IZ_CONFIG_TYPE_U8,
  41. sizeof(u8),
  42. "Network",
  43. "ReconnectIntervalSeconds",
  44. NULL,
  45. &IZ_NET_CLIENT_DEFAULT_STATE.config.reconnect_interval_secs,
  46. IZ_NetClientIsValidReconnectIntervalSeconds,
  47. },
  48. };
  49. void IZ_NetClientBindStateToConfig(IZ_NetClientState* state, IZ_ConfigItem config_items[]) {
  50. config_items[0].dest = &state->config.username;
  51. config_items[1].dest = &state->config.packet_interval_ms;
  52. config_items[2].dest = &state->config.max_reconnect_retries;
  53. config_items[3].dest = &state->config.reconnect_interval_secs;
  54. }
  55. IZ_ProcedureResult IZ_NetClientSaveConfig(IZ_NetClientState* state, const char* config_path) {
  56. IZ_NetClientBindStateToConfig(state, net_config_items);
  57. return IZ_ConfigSave(net_config_items, config_path);
  58. }
  59. IZ_ProcedureResult IZ_NetClientInitialize(
  60. IZ_NetClientState* state,
  61. void* user_data,
  62. void* callback,
  63. const char* config_path,
  64. u8 argc,
  65. const char* argv[]
  66. ) {
  67. memcpy_s(state, sizeof(IZ_NetClientState), &IZ_NET_CLIENT_DEFAULT_STATE, sizeof(IZ_NetClientState));
  68. IZ_NetClientBindStateToConfig(state, net_config_items);
  69. IZ_ConfigInit(net_config_items, config_path, argc, argv);
  70. if (!user_data) {
  71. return -2;
  72. }
  73. state->binding.user_data = user_data;
  74. state->callback = callback;
  75. state->retries = state->config.max_reconnect_retries;
  76. u8 player_index;
  77. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  78. state->action[player_index] = 0;
  79. }
  80. return 0;
  81. }
  82. void IZ_NetClientConnect(IZ_NetClientState* state, IZ_WSClientInitializeParams params) {
  83. if (!state->callback) {
  84. return;
  85. }
  86. if (state->status == IZ_NET_CLIENT_STATUS_CONNECTED) {
  87. return;
  88. }
  89. if (state->status == IZ_NET_CLIENT_STATUS_CONNECTING) {
  90. return;
  91. }
  92. if (state->retries < state->config.max_reconnect_retries) {
  93. return;
  94. }
  95. state->retries = 0;
  96. state->params = params;
  97. state->client_thread = SDL_CreateThread(state->callback, "networking", state->binding.user_data);
  98. SDL_DetachThread(state->client_thread);
  99. }
  100. void IZ_NetClientDisconnect(IZ_NetClientState* state) {
  101. if (state->status == IZ_NET_CLIENT_STATUS_PRISTINE) {
  102. return;
  103. }
  104. if (state->binding.connection) {
  105. IZ_WSClientVHostData *vhd = (IZ_WSClientVHostData *) lws_protocol_vh_priv_get(
  106. lws_get_vhost(state->binding.connection),
  107. lws_get_protocol(state->binding.connection)
  108. );
  109. if (vhd) {
  110. lws_sul_cancel(&vhd->sul);
  111. }
  112. }
  113. state->retries = state->config.max_reconnect_retries;
  114. IZ_WSClientCancelService(&state->binding);
  115. }
  116. void IZ_NetClientSendBinaryMessage(IZ_NetClientState* state, void* in, size_t len) {
  117. if (state->status != IZ_NET_CLIENT_STATUS_CONNECTED) {
  118. return;
  119. }
  120. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  121. lws_get_vhost(state->binding.connection),
  122. lws_get_protocol(state->binding.connection)
  123. );
  124. IZ_WebsocketMessage amsg;
  125. i32 result;
  126. result = IZ_WebsocketCreateBinaryMessage(state->binding.connection, &amsg, in, len);
  127. if (result < 0) {
  128. return;
  129. }
  130. lws_ring_insert(vhd->ring, &amsg, 1);
  131. lws_callback_on_writable(state->binding.connection);
  132. }
  133. void IZ_NetClientSendTextMessage(IZ_NetClientState* state, char* in, size_t len) {
  134. if (state->status != IZ_NET_CLIENT_STATUS_CONNECTED) {
  135. return;
  136. }
  137. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  138. lws_get_vhost(state->binding.connection),
  139. lws_get_protocol(state->binding.connection)
  140. );
  141. IZ_WebsocketMessage amsg;
  142. i32 result;
  143. result = IZ_WebsocketCreateTextMessage(state->binding.connection, &amsg, in, len);
  144. if (result < 0) {
  145. return;
  146. }
  147. lws_ring_insert(vhd->ring, &amsg, 1);
  148. lws_callback_on_writable(state->binding.connection);
  149. }