level.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #include <game/level.h>
  2. static void level_start(Level *level, GameManager *manager, void *context)
  3. {
  4. UNUSED(manager);
  5. level_clear(level);
  6. player_spawn(level, manager);
  7. LevelContext *level_context = context;
  8. // check if the world exists
  9. if (!world_exists(level_context->id))
  10. {
  11. FURI_LOG_E("Game", "World does not exist.. downloading now");
  12. if (!level_context->app)
  13. {
  14. level_context->app = (FlipWorldApp *)malloc(sizeof(FlipWorldApp));
  15. if (!level_context->app)
  16. {
  17. FURI_LOG_E("Game", "Failed to allocate FlipWorldApp");
  18. free(level_context->app);
  19. level_context->app = NULL;
  20. return;
  21. }
  22. }
  23. FuriString *world_data = fetch_world(level_context->id, level_context->app);
  24. if (!world_data)
  25. {
  26. FURI_LOG_E("Game", "Failed to fetch world data");
  27. draw_town_world(level);
  28. free(level_context->app);
  29. level_context->app = NULL;
  30. furi_string_free(world_data);
  31. return;
  32. }
  33. if (!draw_json_world(level, furi_string_get_cstr(world_data)))
  34. {
  35. FURI_LOG_E("Game", "Failed to draw world");
  36. draw_town_world(level);
  37. }
  38. free(level_context->app);
  39. level_context->app = NULL;
  40. furi_string_free(world_data);
  41. return;
  42. }
  43. // get the world data
  44. FuriString *world_data = load_furi_world(level_context->id);
  45. if (!world_data)
  46. {
  47. FURI_LOG_E("Game", "Failed to load world data");
  48. draw_town_world(level);
  49. furi_string_free(world_data);
  50. return;
  51. }
  52. // draw the world
  53. if (!draw_json_world(level, furi_string_get_cstr(world_data)))
  54. {
  55. FURI_LOG_E("Game", "World exists but failed to draw.");
  56. draw_town_world(level);
  57. }
  58. furi_string_free(world_data);
  59. }
  60. static LevelContext *level_context_generic;
  61. static LevelContext *level_generic_alloc(const char *id, int index)
  62. {
  63. if (!level_context_generic)
  64. {
  65. level_context_generic = malloc(sizeof(LevelContext));
  66. }
  67. snprintf(level_context_generic->id, sizeof(level_context_generic->id), "%s", id);
  68. level_context_generic->index = index;
  69. level_context_generic->app = NULL;
  70. return level_context_generic;
  71. }
  72. static void level_generic_free()
  73. {
  74. if (level_context_generic)
  75. {
  76. free(level_context_generic);
  77. level_context_generic = NULL;
  78. }
  79. }
  80. static void level_alloc_generic_world(Level *level, GameManager *manager, void *context)
  81. {
  82. UNUSED(manager);
  83. UNUSED(level);
  84. if (!level_context_generic)
  85. {
  86. FURI_LOG_E("Game", "Generic level context not set");
  87. return;
  88. }
  89. LevelContext *level_context = context;
  90. snprintf(level_context->id, sizeof(level_context->id), "%s", level_context_generic->id);
  91. level_context->index = level_context_generic->index;
  92. level_context->app = level_context_generic->app;
  93. }
  94. // Do NOT touch (this is for dynamic level creation)
  95. const LevelBehaviour _generic_level = {
  96. .alloc = level_alloc_generic_world, // called once, when level allocated
  97. .free = NULL, // called once, when level freed
  98. .start = level_start, // called when level is changed to this level
  99. .stop = NULL, // called when level is changed from this level
  100. .context_size = sizeof(LevelContext), // size of level context, will be automatically allocated and freed
  101. };
  102. const LevelBehaviour *generic_level(const char *id, int index)
  103. {
  104. level_generic_free();
  105. level_context_generic = level_generic_alloc(id, index);
  106. return &_generic_level;
  107. }