callback.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. #include <callback/callback.h>
  2. #include <callback/loader.h>
  3. #include <callback/free.h>
  4. #include <callback/alloc.h>
  5. #include <callback/game.h>
  6. #include "alloc/alloc.h"
  7. #include <flip_storage/storage.h>
  8. bool callback_message_input(InputEvent *event, void *context)
  9. {
  10. FlipWorldApp *app = (FlipWorldApp *)context;
  11. furi_check(app);
  12. if (event->key == InputKeyBack)
  13. {
  14. FURI_LOG_I(TAG, "Message view - BACK pressed");
  15. user_hit_back = true;
  16. }
  17. return true;
  18. }
  19. void callback_message_draw(Canvas *canvas, void *model)
  20. {
  21. MessageModel *message_model = model;
  22. canvas_clear(canvas);
  23. if (message_model->message_state == MessageStateAbout)
  24. {
  25. canvas_draw_str(canvas, 0, 10, VERSION_TAG);
  26. canvas_set_font_custom(canvas, FONT_SIZE_SMALL);
  27. canvas_draw_str(canvas, 0, 20, "Dev: JBlanked, codeallnight");
  28. canvas_draw_str(canvas, 0, 30, "GFX: the1anonlypr3");
  29. canvas_draw_str(canvas, 0, 40, "github.com/jblanked/FlipWorld");
  30. canvas_draw_str_multi(canvas, 0, 55, "The first open world multiplayer\ngame on the Flipper Zero.");
  31. }
  32. else if (message_model->message_state == MessageStateLoading)
  33. {
  34. canvas_set_font(canvas, FontPrimary);
  35. if (game_mode_index != 1)
  36. {
  37. canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Starting FlipWorld");
  38. canvas_set_font(canvas, FontSecondary);
  39. canvas_draw_str(canvas, 0, 50, "Please wait while your");
  40. canvas_draw_str(canvas, 0, 60, "game is started.");
  41. }
  42. else
  43. {
  44. canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Loading Lobbies");
  45. canvas_set_font(canvas, FontSecondary);
  46. canvas_draw_str(canvas, 0, 60, "Please wait....");
  47. }
  48. }
  49. // well this is only called once so let's make a while loop
  50. else if (message_model->message_state == MessageStateWaitingLobby)
  51. {
  52. canvas_draw_str(canvas, 0, 10, "Waiting for more players...");
  53. // time elapsed based on timer_iteration and timer_refresh
  54. // char str[32];
  55. // snprintf(str, sizeof(str), "Time elapsed: %d seconds", timer_iteration * timer_refresh);
  56. // canvas_draw_str(canvas, 0, 50, str);
  57. canvas_draw_str(canvas, 0, 60, "Press BACK to cancel.");
  58. canvas_commit(canvas); // make sure message is drawn
  59. }
  60. else
  61. {
  62. canvas_draw_str(canvas, 0, 10, "Unknown message state");
  63. }
  64. }
  65. void callback_submenu_choices(void *context, uint32_t index)
  66. {
  67. FlipWorldApp *app = (FlipWorldApp *)context;
  68. furi_check(app);
  69. switch (index)
  70. {
  71. case FlipWorldSubmenuIndexGameSubmenu:
  72. free_all_views(app, true, true, true);
  73. if (!alloc_game_submenu(app))
  74. {
  75. FURI_LOG_E(TAG, "Failed to allocate game submenu");
  76. return;
  77. }
  78. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewGameSubmenu);
  79. break;
  80. case FlipWorldSubmenuIndexStory:
  81. game_mode_index = 2; // GAME_MODE_STORY
  82. game_run(app);
  83. break;
  84. case FlipWorldSubmenuIndexPvP:
  85. game_mode_index = 1; // GAME_MODE_PVP
  86. game_run(app);
  87. break;
  88. case FlipWorldSubmenuIndexPvE:
  89. game_mode_index = 0; // GAME_MODE_PVE
  90. game_run(app);
  91. break;
  92. case FlipWorldSubmenuIndexMessage:
  93. // About menu.
  94. free_all_views(app, true, true, true);
  95. if (!alloc_message_view(app, MessageStateAbout))
  96. {
  97. FURI_LOG_E(TAG, "Failed to allocate message view");
  98. return;
  99. }
  100. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewMessage);
  101. break;
  102. case FlipWorldSubmenuIndexSettings:
  103. free_all_views(app, true, true, true);
  104. if (!alloc_submenu_other(app, FlipWorldViewSettings))
  105. {
  106. FURI_LOG_E(TAG, "Failed to allocate settings view");
  107. return;
  108. }
  109. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewSubmenuOther);
  110. break;
  111. case FlipWorldSubmenuIndexWiFiSettings:
  112. free_all_views(app, true, false, true);
  113. if (!alloc_variable_item_list(app, FlipWorldSubmenuIndexWiFiSettings))
  114. {
  115. FURI_LOG_E(TAG, "Failed to allocate variable item list");
  116. return;
  117. }
  118. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList);
  119. break;
  120. case FlipWorldSubmenuIndexGameSettings:
  121. free_all_views(app, true, false, true);
  122. if (!alloc_variable_item_list(app, FlipWorldSubmenuIndexGameSettings))
  123. {
  124. FURI_LOG_E(TAG, "Failed to allocate variable item list");
  125. return;
  126. }
  127. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList);
  128. break;
  129. case FlipWorldSubmenuIndexUserSettings:
  130. free_all_views(app, true, false, true);
  131. if (!alloc_variable_item_list(app, FlipWorldSubmenuIndexUserSettings))
  132. {
  133. FURI_LOG_E(TAG, "Failed to allocate variable item list");
  134. return;
  135. }
  136. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList);
  137. break;
  138. default:
  139. break;
  140. }
  141. }
  142. void callback_updated_wifi_ssid(void *context)
  143. {
  144. FlipWorldApp *app = (FlipWorldApp *)context;
  145. if (!app)
  146. {
  147. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  148. return;
  149. }
  150. // store the entered text
  151. strncpy(app->text_input_buffer, app->text_input_temp_buffer, app->text_input_buffer_size);
  152. // Ensure null-termination
  153. app->text_input_buffer[app->text_input_buffer_size - 1] = '\0';
  154. // save the setting
  155. save_char("WiFi-SSID", app->text_input_buffer);
  156. // update the variable item text
  157. if (app->variable_item_wifi_ssid)
  158. {
  159. variable_item_set_current_value_text(app->variable_item_wifi_ssid, app->text_input_buffer);
  160. // get value of password
  161. char pass[64];
  162. char username[64];
  163. char password[64];
  164. if (load_char("WiFi-Password", pass, sizeof(pass)))
  165. {
  166. if (strlen(pass) > 0 && strlen(app->text_input_buffer) > 0)
  167. {
  168. // save the settings
  169. load_char("Flip-Social-Username", username, sizeof(username));
  170. load_char("Flip-Social-Password", password, sizeof(password));
  171. save_settings(app->text_input_buffer, pass, username, password);
  172. // initialize the http
  173. FlipperHTTP *fhttp = flipper_http_alloc();
  174. if (fhttp)
  175. {
  176. // save the wifi if the device is connected
  177. if (!flipper_http_save_wifi(fhttp, app->text_input_buffer, pass))
  178. {
  179. easy_flipper_dialog("FlipperHTTP Error", "Ensure your WiFi Developer\nBoard or Pico W is connected\nand the latest FlipperHTTP\nfirmware is installed.");
  180. }
  181. // free the resources
  182. flipper_http_free(fhttp);
  183. }
  184. else
  185. {
  186. easy_flipper_dialog("FlipperHTTP Error", "The UART is likely busy.\nEnsure you have the correct\nflash for your board then\nrestart your Flipper Zero.");
  187. }
  188. }
  189. }
  190. }
  191. // switch to the settings view
  192. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList);
  193. }
  194. void callback_updated_wifi_pass(void *context)
  195. {
  196. FlipWorldApp *app = (FlipWorldApp *)context;
  197. if (!app)
  198. {
  199. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  200. return;
  201. }
  202. // store the entered text
  203. strncpy(app->text_input_buffer, app->text_input_temp_buffer, app->text_input_buffer_size);
  204. // Ensure null-termination
  205. app->text_input_buffer[app->text_input_buffer_size - 1] = '\0';
  206. // save the setting
  207. save_char("WiFi-Password", app->text_input_buffer);
  208. // update the variable item text
  209. if (app->variable_item_wifi_pass)
  210. {
  211. // variable_item_set_current_value_text(app->variable_item_wifi_pass, app->text_input_buffer);
  212. }
  213. // get value of ssid
  214. char ssid[64];
  215. char username[64];
  216. char password[64];
  217. if (load_char("WiFi-SSID", ssid, sizeof(ssid)))
  218. {
  219. if (strlen(ssid) > 0 && strlen(app->text_input_buffer) > 0)
  220. {
  221. // save the settings
  222. load_char("Flip-Social-Username", username, sizeof(username));
  223. load_char("Flip-Social-Password", password, sizeof(password));
  224. save_settings(ssid, app->text_input_buffer, username, password);
  225. // initialize the http
  226. FlipperHTTP *fhttp = flipper_http_alloc();
  227. if (fhttp)
  228. {
  229. // save the wifi if the device is connected
  230. if (!flipper_http_save_wifi(fhttp, ssid, app->text_input_buffer))
  231. {
  232. easy_flipper_dialog("FlipperHTTP Error", "Ensure your WiFi Developer\nBoard or Pico W is connected\nand the latest FlipperHTTP\nfirmware is installed.");
  233. }
  234. // free the resources
  235. flipper_http_free(fhttp);
  236. }
  237. else
  238. {
  239. easy_flipper_dialog("FlipperHTTP Error", "The UART is likely busy.\nEnsure you have the correct\nflash for your board then\nrestart your Flipper Zero.");
  240. }
  241. }
  242. }
  243. // switch to the settings view
  244. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList);
  245. }
  246. void callback_updated_username(void *context)
  247. {
  248. FlipWorldApp *app = (FlipWorldApp *)context;
  249. if (!app)
  250. {
  251. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  252. return;
  253. }
  254. // store the entered text
  255. strncpy(app->text_input_buffer, app->text_input_temp_buffer, app->text_input_buffer_size);
  256. // Ensure null-termination
  257. app->text_input_buffer[app->text_input_buffer_size - 1] = '\0';
  258. // save the setting
  259. save_char("Flip-Social-Username", app->text_input_buffer);
  260. // update the variable item text
  261. if (app->variable_item_user_username)
  262. {
  263. variable_item_set_current_value_text(app->variable_item_user_username, app->text_input_buffer);
  264. }
  265. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList); // back to user settings
  266. }
  267. void callback_updated_password(void *context)
  268. {
  269. FlipWorldApp *app = (FlipWorldApp *)context;
  270. if (!app)
  271. {
  272. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  273. return;
  274. }
  275. // store the entered text
  276. strncpy(app->text_input_buffer, app->text_input_temp_buffer, app->text_input_buffer_size);
  277. // Ensure null-termination
  278. app->text_input_buffer[app->text_input_buffer_size - 1] = '\0';
  279. // save the setting
  280. save_char("Flip-Social-Password", app->text_input_buffer);
  281. // update the variable item text
  282. if (app->variable_item_user_password)
  283. {
  284. variable_item_set_current_value_text(app->variable_item_user_password, app->text_input_buffer);
  285. }
  286. // get value of username
  287. char username[64];
  288. char ssid[64];
  289. char pass[64];
  290. if (load_char("Flip-Social-Username", username, sizeof(username)))
  291. {
  292. if (strlen(username) > 0 && strlen(app->text_input_buffer) > 0)
  293. {
  294. // save the settings
  295. load_char("WiFi-SSID", ssid, sizeof(ssid));
  296. load_char("WiFi-Password", pass, sizeof(pass));
  297. save_settings(ssid, pass, username, app->text_input_buffer);
  298. }
  299. }
  300. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewVariableItemList); // back to user settings
  301. }
  302. void callback_wifi_settings_select(void *context, uint32_t index)
  303. {
  304. FlipWorldApp *app = (FlipWorldApp *)context;
  305. if (!app)
  306. {
  307. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  308. return;
  309. }
  310. char ssid[64];
  311. char pass[64];
  312. char username[64];
  313. char password[64];
  314. switch (index)
  315. {
  316. case 0: // Input SSID
  317. free_all_views(app, false, false, true);
  318. if (!alloc_text_input_view(app, "SSID"))
  319. {
  320. FURI_LOG_E(TAG, "Failed to allocate text input view");
  321. return;
  322. }
  323. // load SSID
  324. if (load_settings(ssid, sizeof(ssid), pass, sizeof(pass), username, sizeof(username), password, sizeof(password)))
  325. {
  326. strncpy(app->text_input_temp_buffer, ssid, app->text_input_buffer_size - 1);
  327. app->text_input_temp_buffer[app->text_input_buffer_size - 1] = '\0';
  328. }
  329. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewTextInput);
  330. break;
  331. case 1: // Input Password
  332. free_all_views(app, false, false, true);
  333. if (!alloc_text_input_view(app, "Password"))
  334. {
  335. FURI_LOG_E(TAG, "Failed to allocate text input view");
  336. return;
  337. }
  338. // load password
  339. if (load_settings(ssid, sizeof(ssid), pass, sizeof(pass), username, sizeof(username), password, sizeof(password)))
  340. {
  341. strncpy(app->text_input_temp_buffer, pass, app->text_input_buffer_size - 1);
  342. app->text_input_temp_buffer[app->text_input_buffer_size - 1] = '\0';
  343. }
  344. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewTextInput);
  345. break;
  346. default:
  347. FURI_LOG_E(TAG, "Unknown configuration item index");
  348. break;
  349. }
  350. }
  351. void callback_fps_change(VariableItem *item)
  352. {
  353. uint8_t index = variable_item_get_current_value_index(item);
  354. fps_index = index;
  355. variable_item_set_current_value_text(item, fps_choices_str[index]);
  356. variable_item_set_current_value_index(item, index);
  357. save_char("Game-FPS", fps_choices_str[index]);
  358. }
  359. void callback_screen_on_change(VariableItem *item)
  360. {
  361. uint8_t index = variable_item_get_current_value_index(item);
  362. screen_always_on_index = index;
  363. variable_item_set_current_value_text(item, yes_or_no_choices[index]);
  364. variable_item_set_current_value_index(item, index);
  365. save_char("Game-Screen-Always-On", yes_or_no_choices[index]);
  366. }
  367. void callback_sound_on_change(VariableItem *item)
  368. {
  369. uint8_t index = variable_item_get_current_value_index(item);
  370. sound_on_index = index;
  371. variable_item_set_current_value_text(item, yes_or_no_choices[index]);
  372. variable_item_set_current_value_index(item, index);
  373. save_char("Game-Sound-On", yes_or_no_choices[index]);
  374. }
  375. void callback_vibration_on_change(VariableItem *item)
  376. {
  377. uint8_t index = variable_item_get_current_value_index(item);
  378. vibration_on_index = index;
  379. variable_item_set_current_value_text(item, yes_or_no_choices[index]);
  380. variable_item_set_current_value_index(item, index);
  381. save_char("Game-Vibration-On", yes_or_no_choices[index]);
  382. }
  383. void callback_player_on_change(VariableItem *item)
  384. {
  385. uint8_t index = variable_item_get_current_value_index(item);
  386. player_sprite_index = index;
  387. variable_item_set_current_value_text(item, is_str(player_sprite_choices[index], "naked") ? "None" : player_sprite_choices[index]);
  388. variable_item_set_current_value_index(item, index);
  389. save_char("Game-Player-Sprite", player_sprite_choices[index]);
  390. }
  391. void callback_vgm_x_change(VariableItem *item)
  392. {
  393. uint8_t index = variable_item_get_current_value_index(item);
  394. vgm_x_index = index;
  395. variable_item_set_current_value_text(item, vgm_levels[index]);
  396. variable_item_set_current_value_index(item, index);
  397. save_char("Game-VGM-X", vgm_levels[index]);
  398. }
  399. void callback_vgm_y_change(VariableItem *item)
  400. {
  401. uint8_t index = variable_item_get_current_value_index(item);
  402. vgm_y_index = index;
  403. variable_item_set_current_value_text(item, vgm_levels[index]);
  404. variable_item_set_current_value_index(item, index);
  405. save_char("Game-VGM-Y", vgm_levels[index]);
  406. }
  407. static bool _fetch_worlds(DataLoaderModel *model)
  408. {
  409. if (!model || !model->fhttp)
  410. {
  411. FURI_LOG_E(TAG, "model or fhttp is NULL");
  412. return false;
  413. }
  414. char directory_path[128];
  415. snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_world");
  416. Storage *storage = furi_record_open(RECORD_STORAGE);
  417. storage_common_mkdir(storage, directory_path);
  418. snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_world/worlds");
  419. storage_common_mkdir(storage, directory_path);
  420. furi_record_close(RECORD_STORAGE);
  421. snprintf(model->fhttp->file_path, sizeof(model->fhttp->file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_world/worlds/world_list_full.json");
  422. model->fhttp->save_received_data = true;
  423. return flipper_http_request(model->fhttp, GET, "https://www.jblanked.com/flipper/api/world/v5/get/10/", "{\"Content-Type\":\"application/json\"}", NULL);
  424. }
  425. static char *_parse_worlds(DataLoaderModel *model)
  426. {
  427. UNUSED(model);
  428. return "World Pack Installed";
  429. }
  430. static void switch_to_view_get_worlds(FlipWorldApp *app)
  431. {
  432. if (!loader_view_alloc(app))
  433. {
  434. FURI_LOG_E(TAG, "Failed to allocate view loader");
  435. return;
  436. }
  437. loader_switch_to_view(app, "Fetching World Pack..", _fetch_worlds, _parse_worlds, 1, callback_to_submenu, FlipWorldViewLoader);
  438. }
  439. void callback_game_settings_select(void *context, uint32_t index)
  440. {
  441. FlipWorldApp *app = (FlipWorldApp *)context;
  442. if (!app)
  443. {
  444. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  445. return;
  446. }
  447. switch (index)
  448. {
  449. case 0: // Download all world data as one huge json
  450. switch_to_view_get_worlds(app);
  451. case 1: // Player Sprite
  452. break;
  453. case 2: // Change FPS
  454. break;
  455. case 3: // VGM X
  456. break;
  457. case 4: // VGM Y
  458. break;
  459. case 5: // Screen Always On
  460. break;
  461. case 6: // Sound On
  462. break;
  463. case 7: // Vibration On
  464. break;
  465. }
  466. }
  467. void callback_user_settings_select(void *context, uint32_t index)
  468. {
  469. FlipWorldApp *app = (FlipWorldApp *)context;
  470. if (!app)
  471. {
  472. FURI_LOG_E(TAG, "FlipWorldApp is NULL");
  473. return;
  474. }
  475. switch (index)
  476. {
  477. case 0: // Username
  478. free_all_views(app, false, false, true);
  479. if (!alloc_text_input_view(app, "Username-Login"))
  480. {
  481. FURI_LOG_E(TAG, "Failed to allocate text input view");
  482. return;
  483. }
  484. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewTextInput);
  485. break;
  486. case 1: // Password
  487. free_all_views(app, false, false, true);
  488. if (!alloc_text_input_view(app, "Password-Login"))
  489. {
  490. FURI_LOG_E(TAG, "Failed to allocate text input view");
  491. return;
  492. }
  493. view_dispatcher_switch_to_view(app->view_dispatcher, FlipWorldViewTextInput);
  494. break;
  495. }
  496. }
  497. void callback_submenu_lobby_choices(void *context, uint32_t index)
  498. {
  499. /* Handle other game lobbies
  500. 1. when clicked on, send request to fetch the selected game lobby details
  501. 2. start the websocket session
  502. 3. start the game thread (the rest will be handled by game_start and player_update)
  503. */
  504. FlipWorldApp *app = (FlipWorldApp *)context;
  505. furi_check(app, "FlipWorldApp is NULL");
  506. if (index >= FlipWorldSubmenuIndexLobby && index < FlipWorldSubmenuIndexLobby + 10)
  507. {
  508. lobby_index = index - FlipWorldSubmenuIndexLobby;
  509. FlipperHTTP *fhttp = flipper_http_alloc();
  510. if (!fhttp)
  511. {
  512. FURI_LOG_E(TAG, "Failed to allocate FlipperHTTP");
  513. easy_flipper_dialog("Error", "Failed to allocate FlipperHTTP. Press BACK to return.");
  514. return;
  515. }
  516. // fetch the lobby details
  517. if (!game_fetch_lobby(fhttp, lobby_list[lobby_index]))
  518. {
  519. FURI_LOG_E(TAG, "Failed to fetch lobby details");
  520. easy_flipper_dialog("Error", "Failed to fetch lobby details. Press BACK to return.");
  521. flipper_http_free(fhttp);
  522. return;
  523. }
  524. // load the lobby details
  525. FuriString *lobby = flipper_http_load_from_file(fhttp->file_path);
  526. if (!lobby)
  527. {
  528. FURI_LOG_E(TAG, "Failed to load lobby details");
  529. flipper_http_free(fhttp);
  530. return;
  531. }
  532. // if there are no players, add the user to the lobby and make the user wait until another player joins
  533. // if there is one player and it's the user, make the user wait until another player joins
  534. // if there is one player and it's not the user, parse_lobby and start websocket
  535. // if there are 2 players (which there shouldn't be at this point), show an error message saying the lobby is full
  536. switch (game_lobby_count(fhttp, lobby))
  537. {
  538. case -1:
  539. FURI_LOG_E(TAG, "Failed to get player count");
  540. easy_flipper_dialog("Error", "Failed to get player count. Press BACK to return.");
  541. flipper_http_free(fhttp);
  542. furi_string_free(lobby);
  543. return;
  544. case 0:
  545. // add the user to the lobby
  546. if (!game_join_lobby(fhttp, lobby_list[lobby_index]))
  547. {
  548. FURI_LOG_E(TAG, "Failed to join lobby");
  549. easy_flipper_dialog("Error", "Failed to join lobby. Press BACK to return.");
  550. flipper_http_free(fhttp);
  551. furi_string_free(lobby);
  552. return;
  553. }
  554. // send the user to the waiting screen
  555. game_waiting_lobby(app);
  556. return;
  557. case 1:
  558. // check if the user is in the lobby
  559. if (game_in_lobby(fhttp, lobby))
  560. {
  561. // send the user to the waiting screen
  562. FURI_LOG_I(TAG, "User is in the lobby");
  563. flipper_http_free(fhttp);
  564. furi_string_free(lobby);
  565. game_waiting_lobby(app);
  566. return;
  567. }
  568. // add the user to the lobby
  569. if (!game_join_lobby(fhttp, lobby_list[lobby_index]))
  570. {
  571. FURI_LOG_E(TAG, "Failed to join lobby");
  572. easy_flipper_dialog("Error", "Failed to join lobby. Press BACK to return.");
  573. flipper_http_free(fhttp);
  574. furi_string_free(lobby);
  575. return;
  576. }
  577. break;
  578. case 2:
  579. // show an error message saying the lobby is full
  580. FURI_LOG_E(TAG, "Lobby is full");
  581. easy_flipper_dialog("Error", "Lobby is full. Press BACK to return.");
  582. flipper_http_free(fhttp);
  583. furi_string_free(lobby);
  584. return;
  585. };
  586. game_start_pvp(fhttp, lobby, app); // this will free both the fhttp and lobby, and start the game
  587. }
  588. }