callback.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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 message_input_callback(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 message_draw_callback(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. run(app);
  83. break;
  84. case FlipWorldSubmenuIndexPvP:
  85. game_mode_index = 1; // GAME_MODE_PVP
  86. run(app);
  87. break;
  88. case FlipWorldSubmenuIndexPvE:
  89. game_mode_index = 0; // GAME_MODE_PVE
  90. 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 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 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 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 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 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 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 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 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 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 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 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 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. 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 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 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. }