#ifndef GAME_ROOT_HPP #define GAME_ROOT_HPP #include #include #include #include #include #include #include #include "game_mode.hpp" #include "level.hpp" namespace godot { class PlayerInput; class IPlayer; class SpawnPoint3D; class GameRoot : public Node { GDCLASS(GameRoot, Node); static void _bind_methods(); public: // get the current active singleton instance of GameRoot static GameRoot *get_singleton(); // returns true if there is currently a singleton active for GameRoot static bool has_singleton(); virtual void _enter_tree() override; virtual void _exit_tree() override; void player_input_connected(); // force-disconnect a player // calls queue_free on the IPlayer instance void player_removed(uint32_t player_id); // initialize and register a player instance bool initialize_player(IPlayer *player, uint32_t id); // shorthand for set_game_mode(Ref()) // unsets the gamemode void reset_game_mode(); // override the current gamemode // force-respawns all players void set_game_mode(Ref prototype); protected: // attempt to make 'this' the current singleton instance void grab_singleton(); // attempt to stop being the active singleton instance // only works if the current singleton is 'this' void release_singleton(); uint32_t find_empty_player_slot() const; virtual IPlayer *spawn_player(uint32_t id); protected: static GameRoot *singleton_instance; uint32_t next_player_id{1}; // 0 is the "invalid" player id HashMap> players{}; Ref game_mode{}; }; class GameRoot3D : public GameRoot { GDCLASS(GameRoot3D, GameRoot); static void _bind_methods(); public: virtual void _ready() override; // shorthand for load_level(level, Transform3D()) Level3D *load_level(Ref level); // 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 Level3D *load_level_at(Ref level, Transform3D at); // register a spawnpoint for use when spawning players void register_spawn_point(SpawnPoint3D *spawn_point); // remove a spawnpoint so it can't be used to spawn players void unregister_spawn_point(SpawnPoint3D *spawn_point); // ----- getter / setters ----- void set_first_boot_level(Ref level); Ref get_first_boot_level() const; protected: virtual IPlayer *spawn_player(uint32_t id) override; static bool is_valid_level(Ref &level); private: HashMap levels{}; HashSet spawn_points{}; Ref first_boot_level{}; }; } #endif // !GAME_ROOT_HPP