#ifndef TERRAIN_WORLD_H #define TERRAIN_WORLD_H #include "core/config/engine.h" #include "core/containers/hash_map.h" #include "../defines.h" #include "scene/main/spatial.h" #include "../areas/terrain_world_area.h" #include "../level_generator/terrain_level_generator.h" #include "../library/terrain_library.h" #include "core/os/os.h" #include "modules/modules_enabled.gen.h" #ifdef MODULE_PROPS_ENABLED #include "../../props/props/prop_data.h" #endif class TerrainStructure; class TerrainChunk; class PropData; class TerrainWorld : public Spatial { GDCLASS(TerrainWorld, Spatial); public: enum ChannelTypeInfo { CHANNEL_TYPE_INFO_TYPE = 0, CHANNEL_TYPE_INFO_ISOLEVEL, CHANNEL_TYPE_INFO_LIQUID_FLOW, }; enum { NOTIFICATION_ACTIVE_STATE_CHANGED = 9000, }; static const String BINDING_STRING_CHANNEL_TYPE_INFO; public: bool get_active() const; void set_active(const bool value); bool get_editable() const; void set_editable(const bool value); int get_chunk_size_x() const; void set_chunk_size_x(const int value); int get_chunk_size_z() const; void set_chunk_size_z(const int value); int get_data_margin_start() const; void set_data_margin_start(const int value); int get_data_margin_end() const; void set_data_margin_end(const int value); int get_current_seed() const; void set_current_seed(const int value); float get_world_height() const; void set_world_height(const float value); int get_max_concurrent_generations(); void set_max_concurrent_generations(const int value); Ref get_library(); void set_library(const Ref &library); Ref get_level_generator() const; void set_level_generator(const Ref &level_generator); float get_voxel_scale() const; void set_voxel_scale(const float value); int get_chunk_spawn_range() const; void set_chunk_spawn_range(const int value); NodePath get_player_path() const; void set_player_path(const NodePath &player_path); Spatial *get_player() const; void set_player(Spatial *player); void set_player_bind(Node *player); //World Areas Ref world_area_get(const int index) const; void world_area_add(const Ref &area); void world_area_remove(const int index); void world_areas_clear(); int world_area_get_count() const; //Terra Structures Ref voxel_structure_get(const int index) const; void voxel_structure_add(const Ref &structure); void voxel_structure_remove(const Ref &structure); void voxel_structure_remove_index(const int index); void voxel_structures_clear(); int voxel_structure_get_count() const; void voxel_structure_add_at_position(Ref structure, const Vector3 &world_position); Vector voxel_structures_get(); void voxel_structures_set(const Vector &structures); //Chunks void chunk_add(Ref chunk, const int x, const int z); bool chunk_has(const int x, const int z) const; Ref chunk_get(const int x, const int z); Ref chunk_remove(const int x, const int z); Ref chunk_remove_index(const int index); Ref chunk_get_index(const int index); int chunk_get_count() const; void chunks_clear(); Ref chunk_get_or_create(const int x, const int z); Ref chunk_create(const int x, const int z); void chunk_setup(Ref chunk); void chunk_generate(Ref chunk); Vector chunks_get(); void chunks_set(const Vector &chunks); bool can_chunk_do_build_step(); bool is_position_walkable(const Vector3 &p_pos); void on_chunk_mesh_generation_finished(Ref p_chunk); void generation_queue_add_to(const Ref &chunk); Ref generation_queue_get_index(const int index); void generation_queue_remove_index(const int index); int generation_queue_get_size() const; void generation_add_to(const Ref &chunk); Ref generation_get_index(const int index); void generation_remove_index(const int index); int generation_get_size() const; #ifdef MODULE_PROPS_ENABLED void prop_add(Transform transform, const Ref &prop, const bool apply_voxel_scale = true); #endif //Lights void light_add(const Ref &light); Ref light_get(const int index); void light_remove(const int index); int light_get_count() const; void lights_clear(); Vector lights_get(); void lights_set(const Vector &chunks); //Helpers uint8_t get_voxel_at_world_position(const Vector3 &world_position, const int channel_index); void set_voxel_at_world_position(const Vector3 &world_position, const uint8_t data, const int channel_index, const bool rebuild = true); Ref get_chunk_at_world_position(const Vector3 &world_position); Ref get_or_create_chunk_at_world_position(const Vector3 &world_position); void set_voxel_with_tool(const bool mode_add, const Vector3 hit_position, const Vector3 hit_normal, const int selected_voxel, const int isolevel); int get_channel_index_info(const ChannelTypeInfo channel_type); Spatial *get_editor_camera(); TerrainWorld(); ~TerrainWorld(); protected: virtual void _generate_chunk(Ref chunk); virtual Ref _create_chunk(int x, int z, Ref p_chunk); virtual int _get_channel_index_info(const ChannelTypeInfo channel_type); virtual void _set_voxel_with_tool(const bool mode_add, const Vector3 hit_position, const Vector3 hit_normal, const int selected_voxel, const int isolevel); virtual void _notification(int p_what); static void _bind_methods(); public: struct IntPos { int x; int z; IntPos() { x = 0; z = 0; } IntPos(int p_x, int p_z) { x = p_x; z = p_z; } IntPos(const Vector2 &p) { x = p.x; z = p.y; } }; struct IntPosHasher { static _FORCE_INLINE_ uint32_t hash(const IntPos &v) { uint32_t hash = hash_djb2_one_32(v.x); hash = hash_djb2_one_32(v.x, hash); return hash_djb2_one_32(v.z, hash); } }; private: bool _active; bool _editable; bool _is_priority_generation; int _chunk_size_x; int _chunk_size_z; int _current_seed; int _data_margin_start; int _data_margin_end; float _world_height; Ref _library; Ref _level_generator; float _voxel_scale; int _chunk_spawn_range; HashMap, IntPosHasher> _chunks; Vector> _chunks_vector; Vector> _world_areas; Vector> _voxel_structures; NodePath _player_path; Spatial *_player; int _max_concurrent_generations; Vector> _generation_queue; Vector> _generating; int _max_frame_chunk_build_steps; int _num_frame_chunk_build_steps; Vector> _lights; }; _FORCE_INLINE_ bool operator==(const TerrainWorld::IntPos &a, const TerrainWorld::IntPos &b) { return a.x == b.x && a.z == b.z; } VARIANT_ENUM_CAST(TerrainWorld::ChannelTypeInfo); #endif