#include #include typedef struct tc_world_registry { u32_t worlds_capacity; u32_t num_worlds; tc_world_s *worlds; } tc_world_registry_s; typedef struct tc_world_updater { bool_t running; tc_world_updater_queue_s queue; tc_world_registry_s world_registry; SDL_Thread *sdl_thread; } tc_world_updater_s; tc_world_updater_s *tc_world_updater_g = NULL; #define TICKS_PER_SECOND 2 #define WORLD_UPDATES_PER_SECOND 0.5 void tc_update_all_worlds(tc_world_registry_s *registry) { for(u32_t world_index = 0; world_index < registry->num_worlds; ++world_index) { tc_world_s *world = ®istry->worlds[world_index]; tc_update_world(world); } } void tc_world_updater_run(void *data) { u64_t tick_at_start = 0; u64_t world_update_count = 0; tc_world_updater_s *updater = data; updater->running = TRUE; while(updater->running) { tick_at_start = SDL_GetTicks(); if((tick_at_start / WORLD_UPDATES_PER_SECOND) == world_update_count) { ++world_update_count; } if(tc_world_updater_g->queue.in_action) { while(tc_world_updater_g->queue.in_action) continue; } tc_world_updater_command_s command = tc_world_updater_query_next_command(&tc_world_updater_g->queue); switch(command.type) { case TC_WORLD_UPDATER_COMMAND_UNKNOWN: break; case TC_WORLD_UPDATER_COMMAND_MOVE_CHUNKLOADER: tc_worldupdater_execute_move_chunkloader(command); case TC_WORLD_UPDATER_COMMAND_PLACE_BLOCK: tc_worldupdater_execute_place_block(command); case TC_WORLD_UPDATER_COMMAND_STOP: tc_worldupdater_execute_stop(command); case TC_WORLD_UPDATER_COMMAND_ADD_WORLD: tc_worldupdater_execute_add_world(command); case TC_WORLD_UPDATER_COMMAND_ADD_CHUNKLOADER: tc_worldupdater_execute_add_chunkloader(command); case TC_WORLD_UPDATER_COMMAND_DELETE_CHUNKLOADER: tc_worldupdater_execute_delete_chunkloader(command); case TC_WORLD_UPDATER_COMMAND_GET_WORLD: tc_worldupdater_execute_get_world(command); case TC_WORLD_UPDATER_COMMAND_GET_CHUNKLOADER: tc_worldupdater_execute_get_chunkloader(command); case TC_WORLD_UPDATER_COMMAND_GET_CHUNKLIST: tc_worldupdater_execute_get_chunklist(command); } u64_t tick_at_end = SDL_GetTicks(); SDL_Delay((1000 / TICKS_PER_SECOND) - (tick_at_end - tick_at_start)); } } tc_world_registry_s tc_new_world_registry() { tc_world_registry_s registry; registry.num_worlds = 0; registry.worlds_capacity = 64; registry.worlds = calloc(sizeof(tc_world_s), registry.worlds_capacity); return registry; } void tc_start_world_updater() { tc_worldupdate_initialize_promises(4096); tc_world_updater_g = malloc(sizeof(tc_world_updater_s)); tc_world_updater_g->world_registry = tc_new_world_registry(); tc_world_updater_g->sdl_thread = SDL_CreateThread((SDL_ThreadFunction) &tc_world_updater_run, "w_update", &tc_world_updater_g); tc_world_updater_g->queue = tc_new_world_updater_queue(4096); SDL_DetachThread(tc_world_updater_g->sdl_thread); } tc_promise_s tc_worldupdate_register_world() { tc_promise_s promise = tc_worldupdate_reserve_world_promise(); return promise; } tc_promise_s tc_worldupdate_add_chunkloader() { tc_promise_s promise = tc_worldupdate_reserve_chunkloader_promise(); tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_ADD_CHUNKLOADER; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); return promise; } void tc_worldupdate_delete_chunkloader(u32_t loader_id) { tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_DELETE_CHUNKLOADER; command.specific.get_item.index = loader_id; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); } u32_t tc_worldupdate_get_chunkloader_count_of_world(u32_t world_id) { return 0; // TODO } u32_t tc_worldupdate_get_world_count() { return 0; // TODO } tc_promise_s tc_worldupdate_get_world(u32_t index) { tc_promise_s promise = tc_worldupdate_reserve_world_promise(); tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_GET_WORLD; command.specific.get_item.index = index; command.specific.get_item.promise = promise.identifier; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); return promise; } tc_promise_s tc_worldupdate_get_chunkloader_of_world(u32_t world_id, u32_t index) { tc_promise_s promise = tc_worldupdate_reserve_chunkloader_promise(); tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_GET_CHUNKLOADER; command.specific.get_item.index = index; command.specific.get_item.promise = promise.identifier; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); return promise; } tc_promise_s tc_worldupdate_get_chunks_of_chunkloader(u32_t loader_id) { tc_promise_s promise = tc_worldupdate_reserve_chunklist_promise(); tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_GET_CHUNKLIST; command.specific.get_item.index = loader_id; command.specific.get_item.promise = promise.identifier; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); return promise; } void tc_worldupdate_move_chunkloader_to(u32_t loader_id, tc_chunk_location_s location) { tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_MOVE_CHUNKLOADER; command.specific.move_chunkloader.loader_id = loader_id; command.specific.move_chunkloader.new_location = location; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); } void tc_worldupdate_place_block(tc_block_location_s location, tc_block_s block) { tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_PLACE_BLOCK; command.specific.place_block.location = location; command.specific.place_block.block = block; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); } void tc_worldupdate_stop() { tc_world_updater_command_s command; command.type = TC_WORLD_UPDATER_COMMAND_STOP; tc_issue_world_updater_command(&tc_world_updater_g->queue, command); }