2024-03-13 15:08:37 +00:00
|
|
|
#ifndef GAME_ROOT_HPP
|
|
|
|
#define GAME_ROOT_HPP
|
|
|
|
|
2024-03-17 13:49:35 +00:00
|
|
|
#include "game_mode.hpp"
|
|
|
|
#include "level.hpp"
|
2024-03-13 15:08:37 +00:00
|
|
|
#include <godot_cpp/classes/node.hpp>
|
2024-03-17 13:49:35 +00:00
|
|
|
#include <godot_cpp/classes/packed_scene.hpp>
|
2024-03-13 15:08:37 +00:00
|
|
|
#include <godot_cpp/templates/hash_map.hpp>
|
|
|
|
#include <godot_cpp/templates/hash_set.hpp>
|
|
|
|
#include <godot_cpp/templates/pair.hpp>
|
|
|
|
#include <godot_cpp/templates/pair.hpp>
|
2024-03-17 13:49:35 +00:00
|
|
|
#include <godot_cpp/templates/vector.hpp>
|
2024-03-13 15:08:37 +00:00
|
|
|
|
|
|
|
namespace godot {
|
|
|
|
class PlayerInput;
|
|
|
|
class IPlayer;
|
|
|
|
class SpawnPoint3D;
|
|
|
|
|
|
|
|
class GameRoot : public Node {
|
|
|
|
GDCLASS(GameRoot, Node);
|
|
|
|
static void _bind_methods();
|
|
|
|
public:
|
2024-03-16 21:12:11 +00:00
|
|
|
// get the current active singleton instance of GameRoot
|
2024-03-13 15:08:37 +00:00
|
|
|
static GameRoot *get_singleton();
|
2024-03-16 21:12:11 +00:00
|
|
|
// returns true if there is currently a singleton active for GameRoot
|
2024-03-13 15:08:37 +00:00
|
|
|
static bool has_singleton();
|
|
|
|
|
|
|
|
virtual void _enter_tree() override;
|
|
|
|
virtual void _exit_tree() override;
|
|
|
|
|
2024-03-16 21:12:11 +00:00
|
|
|
void player_input_connected();
|
|
|
|
// force-disconnect a player
|
|
|
|
// calls queue_free on the IPlayer instance
|
2024-03-17 13:49:35 +00:00
|
|
|
void remove_player(uint32_t player_id);
|
|
|
|
// calls remove_player for every used player input slot
|
|
|
|
void remove_all_players();
|
2024-03-16 21:12:11 +00:00
|
|
|
// initialize and register a player instance
|
2024-03-17 13:49:35 +00:00
|
|
|
// the player will be added to the tree and AFTER setup_player_input will be called
|
|
|
|
// this way the player can initialize before setting up input
|
2024-03-16 12:02:36 +00:00
|
|
|
bool initialize_player(IPlayer *player, uint32_t id);
|
2024-03-13 15:08:37 +00:00
|
|
|
|
2024-03-16 21:12:11 +00:00
|
|
|
// shorthand for set_game_mode(Ref<GameMode>())
|
|
|
|
// unsets the gamemode
|
2024-03-13 15:08:37 +00:00
|
|
|
void reset_game_mode();
|
2024-03-16 21:12:11 +00:00
|
|
|
// override the current gamemode
|
|
|
|
// force-respawns all players
|
|
|
|
void set_game_mode(Ref<GameMode> prototype);
|
2024-03-20 08:43:48 +00:00
|
|
|
Ref<GameMode> get_game_mode() const;
|
|
|
|
Ref<GameState> get_game_state() const;
|
2024-03-13 15:08:37 +00:00
|
|
|
protected:
|
2024-03-16 21:12:11 +00:00
|
|
|
// attempt to make 'this' the current singleton instance
|
2024-03-13 15:08:37 +00:00
|
|
|
void grab_singleton();
|
2024-03-16 21:12:11 +00:00
|
|
|
// attempt to stop being the active singleton instance
|
|
|
|
// only works if the current singleton is 'this'
|
2024-03-13 15:08:37 +00:00
|
|
|
void release_singleton();
|
2024-03-16 12:02:36 +00:00
|
|
|
uint32_t find_empty_player_slot() const;
|
|
|
|
virtual IPlayer *spawn_player(uint32_t id);
|
2024-03-13 15:08:37 +00:00
|
|
|
protected:
|
|
|
|
static GameRoot *singleton_instance;
|
|
|
|
|
2024-03-16 12:02:36 +00:00
|
|
|
uint32_t next_player_id{1}; // 0 is the "invalid" player id
|
2024-03-13 15:08:37 +00:00
|
|
|
HashMap<uint32_t, Pair<PlayerInput*, IPlayer*>> players{};
|
|
|
|
Ref<GameMode> game_mode{};
|
|
|
|
};
|
|
|
|
|
|
|
|
class GameRoot3D : public GameRoot {
|
|
|
|
GDCLASS(GameRoot3D, GameRoot);
|
|
|
|
static void _bind_methods();
|
|
|
|
public:
|
|
|
|
virtual void _ready() override;
|
2024-03-16 21:12:11 +00:00
|
|
|
// shorthand for load_level(level, Transform3D())
|
2024-03-13 15:08:37 +00:00
|
|
|
Level3D *load_level(Ref<PackedScene> level);
|
2024-03-16 21:12:11 +00:00
|
|
|
// 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
|
2024-03-13 15:08:37 +00:00
|
|
|
Level3D *load_level_at(Ref<PackedScene> level, Transform3D at);
|
|
|
|
|
2024-03-16 21:12:11 +00:00
|
|
|
// register a spawnpoint for use when spawning players
|
2024-03-13 15:08:37 +00:00
|
|
|
void register_spawn_point(SpawnPoint3D *spawn_point);
|
2024-03-16 21:12:11 +00:00
|
|
|
// remove a spawnpoint so it can't be used to spawn players
|
2024-03-13 15:08:37 +00:00
|
|
|
void unregister_spawn_point(SpawnPoint3D *spawn_point);
|
|
|
|
|
2024-03-16 21:12:11 +00:00
|
|
|
// ----- getter / setters -----
|
2024-03-13 15:08:37 +00:00
|
|
|
void set_first_boot_level(Ref<PackedScene> level);
|
|
|
|
Ref<PackedScene> get_first_boot_level() const;
|
2024-03-16 12:02:36 +00:00
|
|
|
protected:
|
|
|
|
virtual IPlayer *spawn_player(uint32_t id) override;
|
2024-03-13 15:08:37 +00:00
|
|
|
static bool is_valid_level(Ref<PackedScene> &level);
|
|
|
|
private:
|
|
|
|
HashMap<StringName, Level3D*> levels{};
|
|
|
|
HashSet<SpawnPoint3D*> spawn_points{};
|
|
|
|
|
|
|
|
Ref<PackedScene> first_boot_level{};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // !GAME_ROOT_HPP
|