fix: error in game root reloading

stripped
Sara 2024-05-21 15:57:55 +02:00
parent dff7631816
commit a9e33a3781
2 changed files with 22 additions and 1 deletions

View File

@ -112,6 +112,7 @@ Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) {
return nullptr; return nullptr;
} }
this->levels.insert(level->get_path(), instance); this->levels.insert(level->get_path(), instance);
instance->connect("tree_exited", callable_mp(this, &GameRoot3D::level_unloaded).bind(level->get_path()));
// store and add to tree at desired transform // store and add to tree at desired transform
// if this is the first level containing a game mode currently active use it's gamemode as a prototype // if this is the first level containing a game mode currently active use it's gamemode as a prototype
bool const switch_game_mode{this->game_mode.is_null()}; bool const switch_game_mode{this->game_mode.is_null()};
@ -120,7 +121,7 @@ Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) {
} }
this->add_child(instance); this->add_child(instance);
instance->set_global_transform(at); instance->set_global_transform(at);
if(switch_game_mode) { if(switch_game_mode && this->game_mode.is_valid()) {
for(KeyValue<uint32_t, Pair<PlayerInput *, IPlayer *>> const &kvp : this->players) { for(KeyValue<uint32_t, Pair<PlayerInput *, IPlayer *>> const &kvp : this->players) {
this->place_player_at_spawnpoint(kvp.value.second); this->place_player_at_spawnpoint(kvp.value.second);
} }
@ -128,6 +129,19 @@ Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) {
return instance; return instance;
} }
void GameRoot3D::unload_all_levels() {
HashMap<StringName, Level3D*> levels = this->get_levels();
for(KeyValue<StringName, Level3D*> &kvp : levels)
kvp.value->call_deferred("queue_free");
this->get_levels().clear();
this->reset_game_mode();
}
void GameRoot3D::replace_levels(Ref<PackedScene> scene) {
this->unload_all_levels();
this->load_level(scene);
}
void GameRoot3D::register_spawn_point(SpawnPoint3D *spawn_point) { void GameRoot3D::register_spawn_point(SpawnPoint3D *spawn_point) {
if(this->spawn_points.has(spawn_point)) { if(this->spawn_points.has(spawn_point)) {
UtilityFunctions::push_error("Duplicate attempt to register spawnpoint '", spawn_point->get_path(), "'"); UtilityFunctions::push_error("Duplicate attempt to register spawnpoint '", spawn_point->get_path(), "'");
@ -258,6 +272,10 @@ IPlayer *GameRoot3D::spawn_player(uint32_t id) {
return player; return player;
} }
void GameRoot3D::level_unloaded(StringName scene_path) {
this->levels.erase(scene_path);
}
bool GameRoot3D::is_valid_level(Ref<PackedScene> &level) { bool GameRoot3D::is_valid_level(Ref<PackedScene> &level) {
if(level.is_null() || !level.is_valid() || !level->can_instantiate()) { if(level.is_null() || !level.is_valid() || !level->can_instantiate()) {
UtilityFunctions::push_error("Can't load level from invalid packed scene"); UtilityFunctions::push_error("Can't load level from invalid packed scene");

View File

@ -49,6 +49,8 @@ public:
// load a level, only works if 'level' is a valid scene where the root Node can cast to 'Level3D' // load a level, only works if 'level' is a valid scene where the root Node can cast to 'Level3D'
// sets the level's root node's global transform // sets the level's root node's global transform
Level3D *load_level_at(Ref<PackedScene> level, Transform3D at); Level3D *load_level_at(Ref<PackedScene> level, Transform3D at);
void unload_all_levels();
void replace_levels(Ref<PackedScene> level);
// register a spawnpoint for use when spawning players // register a spawnpoint for use when spawning players
void register_spawn_point(SpawnPoint3D *spawn_point); void register_spawn_point(SpawnPoint3D *spawn_point);
@ -74,6 +76,7 @@ protected:
void release_singleton(); void release_singleton();
uint32_t find_empty_player_slot() const; uint32_t find_empty_player_slot() const;
IPlayer *spawn_player(uint32_t id); IPlayer *spawn_player(uint32_t id);
void level_unloaded(StringName scene_path);
static bool is_valid_level(Ref<PackedScene> &level); static bool is_valid_level(Ref<PackedScene> &level);
protected: protected:
static GameRoot3D *singleton_instance; static GameRoot3D *singleton_instance;