diff --git a/.gitignore b/.gitignore index 4135e0d8..bfc45cfa 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,9 @@ extension_api.json .vscode/ build +builds/ -testing.* -testing +docs/build +world/ -world/ \ No newline at end of file +testing.* diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 00000000..0f166552 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,9 @@ +PROJECT_NAME = "CavernServer" +OUTPUT_DIRECTORY = builds/docs + +GENERATE_XML = YES +XML_OUTPUT = xml +GENERATE_HTML = NO +FILE_PATTERNS = *.c *.h *.hpp +INPUT = src includes +RECURSIVE = YES \ No newline at end of file diff --git a/docs.sh b/docs.sh new file mode 100644 index 00000000..141cd7b0 --- /dev/null +++ b/docs.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +mkdir -p builds/docs + +doxygen Doxyfile + +cd docs +sphinx-build -b html source build/html \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d0c3cbf1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..dc1312ab --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/doxygen.css b/docs/source/_static/doxygen.css new file mode 100644 index 00000000..d9f2b051 --- /dev/null +++ b/docs/source/_static/doxygen.css @@ -0,0 +1,30 @@ +.doxygenindex, +.doxygenclass, +.doxygennamespace, +.doxygenfile, +.doxygenfunction, +.doxygengroup, +.doxygenstruct { + margin-top: 2rem !important; + margin-bottom: 2rem !important; + line-height: 1.6; +} + +.doxygenindex p, +.doxygenclass p, +.doxygenfile p, +.doxygenstruct p { + margin: 0.6em 0 !important; +} + +dl.cpp, +dl.c { + margin-top: 1.4rem !important; + margin-bottom: 1.4rem !important; +} + +div.highlight { + padding: 1rem !important; + border-radius: 8px; + margin: 1rem 0 !important; +} \ No newline at end of file diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 00000000..c975c71a --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,5 @@ +API +=== + +.. doxygenindex:: + :project: CavernServer \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..efc62e3e --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,47 @@ +import os +import sys + +sys.path.insert(0, os.path.abspath('.')) + + +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'CavernServer' +copyright = '2025, Cavernfall Interactives' +author = 'Cavernfall Interactives' +release = '1.0.0-dev' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [] + +templates_path = ['_templates'] +exclude_patterns = [] + +breathe_projects = { + "CavernServer": "../../builds/docs/xml" +} +breathe_default_project = "CavernServer" + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +extensions = [ + "breathe", +] + +html_theme = "furo" +html_static_path = ['_static'] + +html_css_files = [ + "doxygen.css" +] + +breathe_default_members = ("members", "undoc-members") \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..af5afbca --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,20 @@ +.. CavernServer documentation master file, created by + sphinx-quickstart on Sun Nov 16 02:53:19 2025. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to CavernServer's documentation! +======================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + api + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/includes/cavernfall/config.hpp b/includes/cavernfall/config.hpp index a07fb6ec..9ddda64f 100644 --- a/includes/cavernfall/config.hpp +++ b/includes/cavernfall/config.hpp @@ -1,9 +1,26 @@ +/** + * @file config.hpp + * @brief Definitions for Cavernfall configurations. + * @details Usually contains default feature flag values and more. + */ + #pragma once #ifndef WORLD_REGION_SIZE +/** + * @brief The side-size of a world region (in terms of chunks). + */ #define WOLRD_REGION_SIZE 8 #endif #ifndef WORLD_CHUNK_SIZE +/** + * @brief The side-size of a chunk (in terms of blocks). + */ #define WORLD_CHUNK_SIZE 32 -#endif \ No newline at end of file +#endif + +/** + * @brief The total size of a chunk (in terms of blocks). + */ +#define WORLD_CHUNK_SIZE_TOTAL WORLD_CHUNK_SIZE * WORLD_CHUNK_SIZE diff --git a/includes/cavernfall/constants.hpp b/includes/cavernfall/constants.hpp index 3c1fc2b9..c2f06f7b 100644 --- a/includes/cavernfall/constants.hpp +++ b/includes/cavernfall/constants.hpp @@ -1,13 +1,35 @@ +/** + * @file constants.hpp + * @details Cavernfall constants definitions. + */ + #pragma once +/** + * @brief The lowest health point an entity can be at. + * @details The lowest health value possible before an entity dies. + */ #define HEALTH_POINT_LOWEST 0 +/** + * @brief The maximum veritcal motion. + * @details The maximum vertical motion an entity can do in one motion tick from the velocity. + */ #define MAX_VERTICAL_MOTION_IN_ONE_TICK 0.10 -#define MAX_MOTION_IN_ONE_TICK 0.15 -#define CHUNK_SIDE_SIZE 32 -#define CHUNK_SIZE_TOTAL CHUNK_SIDE_SIZE * CHUNK_SIDE_SIZE -#define CHUNK_MAX_HEIGHT 50 +/** + * @brief The maximum horizontal motion. + * @details The maximum horizontal motion an entity can do in one motion tick from the velocity. + */ +#define MAX_MOTION_IN_ONE_TICK 0.15 +/** + * @brief The maximum health level of a player. + * @deprecated Should be soon removed as it not important enough to be here. + */ #define PLAYER_MAX_HEALTH 100 + +/** + * @brief The player's render distance in terms of chunks. + */ #define PLAYER_RENDER_DISTANCE 8 diff --git a/includes/cavernfall/entity/entity.hpp b/includes/cavernfall/entity/entity.hpp index de7a546a..18625e20 100644 --- a/includes/cavernfall/entity/entity.hpp +++ b/includes/cavernfall/entity/entity.hpp @@ -1,8 +1,14 @@ +/** + * @file entity.hpp + * @details Entity related definitions. + */ + #pragma once #include #include +#include #include #include @@ -17,24 +23,67 @@ namespace cavernfall { +/** @brief The distance in meters before the entity should be report the position update to it's viewers. */ #define ENTITY_POSITION_REPORTING_DISTANCE 3 +/** + * @brief The base of an entity. + */ class EntityBase: public cavernfall::utils::realpos_t { public: + /** @brief The type of entity. */ uint8_t type; + + /** @brief The living ID of the entity. */ int id; + /** + * @brief The last reported X position of the entity. + * @deprecated Will soon be replaced by a real pos object. + */ double reported_x; + + /** + * @brief The last reported Y position of the entity. + * @deprecated Will soon be replaced by a real pos object. + */ double reported_y; + + /** + * @brief The last reported Z position of the entity. + * @deprecated Will soon be replaced by a real pos object. + */ double reported_z; + /** + * @brief The currently applied entity motion velocity. + */ cavernfall::maths::Vec velocity; + /** + * @brief Creates an entity base. + * @details Creates an entity base with the given type and entity id and sets it's default position to 0 0 0. + * + * @param type the entity type ID. + * @param id the ID representing the entity instance. + */ EntityBase(uint8_t type, int id): cavernfall::utils::realpos_t(0, 0, 0) { this->type = type; this->id = id; } + /** + * @brief Creates an entity base. + * @details Creates an entity base with the given type and entity id at the given position. + * + * @param type the entity type ID. + * @param id the ID representing the entity instance. + * @param x the X position. + * @param y the Y position. + * @param z the Z position. + * + * @warning Will soon be replaced by a real pos object instead of raw coordinates for consistency. + */ EntityBase(uint8_t type, int id, double x, double y, double z): cavernfall::utils::realpos_t(x, y, z) { this->type = type; this->id = id; @@ -47,27 +96,31 @@ class EntityBase: public cavernfall::utils::realpos_t { }; /** - * The base class for entities in Cavernfall. - * Represents an entity. + * @brief The main entity class. + * @details Represents an entity within a Cavernfall world. */ class CavernEntity: public cavernfall::view::ViewEngine, public cavernfall::EntityBase { protected: - /** - * Whenever the entity was spawned or not - */ + /** @brief Indicates if the entity is currently spawned or not */ bool spawned; /** - * Is the entity tickable. - */ + * @brief Indicates if the entity is tickable. + * + * @deprecated Will soon be removed for a direct scheduler ref + * @warning Currently unused. + */ bool tickable; /** - * @name onDeath - * Gets triggered when an entity dies + * @brief Gets triggered when an entity dies + * * @param source the entity that caused the death - * @return true if this entity should be erased / actually die or not + * + * @return the death result. + * @retval true the entity dies. + * @retval false the entity doesn't die. */ bool onDeath(CavernEntity* source) { return true; @@ -77,26 +130,32 @@ class CavernEntity: public cavernfall::view::ViewEngine, public cavernfall::Enti void viewer_remove(cavernfall::player::Player* player) override; public: + /** @brief An incrementing entity ID, allows to generate entity IDs */ static int incrementable_entity_id; /** - * The maximum amount of health the entity can have - */ + * @brief The maximum amount of health the entity can have + * + * @deprecated Will be removed by the introduction of Entity types classes + */ float maxHealth; - /** - * The current amount of health the entity has - */ + /** @brief The current amount of health the entity has */ float health; + /** @brief The entity tracker refernce within the entity tracker. */ std::list* tracker_ref; + + /** @brief The entity world linked list reference. */ cavernfall::structs::linked_list_reference entity_world_reference; /** - * @name CavernEntity - * The classic constructor + * @brief Constructs a entity. + * @details Creates an entity with the given max health and type. + * * @param maxHealth the maximum amount of health the entity can have + * @param type the entity type ID. */ CavernEntity(float maxHealth, uint8_t type): EntityBase(type, CavernEntity::incrementable_entity_id) { this->maxHealth = maxHealth; @@ -110,19 +169,18 @@ class CavernEntity: public cavernfall::view::ViewEngine, public cavernfall::Enti } /** - * @name ~CavernEntity - * Destroys the entity and removes it from it's world + * @brief Destructs the entity. */ virtual ~CavernEntity() {} /** - * @name remove - * Removes the entity from it's current world + * @brief Cleanly removes the entity from it's current world. */ virtual void remove(); /** - * @name damage + * @brief Damages the entity and kills it if it's health is empty after. + * * @param damage the amount of damage * @param source the entity source of the damage, or nullptr if none */ @@ -139,43 +197,53 @@ class CavernEntity: public cavernfall::view::ViewEngine, public cavernfall::Enti } /** - * @name tick - * Ticks the entity + * @brief Ticks the entity. + * @details Performs motion ticking, AI ticking and a lot of stuff. + * + * @warning Currently unused. */ virtual void tick(); /** - * @name set_position - * Sets the entity's position + * @brief Sets the entity position. + * @details Handles updating, chunk loading and unloading for players. + * * @param x the X position * @param y the Y position * @param z the Z position + * + * @warning Will get replaced by a real pos object for consistency. */ virtual void set_position(double x, double y, double z); /** - * @name spawn - * Spawns the entity, cannot be done if the entity is already spawned + * @brief Spawns the entity. + * @details Handles chunk loading if needed. Cannot be done if the entity is already loaded. + * * @param x the X coordinate * @param y the Y coordinate * @param z the Z coordinate + * + * @warning Will get replaced by a real pos object for consistency. */ virtual void spawn(double x, double y, double z); /** - * @name get_chunk_x - * @return the X position of the current chunk of the entity + * @brief Returns the entity's current chunk X coordinate. + * + * @deprecated Will be removed shortly in favor of the position objects. */ long get_chunk_x() { - return (long) (this->x / CHUNK_SIDE_SIZE); + return (long) (this->x / WORLD_CHUNK_SIZE); } /** - * @name get_chunk_z - * @return the Z position of the current chunk of the entity + * @brief Returns the entity's current chunk Z coordinate. + * + * @deprecated Will be removed shortly in favor of the position objects. */ long get_chunk_z() { - return (long) (this->z / CHUNK_SIDE_SIZE); + return (long) (this->z / WORLD_CHUNK_SIZE); } }; diff --git a/includes/cavernfall/entity/player.hpp b/includes/cavernfall/entity/player.hpp index d148cc73..d1f198d4 100644 --- a/includes/cavernfall/entity/player.hpp +++ b/includes/cavernfall/entity/player.hpp @@ -1,3 +1,8 @@ +/** + * @file player.hpp + * @brief Player-related definitions. + */ + #pragma once #include @@ -11,45 +16,60 @@ namespace cavernfall::world {class Chunk;} namespace cavernfall::player { /** - * The main class of a Player in Cavernfall. Is used to differentiate socket players and local ones - */ + * @brief The main class of a Player in Cavernfall. Is used to differentiate socket players and local ones +*/ class Player: public cavernfall::CavernEntity { protected: /** - * Should the player load chunks around them or not. + * @brief Determines if the player should load chunks around them. */ bool shouldLoadChunks; /** - * @name load_chunks_around_player - * Loads the chunks arround the player and sends them to it. Used during the initial spawn of the player + * @brief Loads the chunks arround the player and sends them to it. Used during the initial spawn of the player + * @details Ignores shouldLoadChunks state, make sure to use accordingly. */ void load_chunks_around_player(); public: + /** @brief The linked list node refernce to the player world linked list. */ cavernfall::structs::linked_list_reference player_list_reference; + /** @brief The name of the player. */ char* name; + /** + * @brief Creates player with the given name and the should load chunks state. + * + * @param name the player name. + * @param shouldLoadChunks should the player load chunks. + */ Player(char* name, bool shouldLoadChunks = false): CavernEntity(100, PLAYER_TYPE_ID) { this->name = name; this->tickable = false; this->shouldLoadChunks = shouldLoadChunks; } + /** + * @brief Creates a player with the given should load chunks state. + * + * @param shouldLoadChunks should the player load chunks. + * + * @warning This won't define a player name, meaning it will be null, make sure to set one. + */ Player(bool shouldLoadChunks = false): CavernEntity(100, PLAYER_TYPE_ID) { this->tickable = false; this->shouldLoadChunks = shouldLoadChunks; + this->name = nullptr; } - void remove() override; - /** - * @name handle_chunk_load - * Makes the player handle whenever a chunk is loaded to them + * @brief Makes the player handle whenever a chunk is loaded to them + * * @param chunk the chunk + * * @return true if it was a success, false if it wasn't */ virtual bool handle_chunk_load(cavernfall::world::Chunk* chunk) { @@ -57,10 +77,11 @@ class Player: public cavernfall::CavernEntity { } /** - * @name handle_chunk_unload - * Makes the player handler whenever a chunk is unloaded to them + * @brief Makes the player handler whenever a chunk is unloaded to them + * * @param chunkX the X coordinate of the chunk * @param chunkZ the Z coordinate of the chunk + * * @return true if it was a success, false if it wasn't */ virtual bool handle_chunk_unload(long chunkX, long chunkZ) { @@ -68,9 +89,10 @@ class Player: public cavernfall::CavernEntity { } /** - * @name handle_entity_spawn - * Makes the player handle whenever an entity is spawned to them + * @brief Makes the player handle whenever an entity is spawned to them + * * @param entity the entity + * * @return true if it was a success, false if it wasn't */ virtual bool handle_entity_spawn(cavernfall::CavernEntity* entity) { @@ -78,9 +100,10 @@ class Player: public cavernfall::CavernEntity { } /** - * @name handle_entity_despawn - * Makes the player handle whenever an entity is despawned to them + * @brief Makes the player handle whenever an entity is despawned to them + * * @param entity_id the entity ID + * * @return true if it was a success, false if it wasn't */ virtual bool handle_entity_despawn(int entity_id) { @@ -88,12 +111,13 @@ class Player: public cavernfall::CavernEntity { } /** - * @name handle_entity_move - * Makes the player handle whenever an entity is moving to them + * @brief Makes the player handle whenever an entity is moving to them + * * @param entityID the identifier for the entity * @param x the new X position * @param y the new Y position * @param z the new Z position + * * @return true if it was a success, false if it wasn't */ virtual bool handle_entity_move(int entityID, double x, double y, double z) { @@ -101,8 +125,8 @@ class Player: public cavernfall::CavernEntity { } void spawn(double x, double y, double z) override; - void set_position(double x, double y, double z) override; + void remove() override; }; } \ No newline at end of file diff --git a/includes/cavernfall/entity/tracker.hpp b/includes/cavernfall/entity/tracker.hpp index d058e3c4..0b3dd681 100644 --- a/includes/cavernfall/entity/tracker.hpp +++ b/includes/cavernfall/entity/tracker.hpp @@ -1,3 +1,8 @@ +/** + * @file tracker.hpp + * @brief Entity tracker definitions. + */ + #pragma once #include @@ -10,14 +15,21 @@ class CavernEntity; namespace cavernfall::entity { +/** + * @brief The entity tracker. + * @details Allows for constant time lookup for most entities under certain lookup types such as by id or by chunk. + */ class EntityTracker { private: + /** @brief Hashmap contaning entities by chunk positions */ emhash7::HashMap*> chunk_track; + + /** @brief Hashmap containing entities by entity IDs. */ emhash7::HashMap entity_by_id; /** - * @name propagate_entity_append - * Propagates the entity append act to the entity tracker. + * @brief Propagates the entity append act to the entity tracker. + * * @param entity the entity * @param chunk_key the chunk key of the entity. */ @@ -25,38 +37,58 @@ class EntityTracker { public: + /** + * @brief Creates a new entity tracker. + */ EntityTracker() { this->chunk_track = emhash7::HashMap*>(); this->entity_by_id = emhash7::HashMap(); } + /** @brief Destructs the entity tracker. */ ~EntityTracker(); - /** - * @name get_chunk_entities - * Gets the entities inside of the given chunk key. + /** + * @brief Gets the entities inside of the given chunk key. + * * @param key the chunk's key. + * + * @return The entities contained in the chunk as an linked list. */ std::list* get_chunk_entities(long key); + /** + * @brief Get the entity that has the given entity ID. + * + * @param id the entity ID. + * + * @return The entity corresponding to the given ID. + * @retval nullptr the ID was invalid or not loaded yet + */ cavernfall::CavernEntity* by_id(int id); /** - * @name push_entity - * Appends the entity into the tracking engine. + * @brief Appends the entity into the tracking engine. + * * @param entity the entity. */ void push_entity(cavernfall::CavernEntity* entity); /** - * @name entity_move - * Updates the position of the given entity. + * @brief Updates the position of the given entity. + * * @param entity the entity. * @param new_cx the new X position of the entity's chunk. * @param new_cz the new Z position of the entity's chunk. */ void entity_move(cavernfall::CavernEntity* entity, long new_cx, long new_cz); + /** + * @brief Removes the given entity from the entity tracker. + * @details Also propagates the entity deletion to the different entity trackers. + * + * @param entity the entity to remove. + */ void entity_remove(cavernfall::CavernEntity* entity); }; diff --git a/includes/cavernfall/entity/view.hpp b/includes/cavernfall/entity/view.hpp index e199143c..9878b684 100644 --- a/includes/cavernfall/entity/view.hpp +++ b/includes/cavernfall/entity/view.hpp @@ -1,3 +1,8 @@ +/** + * @file view.hpp + * @brief The view engine related definitions + */ + #pragma once #include @@ -10,37 +15,92 @@ class Player; namespace cavernfall::view { -// The ViewEngine is responsible for allowing entity to view othe entities efficiently. +/** + * @brief The main view engine class. + * @details The view engine allows to distribute changes efficiently to the different players. + */ class ViewEngine { private: + /** @brief A set containing all of the viewer IDs. */ std::unordered_set viewers; protected: + /** + * @brief Gets triggered when a viewer is added. + * + * @param player the viewer. + */ virtual void viewer_add(cavernfall::player::Player* player) {} + + /** + * @brief Gets triggered when a viewer is removed. + * + * @param player the viewer. + */ virtual void viewer_remove(cavernfall::player::Player* player) {} public: + /** + * @brief Add a viewer to the current view engine. + * @details Triggers viewer_append when finished. + * + * @param player the viewer to append. + */ void append_viewer(cavernfall::player::Player* player); + /** + * @brief Removes a viewer from the current view engine. + * @details Triggers viewer_remove when finished. + * + * @param player the viewer to remove. + */ void remove_viewer(cavernfall::player::Player* player); - ViewEngine(): viewers(0) { - - } + /** @brief Creates a new empty view engine. */ + ViewEngine(): viewers(0) {} + /** + * @brief Gets the current viewer count. + * + * @warning This count is an estimation and doesn't include disconnected players. + */ size_t get_viewer_count() { return this->viewers.size(); } + /** + * @brief Destructs the view engine. + */ ~ViewEngine() { this->viewers.clear(); } + /** + * @brief Checks if the view engine has this viewer. + * + * @param player the viewer. + */ bool has_viewer(cavernfall::player::Player* player); + /** + * @brief Checks if the object is currently viewable. + * @details In order to be considered viewable, an object must have at least one viewer. + * + * @warning This uses estimated counting and thus isn't accuate with disconnected players. + */ bool is_viewable(); + + /** + * @brief Checks if the objefct is currently viewable. + * @details In order to be considered viewable, an object must have at least one viewer. Also actually checks the state of each ID entry to ensure connected players. + */ bool is_viewable_true(); + /** + * @brief Performs an action onto each viewer. + * + * @param act the action to perform on each viewer. + */ void send_to_viewers(std::function act); }; } \ No newline at end of file diff --git a/includes/cavernfall/local/client.hpp b/includes/cavernfall/local/client.hpp index e0e865ac..36f740bb 100644 --- a/includes/cavernfall/local/client.hpp +++ b/includes/cavernfall/local/client.hpp @@ -1,3 +1,10 @@ +/** + * @file client.hpp + * @brief Local client definitions. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ + #pragma once #include @@ -9,23 +16,48 @@ namespace cavernfall::local::net { +/** @brief The max amount of polling turns a client can do in a single polling call */ #define CLIENT_MAX_POLLING_TURN 15 +/** + * @brief Represents client socket-wise. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ class SocketClient: public cavernfall::net::ISocket { public: + /** @brief The socket server address. */ sockaddr_in server_address; + /** + * @brief Is the socket client connected. + * @details Checks using a timeout to make sure. + * + * @return the connected state. + */ bool is_client_timeout_connected(); + /** + * @brief Creates a socket client to the given address. + * + * @param server_address the server socket address. + */ SocketClient(sockaddr_in server_address); - virtual void process_packet(cavernfall::net::Packet* packet) override {}; - - ~SocketClient() { - std::cout << "Socket client destructoir\n"; - } - + /** + * @brief Destructs a socket client. + * + * @deprecated Is empty, might be able to remove it. + */ + ~SocketClient() {}; + + /** + * @brief Directly polls the client packets. + * @details Also automatically disconnects the client if there is need to do so (eg: errors were encountered during polling). + */ void poll_direct(); + + virtual void process_packet(cavernfall::net::Packet* packet) override {}; }; } \ No newline at end of file diff --git a/includes/cavernfall/local/ctx.hpp b/includes/cavernfall/local/ctx.hpp index c9612088..10c7ede1 100644 --- a/includes/cavernfall/local/ctx.hpp +++ b/includes/cavernfall/local/ctx.hpp @@ -1,3 +1,10 @@ +/** + * @file ctx.hpp + * @brief Local context definitions. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ + #pragma once #include @@ -9,20 +16,45 @@ class SceneTree; namespace cavernfall::local { -/** - * Represents the current game running instance to the eyes of a player. - * WARN: Anything contained in cavernfall::local should NOT use anything else than godot code or basic c++! - */ +/** + * @brief Represents the local context for a client player, aka the world and other stuff. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! +*/ class PlayerLocalContext { protected: + /** @brief The currently loaded entities client side */ emhash7::HashMap stored_entities; + /** @brief The godot scene tree */ static godot::SceneTree* scene_tree; public: + /** + * @brief Initializes the player local context. + */ static void init(); + /** + * @brief Adds an entity in the local context. + * @details Also creates it inside of Godot. + * + * @param entityId the entity ID. + * @param entityType the entity type. + * @param x the X position of the entity. + * @param y the Y position of the entity. + * @param z the Z position of the entity. + * + * @warning Position arguments will be changed to use a realpos_t. + */ void add_entity(int entityId, uint8_t entityType, double x, double y, double z); + + /** + * @brief Instantly removes an entity. + * @details Also removes it inside of Godot. + * + * @param entityId the entity ID. + */ void remove_entity_direct(int entityID); }; diff --git a/includes/cavernfall/local/player.hpp b/includes/cavernfall/local/player.hpp index 97edd466..de942c34 100644 --- a/includes/cavernfall/local/player.hpp +++ b/includes/cavernfall/local/player.hpp @@ -1,3 +1,10 @@ +/** + * @file player.hpp + * @brief Local player declarations + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ + #include #include #include @@ -19,10 +26,25 @@ namespace cavernfall::local { +/** + * @brief The base of a local player. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ class LocalPlayerBase: public godot::RefCounted, public cavernfall::player::Player, public cavernfall::local::PlayerLocalContext { public: + + /** + * @brief Creates a local player base. + * @details This created base will be named "LocalPlayerBase" and will automatically load chunks like a real player. + */ LocalPlayerBase(): cavernfall::player::Player("LocalPlayerBase", true) {} + /** + * @brief Gets the godot position equivalent. + * + * @return the Godot position as an godot::Vector2 + */ godot::Vector2 get_position_gd() { return godot::Vector2(this->x, this->z); } diff --git a/includes/cavernfall/local/resources.hpp b/includes/cavernfall/local/resources.hpp index 3a0f2729..20e2a2b9 100644 --- a/includes/cavernfall/local/resources.hpp +++ b/includes/cavernfall/local/resources.hpp @@ -1,3 +1,10 @@ +/** + * @file resources.hpp + * @brief Resource maangement definitions. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ + #include #include @@ -11,19 +18,40 @@ namespace cavernfall::local { +/** + * @brief Represents a Cavernfall-managed resource. + * @details Contains a Godot reference and an auto loading system when the resource is required. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ class Resource { private: + /** @brief The Godot resource reference. */ godot::Ref reference; public: + /** @brief The resource path. */ std::string path; + + /** @brief Determines if the resource is loaded or not. */ bool loaded; + /** + * @brief Creates a resource at the given path. + * + * @param p the resource path. + */ Resource(std::string p) { this->path = p; this->loaded = false; } + /** + * @brief Gets the Godot resource reference. + * @details Also creates it if the resource is not loaded yet. + * + * @return the Godot reference casted as godot::Ref* + */ template godot::Ref* get() { static_assert(std::is_base_of::value, "T must be a Godot resource!"); @@ -38,23 +66,47 @@ class Resource { } }; +/** + * @brief The manager for every resource instance. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ class ResourceManager { private: - emhash7::HashMap res; // the pointer here is to handle multiple resource types. + /** @brief The different resource instances based by key. */ + emhash7::HashMap res; + /** + * @brief Creates an empty resource manager. + */ ResourceManager(); + /** + * @brief Registers a new resource. + * + * @param key the resource key. + * @param path the resource path. + */ template void register_res(std::string key, std::string path); public: + /** @brief The resource manager instance. */ static ResourceManager* singleton; + /** + * @brief Initializes the resource amanger. + */ static void init() { if(singleton != nullptr) return; singleton = new ResourceManager(); } + /** + * @brief Gets the resource at the given key. + * + * @param key the key or ID representing the resource. + */ template godot::Ref* get_res(std::string key) { static_assert(std::is_base_of::value, "T must be a Godot resource!"); Resource* r = this->res.at(key); diff --git a/includes/cavernfall/local/utils.hpp b/includes/cavernfall/local/utils.hpp index b4f813a0..479a887f 100644 --- a/includes/cavernfall/local/utils.hpp +++ b/includes/cavernfall/local/utils.hpp @@ -1,3 +1,10 @@ +/** + * @file utils.hpp + * @brief Local-related utilities. + * + * @warning This is part of the local API, DO NOT use any server-related variables in it! + */ + #include #ifdef GODOT_EXT @@ -10,6 +17,17 @@ namespace cavernfall::local { -USING_GODOT(Vector2 to_godot_pos(double x, double y, double z);) +USING_GODOT( +/** + * @brief Converts a position to a godot position. + * + * @param x the X position. + * @param y the Y position. + * @param z the Z position. + * + * @return the godot position as a godot::Vector2 + */ +Vector2 to_godot_pos(double x, double y, double z); +) } \ No newline at end of file diff --git a/includes/cavernfall/network/buff.hpp b/includes/cavernfall/network/buff.hpp index f9abe7fb..4ca14c67 100644 --- a/includes/cavernfall/network/buff.hpp +++ b/includes/cavernfall/network/buff.hpp @@ -1,3 +1,8 @@ +/** + * @file buff.hpp + * @brief Network buffer related definitions. + */ + #pragma once #include @@ -13,12 +18,13 @@ namespace cavernfall::net { class NetworkBuff { private: + /** @brief Determines if the buffer was internally allocated. */ bool allocated; protected: /** - * @name can_read - * Determines whenever the buffer is big enough to read n bytes. + * @brief Determines whether the buffer is big enough to read n bytes. + * * @param size the amount of bytes */ constexpr bool can_read(size_t size) { @@ -26,8 +32,8 @@ class NetworkBuff { } /** - * @name can_write - * Determines whenever the buffer is big enough to write n bytes. + * @brief Determines whether the buffer is big enough to write n bytes. + * * @param size the amount of bytes */ constexpr bool can_write(size_t size) { @@ -35,9 +41,11 @@ class NetworkBuff { } /** - * @name ensure_space - * Ensures that the buffer has at least n bytes of space to write. + * @brief Ensures that the buffer has at least n bytes of space to write. + * * @param size the expected minimim buffer size. + * + * @warning If the buffer is allocated outside of the network buffer, it won't free it when expanding */ constexpr void ensure_space(size_t size) { if(this->can_write(size)) return; @@ -61,34 +69,107 @@ class NetworkBuff { } public: + /** @brief The actual byte buffer. */ uint8_t* buff; + + /** @brief The currently allocated buffer size. */ size_t sz; + /** @brief The write position of the buffer. */ int writePosition; + + /** @brief The read position of the buffer. */ int readPosition; + /** + * @brief Creates a network buffer. + * @details The created network buffer is based of an already existing buffer. + * + * @param buff the already existing buffer. + * @param sz the buffer size. + */ NetworkBuff(uint8_t* buff, size_t sz); + + /** + * @brief Creates a network buffer. + * @details The created network buffer is internally created + * + * @param sz the buffer size. + */ NetworkBuff(size_t sz); + /** + * @brief Destructs the network buffer. + * + * @warning If the buffer was allocated outside the network buffer, it won't be freed. + */ ~NetworkBuff(); + /** + * @brief Reads a byte. + * + * @return the read byte. + * @retval 0 The byte couldn't be read. + */ constexpr uint8_t read_byte() { if(!this->can_read(1)) return 0; return this->buff[this->readPosition++]; } + /** + * @brief Writes a byte. + * + * @param byte the byte to write. + */ constexpr void write_byte(uint8_t byte) { this->ensure_space(1); this->buff[this->writePosition++] = byte; } + /** + * @brief Reads a number. + * @details Reads a number of type T. Handles endianness and the other stuff. + * + * @return the read number. + */ template constexpr T read_number(); + + /** + * @brief Writes a number. + * @details Writes a number of type T. Handles endianness and the other stuff. + * + * @param num the number to write. + */ template constexpr void write_number(T num); + /** + * @brief Writes bytes from a given pointer. + * + * @param ptr the pointer to write from. + * @param sz the amount of bytes to write. + */ inline void write_from_ptr(uint8_t* ptr, size_t sz); + + /** + * @brief Reads bytes to a given pointer. + * + * @param ptr the pointer to read to. + * @param sz the amount of bytes to read. + */ inline void read_to_ptr(uint8_t* ptr, size_t sz); + /** + * @brief Reads a string. + * + * @return the read string. + */ constexpr std::string read_string(); + + /** + * @brief Writes a string. + * + * @param str the string to write. + */ constexpr void write_string(std::string str); }; } diff --git a/includes/cavernfall/network/conn.hpp b/includes/cavernfall/network/conn.hpp index ef42b938..3e446c61 100644 --- a/includes/cavernfall/network/conn.hpp +++ b/includes/cavernfall/network/conn.hpp @@ -1,3 +1,8 @@ +/** + * @file conn.hpp + * @brief Connection related definitions. + */ + #pragma once #include @@ -12,38 +17,70 @@ namespace cavernfall::net { +/** @brief The amount of seconds before a connection timeouts after not having reached the PLAY state. */ #define CONNECTION_PLAYSTATE_TIMEOUT 2 +/** + * @brief The different states of a connection. + */ enum ConnectionState { + /** @brief The initial state of the connection. Contains auth related packets */ LOGIN, + + /** @brief The core state of the connection. Contains world, entity and player packets. */ PLAY }; +/** + * @brief A socket-based connection. + */ class SocketConnection: public ISocket { private: + /** @brief Is currently extending to become a player instance. */ bool is_player_extending; + /** + * @brief Swaps this instance to a Player instance instead of a mere connection instance. + * @details Frees the previous nstance. + */ void __swap_to_player(); public: + /** @brief The socket address. */ sockaddr address; + /** @brief The current state of this connection. */ ConnectionState state; + /** @brief The timestamp at which the player connected. */ std::chrono::time_point connection_login_time; + + /** @brief The queue containing the packets to process. */ std::queue packets_to_process; + /** + * @brief Creates a socket connection instance. + * + * @param sock the raw socket. + * @param addr the socket address. + */ SocketConnection(socket_t sock, sockaddr addr); - ~SocketConnection(); - - virtual void process_packet(Packet* packet) override; - SocketPollingState poll_now() override; + /** + * @brief Destructs the socket connection and closes it. + */ + ~SocketConnection(); SocketConnection* prev; SocketConnection* next; + + virtual void process_packet(Packet* packet) override; + SocketPollingState poll_now() override; }; +/** + * @brief Represents any type that is derived from a connection. + */ template concept ConnectionDerived = std::derived_from; diff --git a/includes/cavernfall/network/isocket.hpp b/includes/cavernfall/network/isocket.hpp index fef495d9..74417b53 100644 --- a/includes/cavernfall/network/isocket.hpp +++ b/includes/cavernfall/network/isocket.hpp @@ -1,3 +1,8 @@ +/** + * @file isocket.hpp + * @brief Raw socket definitions. + */ + #pragma once #include @@ -10,6 +15,17 @@ namespace cavernfall::net { +/** + * @brief Safely gets the given amount of bytes. + * @details Handles sudden disconnects and errors. + * + * @param buffName the variable name of the buffer. + * @param sz the amount of bytes to get. + * @param errUsing the thing to do when an error is found (use the using macros). + * @param emptyUsing the thing to do when the socket is empty (use the using macros). + * @param returnSizeVariabe the variable name of the returned read size. + * @param defined is the variable already defined, use USING_TRUE or USING_FALSE macros + */ #define SOCKET_SAFE_GET(buffName, sz, errUsing, emptyUsing, returnSizeVariable, defined) \ uint8_t buffName[sz]; \ defined(int) returnSizeVariable = this->get(sz, buffName); \ @@ -23,54 +39,124 @@ namespace cavernfall::net { } +/** + * @brief The state after polling an ISocket. + */ enum SocketPollingState { /** - * The polling returned packets. - * In the case of a polling turn system, this means that the poll_now returned a packet on every turn. + * @brief The polling returned packets. + * @details In the case of a polling turn system, this means that the poll_now returned a packet on every turn. */ PACKETS, /** - * Only in the case of a polling turn system, is returned when the poll_now did not return a packet on every turn but still returned some. + * @brief Only in the case of a polling turn system, is returned when the poll_now did not return a packet on every turn but still returned some. */ FEWER_PACKETS, /** - * Did not return any packets + * @brief Did not return any packets */ NO_PACKET, /** - * The socket should be disconnected + * @brief The socket should be disconnected */ DISCONNECT }; +/** + * @brief The base class of raw socket connections. + */ class ISocket { public: + /** + * @brief Determines if the socket currently connected. + * + * @deprecated will soon be replaced by a direct check to the kernel socket. + */ bool connected; + + /** + * @brief The max amount of packet polling turns can happen at each poll. + */ int maxPollingTurn; + + /** @brief The raw socket. */ socket_t sock; + + /** + * @brief The packet origin type for the socket. + * @details Represents the direction of packets to expect to poll from the connection. + */ PacketOriginType origin; + /** + * @brief Create an ISocket class. + * + * @param maxPollingTurn the max amount of polling turns + * @param origin the origin type for the socket polled packets. + */ ISocket(int maxPollingTurn, PacketOriginType origin) { this->maxPollingTurn = maxPollingTurn; this->connected = true; this->origin = origin; } + /** + * @brief Destroys the ISocket instance and closes the socket. + */ ~ISocket(); + /** + * @brief Polls for packets inside the socket stream. + * @details Polls for packets. The max polling turns are determined by the maxPollingTurn variable. + * + * @return the returned polling state. + */ virtual SocketPollingState poll_now(); + + /** + * @brief Instantly disconnects the socket and closes the connection. + */ void disconnect(); + /** + * @brief Gets the given amount of bytes from the socket. + * + * @param bytes the amount of bytes + * @param ptr the pointer to write the bytes to. + * @return the amount of read bytes. + */ int get(size_t bytes, uint8_t* ptr); + /** + * @brief Determines if the socket is currently connected. + * @details Uses the socket kernel state to determine such. + */ bool is_connected(); + /** + * @brief Sends a packet to the socket. + * + * @param packet the packet. + */ void send_packet(Packet* packet); + + /** + * @brief Sends a packet to the socket. + * @details This function uses a network buffer and a packet type instead of a fully built packets. + * + * @param buff the network buff. + * @param type the packet type. + */ void send_packet(NetworkBuff* buff, PacketType type); + /** + * @brief Processes a given packet. + * + * @param packet the packet to process. + */ virtual void process_packet(Packet* packet) { std::cout << "Recieved packet with id " << packet->type; }; diff --git a/includes/cavernfall/network/net.hpp b/includes/cavernfall/network/net.hpp index faa3222d..01e2087e 100644 --- a/includes/cavernfall/network/net.hpp +++ b/includes/cavernfall/network/net.hpp @@ -1,3 +1,8 @@ +/** + * @file net.hpp + * @brief Network related definitions + */ + #pragma once #include diff --git a/includes/cavernfall/network/packet/client.hpp b/includes/cavernfall/network/packet/client.hpp index a4bb8846..211aef25 100644 --- a/includes/cavernfall/network/packet/client.hpp +++ b/includes/cavernfall/network/packet/client.hpp @@ -1,33 +1,66 @@ +/** + * @file client.hpp + * @brief From-client packet definitions. + */ + #include namespace cavernfall::net::packets::client { +/** + * @brief The packet sent containing the player login data. + */ class ClientLoginInfoPacket: public Packet { public: + /** @brief The player name. */ std::string player_name; + /** + * @brief Creates a login info packet. + * + * @param name the player name. + */ + ClientLoginInfoPacket(std::string name): player_name(name), Packet(SERVER_CLIENT_LOGIN_INFO) {} + + /** @brief Creates a login info packet. */ + ClientLoginInfoPacket(): Packet(SERVER_CLIENT_LOGIN_INFO) {} + size_t get_write_sz_estimate() override; void write(NetworkBuff* destination) override; void read(NetworkBuff* source) override; - - ClientLoginInfoPacket(std::string name): player_name(name), Packet(SERVER_CLIENT_LOGIN_INFO) {} - ClientLoginInfoPacket(): Packet(SERVER_CLIENT_LOGIN_INFO) {} }; +/** + * @brief The packet sent for player position changes. + */ class PlayerPositionUpdatePacket: public Packet { public: + /** @brief The new player X position. */ double x; + + /** @brief The new player Y position. */ double y; + + /** @brief The new player Z position. */ double z; + + /** + * @brief Creates a player position update packet. + * + * @param x the new X position. + * @param y the new Y position. + * @param z the new Z position. + */ + PlayerPositionUpdatePacket(double x, double y, double z); + /** @brief Creates a player position update packet. */ + PlayerPositionUpdatePacket(): Packet(PacketType::SERVER_PLAYER_POSITION_UPDATE) {} + size_t get_write_sz_estimate() override; void write(NetworkBuff* destination) override; void read(NetworkBuff* source) override; - - PlayerPositionUpdatePacket(double x, double y, double z); - PlayerPositionUpdatePacket(): Packet(PacketType::SERVER_PLAYER_POSITION_UPDATE) {} }; } \ No newline at end of file diff --git a/includes/cavernfall/network/packet/packet.hpp b/includes/cavernfall/network/packet/packet.hpp index a03ae3e2..9d72e200 100644 --- a/includes/cavernfall/network/packet/packet.hpp +++ b/includes/cavernfall/network/packet/packet.hpp @@ -1,3 +1,8 @@ +/** + * @file packet.hpp + * @details Packet related definitions. + */ + #pragma once #include @@ -6,11 +11,18 @@ namespace cavernfall::net { +/** + * @brief The different packet origin types. + * @details For example PacketOriginType::CLIENT means packets that are meant for a client, and vice versa. + */ enum PacketOriginType { CLIENT, SERVER }; +/** + * @brief The different types of packets. + */ enum PacketType { CLIENT_CHUNK_LOAD, CLIENT_CHUNK_UNLOAD, @@ -22,38 +34,94 @@ enum PacketType { SERVER_PLAYER_POSITION_UPDATE }; +/** + * @brief A basic network packet within the Cavernfall socket connections. + */ class Packet { public: + /** @brief The type of packet. */ PacketType type; + /** + * @brief Creates a packet instance with the given packet type. + * + * @param type the given packet type. + */ Packet(PacketType type) { this->type = type; } + /** + * @brief Calculates the estimated total size of the packet network buffer. + * + * @return the size of the network buffer for the packet in bytes. + */ virtual size_t get_write_sz_estimate() { return 0; } + /** + * @brief Writes the packet data into a buffer. + * + * @param destination the destination network buffer. + */ virtual void write(NetworkBuff* destination) {} + + /** + * @brief Reads the packet data from a network buff. + * + * @param source the source network buffer. + */ virtual void read(NetworkBuff* source) {} }; - +/** + * @brief Represents a constructor for a packet instance. + */ using PacketConstructor = std::function; +/** + * @brief The factory / register for packets. + */ class PacketFactory { private: + /** @brief Constructors for client-bound packets. */ PacketConstructor* client_constructors; + + /** @brief Constructors for server-bound packets. */ PacketConstructor* server_constructors; + /** @brief The max allocated size of client packet constructors. */ size_t max_client_packets; + + /** @brief The max allocated size of server packet constructors. */ size_t max_server_packets; + /** @brief The index for registering client constructors. */ size_t client_index; + + /** @brief The index for registering server constructors. */ size_t server_index; + /** + * @brief Expands the packet factory's pointers to the given size. + * + * @param server_sz the new maximum size of the allocated server packet constructors. + * @param client_sz the new maximum size of the allocated client packet constructors. + * + * @warning Should only be used at constructor time. + * @internal + */ void expand_to_size_final(size_t server_sz, size_t client_sz); + /** + * @brief Registers the given packet constructor inside the given packet origin. + * + * @param type the packet origin type. + * @param constructor the packet instance constructor. + * + * @warning This won't do anything if the target origin's constructor pointer is already full. + */ inline void reg(PacketOriginType type, PacketConstructor constructor) { if(type == PacketOriginType::SERVER) { if(this->server_index >= this->max_server_packets) return; @@ -68,14 +136,28 @@ class PacketFactory { public: + /** + * @brief Constructs a packet factory. + */ PacketFactory(); + + /** + * @brief Destructs the packet factory. + */ ~PacketFactory(); + /** + * @brief The currently createed packet factory instance. + */ static PacketFactory* instance; + /** + * @brief Creates a packet instance from the packet id and origin. + * + * @param packetId the packet ID. + * @param type the origin type of the packet. + */ Packet* make(size_t packetId, PacketOriginType type); - - }; } \ No newline at end of file diff --git a/includes/cavernfall/network/packet/server.hpp b/includes/cavernfall/network/packet/server.hpp index 1479a386..83ae01ab 100644 --- a/includes/cavernfall/network/packet/server.hpp +++ b/includes/cavernfall/network/packet/server.hpp @@ -1,3 +1,8 @@ +/** + * @file server.hpp + * @brief From server pacekt definitions. + */ + #pragma once #include @@ -12,43 +17,85 @@ class Chunk; namespace cavernfall::net::packets::server { +/** + * @brief The packet used to indicate whenever a chunk loads. +*/ class ChunkLoadPacket: public Packet { public: + /** @brief The loaded chunks. */ cavernfall::world::Chunk* chunk; + /** + * @brief Creates a chunk load packet. + * + * @param chunk the chunk that was loaded. + */ + ChunkLoadPacket(cavernfall::world::Chunk* chunk); + + /** @brief Creates a chunk load packet. */ + ChunkLoadPacket(): Packet(PacketType::CLIENT_CHUNK_LOAD) {} + size_t get_write_sz_estimate() override; void write(NetworkBuff* destination) override; void read(NetworkBuff* source) override; - - ChunkLoadPacket(cavernfall::world::Chunk* chunk); - ChunkLoadPacket(): Packet(PacketType::CLIENT_CHUNK_LOAD) {} }; -class ChunkUnloadPacket: public Packet { +/** + * @brief The packet used to indicate whenever a chunk unloads. +*/class ChunkUnloadPacket: public Packet { public: + /** @brief The chunk X position. */ long chunkX; + + /** @brief The chunk Z position. */ long chunkZ; + /** + * @brief Creates a chunk unload packet. + * + * @param chunkX the chunk X position. + * @param chunkZ the chunk Z position. + */ + ChunkUnloadPacket(long chunkX, long chunkZ); + + /** @brief Creates a chunk unload packet. */ + ChunkUnloadPacket(): Packet(PacketType::CLIENT_CHUNK_UNLOAD) {} + size_t get_write_sz_estimate() override; void write(NetworkBuff* destination) override; void read(NetworkBuff* source) override; - - ChunkUnloadPacket(long chunkX, long chunkZ); - ChunkUnloadPacket(): Packet(PacketType::CLIENT_CHUNK_UNLOAD) {} }; +/** + * @brief The packet used whenever an entity is spawned. + */ class EntitySpawnPacket: public Packet { public: + /** @brief The entity type. */ uint8_t type; + + /** @brief The entity ID */ int entity_id; + /** @brief The entity X position. */ double x; + + /** @brief The entity Y position. */ double y; + + /** @brief The entity Z position. */ double z; + /** + * @brief Creates an entity spawn packet. + * + * @param entity the spawned entity. + */ EntitySpawnPacket(cavernfall::CavernEntity* entity); + + /** @brief Creates an entity spawn packet. */ EntitySpawnPacket(): Packet(PacketType::CLIENT_ENTITY_SPAWN) {} size_t get_write_sz_estimate() override; @@ -57,15 +104,36 @@ class EntitySpawnPacket: public Packet { void read(NetworkBuff* source) override; }; +/** + * @brief The packet used whenever an entity moves. + */ class EntityMovePacket: public Packet { public: + /** @brief The entity ID. */ int entity_id; + /** @brief The new entity's X position. */ double x; + + /** @brief The new entity's Y position. */ double y; + + /** @brief The new entity's Z position. */ double z; + /** + * @brief Creates an entity move packet. + * + * @param entity_id the entity ID. + * @param x the entity's X position. + * @param y the entity's Y position. + * @param z the entity's Z position. + * + * @warning The position will be changed to a realpos_t. + */ EntityMovePacket(int entity_id, double x, double y, double z); + + /** @brief Creates an entity move packet. */ EntityMovePacket(): Packet(PacketType::CLIENT_ENTITY_MOVE) {} size_t get_write_sz_estimate() override; @@ -74,11 +142,22 @@ class EntityMovePacket: public Packet { void read(NetworkBuff* source) override; }; +/** + * @brief The packet used whenever an entity is despawned. + */ class EntityDespawnPacket: public Packet { public: + /** @brief The entity ID. */ int entity_id; + /** + * @brief Creates an entity despawn packet. + * + * @param entity_id the entity ID. + */ EntityDespawnPacket(int entity_id); + + /** @brief Creates an entity despawn packet. */ EntityDespawnPacket(): Packet(PacketType::CLIENT_ENTITY_DESPAWN) {} size_t get_write_sz_estimate() override; diff --git a/includes/cavernfall/network/player.hpp b/includes/cavernfall/network/player.hpp index af7eff40..8160630f 100644 --- a/includes/cavernfall/network/player.hpp +++ b/includes/cavernfall/network/player.hpp @@ -1,3 +1,8 @@ +/** + * @file player.hpp + * @brief Network player related definitions. + */ + #pragma once #include @@ -5,6 +10,9 @@ namespace cavernfall::net { +/** + * @brief A player trough the network. + */ class NetworkPlayer: public cavernfall::net::SocketConnection, public cavernfall::player::Player { public: NetworkPlayer(socket_t sock, sockaddr addr): SocketConnection(sock, addr) {} diff --git a/includes/cavernfall/network/server.hpp b/includes/cavernfall/network/server.hpp index a087ec15..35c22c78 100644 --- a/includes/cavernfall/network/server.hpp +++ b/includes/cavernfall/network/server.hpp @@ -1,3 +1,8 @@ +/** + * @file server.hpp + * @brief Network server related definitions. + */ + #pragma once #include @@ -10,21 +15,55 @@ namespace cavernfall::net { +/** + * @brief The socket backlog for the server. + */ #define SERVER_SOCKET_BACKLOG 128 +/** + * @brief Represents a constructor for any given connection class. + */ template using ConnectionConstructor = std::function; +/** + * @brief The core class for a socket server. + */ template class SocketServer { private: + /** @brief The raw server kernel socket. */ socket_t serversock; + + /** @brief The constructor for the socket connection instances. */ ConnectionConstructor constructor; + + /** + * @brief Determines if the server should only poll clients. + * + * @warning Currently without effect. + * @deprecated Will soon be removed due to it's uselessness + */ bool only_poll_clients; + /** + * @brief The client polling thread. + * @details Also the packet polling thread if single thread mode is enabled. + */ std::jthread client_thread; + #ifndef SOCKET_USESAME_POLLFIND_THREAD + /** + * @brief The packet polling thread. + * @details Only exists if the single thread mode is disabled. + */ std::jthread poll_thread; #endif + /** + * @brief Appends a connection to the server. + * @details Appends the connection to the list, also increases the client count. + * + * @param connection the connection. + */ inline void append_conn(T* connection) { connection->prev = this->head; @@ -41,16 +80,38 @@ template class SocketServer { } public: + /** @brief The root of the linked list tree. */ T* root; + + /** @brief The head (furthest element) of the linked list tree. */ T* head; + /** @brief Indicator of if the server is running or not. */ bool running; + /** @brief The current amount of connected clients. */ size_t connected_client_count; + /** + * @brief Creates a socket server. + * + * @param port the port to open the socket on. + * @param constructor the constructor to create the connection instances. + */ SocketServer(short port, ConnectionConstructor constructor); + + /** + * @brief Destructs the socket server. + * @details Also disconnects and closes any socket connection. + */ ~SocketServer(); + /** + * @brief Removes the socket connection from the server. + * @details Also frees and closes the connection. + * + * @param connection the connection. + */ inline void remove_conn(T* connection) { if(this->head == connection) this->head = connection->prev; if(this->root == connection) this->root = connection->next; @@ -59,10 +120,28 @@ template class SocketServer { --this->connected_client_count; } + /** + * @brief Triggers a packet polling turn. + */ inline void poll_turn(); + + /** + * @brief Triggers a client finding turn. + */ inline void client_find_turn(); + /** + * @brief Starts the server. + * + * @param only_poll_clients should the server only poll clients and not process packets? + * + * @warning the parameter only_poll_clients will be removed shortly. + */ void start(bool only_poll_clients = false); + + /** + * @brief Shutdowns the server. + */ void shutdown(); }; diff --git a/includes/cavernfall/server.hpp b/includes/cavernfall/server.hpp index 63d05128..93f152a9 100644 --- a/includes/cavernfall/server.hpp +++ b/includes/cavernfall/server.hpp @@ -1,3 +1,9 @@ +/** + * @file server.hpp + * @brief The main Cavernfall server. + * @details Contains the world, server logic and game logic, very important. +**/ + #pragma once // FORWARD DECLARATIONS @@ -15,27 +21,55 @@ class Player; } -/** - * The main class of the Cavernfall Game. Allows for both multiplayer and singleplayer experience. - */ namespace cavernfall { class World; +/** + * @class Server + * @brief the Cavernfall server base + * + * @details the base of all Cavernfall game instances +**/ class Server { public: + + /** @brief The world contained within the server **/ cavernfall::World* world; + + /** @brief The register for the various block types. **/ cavernfall::world::BlockTypeRegister* block_register; + + /** @brief The generator for chunks **/ cavernfall::world::gen::ChunkGenerator* chunk_generator; - + /** + * @brief Constructs the server base. + * + * @details Also constructs the child elements (eg world, chunk generator) + **/ Server(); + + /** + * @brief Destructs the server and the given world and other children + * + * @details Also cleanly disconnects and save data ans players + **/ ~Server(); + /** + * @brief Starts the server. + + * @details Starts the server and different tasks (eg: entity ticking, socket) + **/ virtual void start(); /** - * @name add_player - * Adds the player into the server + * @brief Adds a player to the server + * @details Adds a player to the server and manages it, also spawns it at a random location. + * + * @param player the player to add + * + * @deprecated Mostly useless and will be replaced when player data saving is introduced */ virtual void add_player(cavernfall::player::Player* player); @@ -43,4 +77,5 @@ class Server { } +/** @brief The currently running server instance **/ extern cavernfall::Server* server; diff --git a/includes/cavernfall/world/biome.hpp b/includes/cavernfall/world/biome.hpp index 54979fc5..0134359f 100644 --- a/includes/cavernfall/world/biome.hpp +++ b/includes/cavernfall/world/biome.hpp @@ -1,9 +1,22 @@ +/** + * @file biome.hpp + * @brief Biome related definitions. + */ + #pragma once namespace cavernfall::world { +/** + * @brief The count of currently implemented biomes. + * @deprecated Will soon be replaced for a better system. + */ #define BIOME_COUNT 3 +/** + * @brief The biomes of the world. + * @details Biomes are type of environments that drastically impact generation. + */ enum Biome { WATER_POINT = 0, PLAINS = 1, diff --git a/includes/cavernfall/world/block.hpp b/includes/cavernfall/world/block.hpp index 02fabd90..a6526da1 100644 --- a/includes/cavernfall/world/block.hpp +++ b/includes/cavernfall/world/block.hpp @@ -1,3 +1,8 @@ +/** + * @file block.hpp + * @details Definitions related to blocks. + */ + #pragma once #include @@ -7,6 +12,7 @@ namespace cavernfall::world { +/** @brief The type represent a block material ID. */ typedef uint8_t block_id_t; /** @@ -28,17 +34,39 @@ class BlockDataContainerBase { virtual void write(cavernfall::fs::file_handle& handle) {} }; +/** + * @brief A block type / material entry. + */ class BlockType { private: + /** @brief The constructor function to a material's BlockDataContainerBase.*/ std::function data_constructor; + + /** @brief Determines if the BlockType has a data constructor or not. */ bool has_data_constructor; public: + /** + * @brief The material's equivalent ID. + * @warning will soon get changed to be a block_id_t. + */ int id; + + /** + * @brief Is the block material tickable. + */ bool tickable; + /** + * @brief The equivalent texture ID for the block. + * @deprecated Isn't used and will soon be removed. + */ int textureID; + /** + * @brief Creates a sample block type. + * @details Creates a block type that isn't tickable, doesn't have a texture ID nor a data constructor. + */ BlockType() { this->id = 0; this->tickable = false; @@ -46,6 +74,13 @@ class BlockType { this->has_data_constructor = false; } + /** + * @brief Creates a block type. + * @details Creates a new block type that can be tickable and have a constructor + * + * @param tickable Determines if the BlockType is tickable. + * @param constructor the block data constructor for the block material. + */ BlockType(bool tickable, std::function constructor) { this->id = 0; this->tickable = tickable; @@ -53,6 +88,13 @@ class BlockType { this->has_data_constructor = true; } + /** + * @brief Creates a Block type. + * @details Creates a block type that can be tickable and have a texture ID. + * + * @param tickable Determines if the Block type is tickable. + * @param textureID the block material's texture ID. + */ BlockType(bool tickable, int textureID) { this->tickable = tickable; this->textureID = textureID; @@ -61,8 +103,8 @@ class BlockType { } /** - * @name tick - * Ticks the block type at the given position + * @brief Ticks the block type at the given position + * * @param x the X coordinate of the initiator block * @param y the Y coordinate of the iniator block * @param z the Z coordinator of the initiator block @@ -76,28 +118,41 @@ class BlockType { }; -//TODO: Make this static at compile time somehow +/** + * @brief The register for every block's material. + */ class BlockTypeRegister { public: BlockType* types; int ind; int sz; + /** + * @brief Creates a block type register. + * @details Creates a block type register with the given size. + * + * @param block_count the size of the block type register in terms of materials (excluding air). + */ BlockTypeRegister(int block_count) { this->types = new BlockType[block_count + 1]; this->sz = block_count + 1; this->ind = 1; } + /** + * @brief Destructs the block type register and frees the registered block types; + */ ~BlockTypeRegister() { delete[] this->types; } /** - * @name registerType - * Registers the given block inside the register - * @param type the type to register - */ + * @brief Registers the type inside of the register. + * + * @param type the type. + * + * @warning Will do nothing if the block type register is already full or overflowing somehow. + */ void registerType(BlockType type) { if(this->ind >= this->sz) { return; @@ -110,22 +165,27 @@ class BlockTypeRegister { } /** - * @name get - * Gets the block type corresponding to the provided identifier. - * @param mat the corresponding identifier. - * @return the block type or nullptr if no block type is associated to the given identifier. - */ + * @brief Gets the material information related to the id. + * + * @param mat the material ID. + * @return the block type material instance or nullptr if the ID is invalid. + * + * @warning The "mat" type will soon changed to block_id_t according to the API changes. + */ BlockType* get(int mat) { - if(mat >= this->sz || mat < 0) return nullptr; + if(mat >= this->sz || mat < 0) return nullptr; return &(this->types[mat]); } }; /** -* @name fill_blocktype_register -* Fills the given register with all given block types -* @param reg the targed register: -*/ + * @brief Fills the block type register. + * + * @param reg the register to fill. + * @warning Soon will be removed due to it's uselessness. + * + * @deprecated Will soon be removed in favor of an in-constructor approach. + */ void fill_blocktype_register(BlockTypeRegister* reg); } diff --git a/includes/cavernfall/world/chunk.hpp b/includes/cavernfall/world/chunk.hpp index 7b985a55..9052e11f 100644 --- a/includes/cavernfall/world/chunk.hpp +++ b/includes/cavernfall/world/chunk.hpp @@ -1,3 +1,8 @@ +/** + * @file chunk.hpp + * @brief Definitions for chunk-related stuff. + */ + #pragma once #include @@ -18,29 +23,83 @@ #include #include +#include #include namespace cavernfall::world { +/** + * @brief Converts the given chunk coordinates into an long index. + * + * @param chunkX the X coordinate of the chunk + * @param chunkZ the Z coordinate of the chunk + * @return the chunk index based on the coords, is a long. + * + * @deprecated Soon removal in favor of usage of the chunk pos class and hash. + */ #define CHUNK_TO_IND(chunkX, chunkZ) (((long) chunkX) << 32) | (chunkZ & 0xffffffffL) + +/** + * @brief Converts the chunk coordinates into a 1D index. + * @details Converts the 2D position into an index for a 1D array. + * + * @param x the X coordinate of a block within chunk. + * @param z the Z coordinate of a block within the chunk. + * @return the 1D array index. + * + * @deprecated Will get replaced / moved to a more context-neutral file. + */ #define CHUNK_MEM_IND(x, z) (x * WORLD_CHUNK_SIZE + z) +/** + * @brief Decodes the chunk array 1D index into the original chunk positions. + * @details convets the index of a 1D array into a 2D position. + * + * @param ind the index. + * @return the x coordinate of the block within the chunk and the z coordinate of the block within the chunk. + * + * @deprecated Will get replaced / moved to a more context-neutral file. + */ #define CHUNK_MEM_FROMIND(ind) (ind / WORLD_CHUNK_SIZE), (ind % WORLD_CHUNK_SIZE) +/** + * @brief Represents an empty block's material, Air. + * @details Is equivalent to the block id of the material with id 0 within a block type register. + */ #define CHUNK_NO_BLOCK 0 /** - * A chunk is a 32*32 region in an Cavernfall world. + * @brief A square shaped region within a world containing a specific amount of blocks. + * @details Acts as a block type & data container as well as more. */ class Chunk: public cavernfall::view::ViewEngine, public cavernfall::utils::chunkpos_t { private: - std::bitset data_presence_cache; + /** + * @brief Cache bitset allowing to check if a block has data. + * @details Faster way to check if a block within the block has data without having to check with the hashmap. + */ + std::bitset data_presence_cache; #if !defined(CHUNK_NO_CACHED_PACKET) + /** + * @internal + * @brief Update the cached chunk spawning packet. + * @details Updates the created and cached chunk spawning packet whenever a block changes inside the chunk. + * + * @param block_ind the block index within the chunk that was modified. + * @param id the new block id contained at this block's position. + */ void __update_cached_packet(size_t block_ind, block_id_t id); #endif + /** + * @internal + * @brief Erases a block correctly within the chunk. + * @details Deletes any trace of block data at this index if there is some and cleanly sets the block to air. + * + * @param ind the block index within the chunk to erase. + */ inline void __erase(size_t ind); protected: @@ -48,20 +107,43 @@ class Chunk: public cavernfall::view::ViewEngine, public cavernfall::utils::chun void viewer_remove(cavernfall::player::Player* player) override; public: - block_id_t data[CHUNK_SIZE_TOTAL]; + /** @brief The main chunk data, contains the raw chunk block material ids. */ + block_id_t data[WORLD_CHUNK_SIZE_TOTAL]; + + /** + * @brief An Hashmap containing the block data containers + * @details the key is the block index within the chunk. + */ emhash7::HashMap block_data; #if !defined(CHUNK_NO_CACHED_PACKET) + /** @brief The cached chunk load packet. */ cavernfall::net::NetworkBuff* load_packet; + + /** + * @brief creates the sample chunk load packet. + * @details Constructs load_packet and triggers a NetworkBuff constructor for ChunkLoadPacket. + */ void __craft_load_packet(); #endif + /** + * @brief Creates a chunk. + * @details Creates an empty chunk at the given position. + * + * @param chunkX the X coordinate of the chunk. + * @param chunkZ the Z coordinate of the chunk. + */ Chunk(long chunkX, long chunkZ): chunkpos_t(chunkX, chunkZ) { #if !defined(CHUNK_NO_CACHED_PACKET) this->__craft_load_packet(); #endif } + /** + * @brief Destroys the chunk. + * @details Destructs the chunk and cleanly removes an block data or allocated objects within it. + */ ~Chunk() { #if !defined(CHUNK_NO_CACHED_PACKET) if(this->load_packet != nullptr) delete this->load_packet; @@ -73,9 +155,31 @@ class Chunk: public cavernfall::view::ViewEngine, public cavernfall::utils::chun } + /** + * @brief Sets the block at the given coordinates to be the given block material. + * + * @param x the x coordinate of the block within the chunk (must be within 0 and 15) + * @param z the z coordinate of the block within the chunk (must be within 0 and 15) + * @param id the block material id. + */ void set(int x, int z, block_id_t id); + + /** + * @brief Sets the block at the given coordinates to be the given block material. + * + * @param x the x coordinate of the block within the chunk (must be within 0 and 15) + * @param z the z coordinate of the block within the chunk (must be within 0 and 15) + * @param type the block material. + */ void set(int x, int z, BlockType* type); + /** + * @brief Gets the current block material the given coordinates. + * + * @param x the x coordinate of the block within the chunk (must be within 0 and 15) + * @param z the z coordinate of the block within the chunk (must be within 0 and 15) + * @return the block material id. + */ block_id_t get(int x, int z); /** @@ -114,7 +218,7 @@ class Chunk: public cavernfall::view::ViewEngine, public cavernfall::utils::chun * @param x the X coordinate of the block (within the chunk) * @param z the Z coordinate of the block (within the chunk) * - * @info will do nothing if chunk data already exists for the block. + * Will do nothing if chunk data already exists for the block. * @return the created / gathered block data */ BlockDataContainerBase* get_or_create_data(int x, int z); @@ -126,7 +230,7 @@ class Chunk: public cavernfall::view::ViewEngine, public cavernfall::utils::chun * @param x the X coordinate of the block (within the chunk) * @param z the Z coordinate of the block (within the chunk) * - * @info will do nothing if the block data doesn't have any data + * Will do nothing if the block data doesn't have any data */ void remove_data(int x, int z); diff --git a/includes/cavernfall/world/loader/chunkGen.hpp b/includes/cavernfall/world/loader/chunkGen.hpp index 0425f44f..14c91f2f 100644 --- a/includes/cavernfall/world/loader/chunkGen.hpp +++ b/includes/cavernfall/world/loader/chunkGen.hpp @@ -1,3 +1,10 @@ +/** + * @file chunkGen.hpp + * @brief Handles chunk generation + * + * @details Uses noise to randomly generate chunks based on seeds. +**/ + #pragma once #include @@ -11,10 +18,18 @@ namespace cavernfall::world::gen { //TODO: Store average, max to be able to generate chunks faster +/** + * @internal + * @brief Object representing the result of the blending process + * + * @see ChunkGenerator::perform_biome_blending +**/ class BlendingResult { public: + /** @brief Blending values for each biome **/ float values[BIOME_COUNT]; + /** @brief Creates an empty BlendingResult and set its values to -1 **/ BlendingResult() { for(int i = 0; i < BIOME_COUNT; ++i) { @@ -23,16 +38,30 @@ class BlendingResult { } + /** + * @brief Appends another biome blend to the biome's blending score. + * + * @param biome the biome + * + * @deprecated append does a very simple operation that can be done without it + **/ void append(cavernfall::world::Biome biome) { ++this->values[biome]; } + /** @brief Resets all of the BlendingResult's content and values. **/ void reset() { for(int i = 0; i < BIOME_COUNT; ++i) { this->values[i] = -1; } } + /** + * @brief Computes the total blends. + * @details Adds all biomes blends together and returns it. + * + * @return the total blends. + **/ float getTotal() { float total = 0; @@ -44,6 +73,13 @@ class BlendingResult { return total; } + + /** + * @brief get the maximum blends. + * @details Computes the highest amount of blends per individual biome. + * + * @return the highest amount of blends for a singular biome. + **/ float getMax() { float max = 0; @@ -55,6 +91,10 @@ class BlendingResult { return max; } + /** + * @brief Divides all scores with the given divisor. + * @param div the divisor. + **/ void divide(float div) { for(int i = 0; i < BIOME_COUNT; ++i) { if(this->values[i] == -1) continue; @@ -62,27 +102,56 @@ class BlendingResult { } } + /** @brief Gets the result biome of the blending **/ cavernfall::world::Biome getResult(); }; +/** + * @brief Generates chunks. + * @details Stores the multiple noise generation engines and manages chunk generation. +**/ class ChunkGenerator { private: + /** @brief Noise used to calculate chunk delegations. **/ FastNoiseLite* delegation_noise; + + /** @brief Noise used to calculate detail. **/ FastNoiseLite* detail_noise; + + /** @brief Noise used to calculate chunk biome merging. **/ FastNoiseLite* merge_noise; + + /** @brief Noise used to calculate chunk biomes. **/ FastNoiseLite* biome_noise; public: + /** + * @brief Creates a chunk generator with the given seeds. + * + * @param delegationSeed the seed for the delegation noise + * @param detailSeed the seed for the detail noise + * @param mergeSeed the seed for the biome merging noise + * @param biomeSeed the seed for chunk biomes. + **/ ChunkGenerator(int delegationSeed, int detailSeed, int mergeSeed, int biomeSeed); + + /** @brief Creates a chunk generator with random seeds **/ ChunkGenerator(); + /** @brief Destructs the chunk generator and the noise generators **/ ~ChunkGenerator(); + /** + * @brief Generates the chunk. + * @details Performs chunk generation on the provided chunk instance. + * + * @param chunk the chunk instance to generate in + **/ void generate_chunk(cavernfall::world::Chunk* chunk); /** - * @name get_biome_for_pos - * Gets the corresponding biome for the delegation generation + * @internal + * @brief Gets the corresponding biome for the delegation generation * @param x the X coordinate * @param z the Z coordinate * @return the generated biome @@ -90,8 +159,8 @@ class ChunkGenerator { cavernfall::world::Biome get_biome_for_pos(long x, long z); /** - * @name perform_biome_blending - * Performs biome blending + * @internal + * @brief Performs biome blending * @param x the X coordinate * @param z the Z coordinate * @param result the blending result @@ -99,8 +168,8 @@ class ChunkGenerator { void perform_biome_blending(long x, long z, BlendingResult* result); /** - * @name generate_material_for_biome - * Generates an adequate block type for the given biome + * @internal + * @brief Generates an adequate block type for the given biome * @param x the X coordinate * @param z the Z coordinate * @param biome the biome diff --git a/includes/cavernfall/world/materials.hpp b/includes/cavernfall/world/materials.hpp index dc85bc5a..c615d7a2 100644 --- a/includes/cavernfall/world/materials.hpp +++ b/includes/cavernfall/world/materials.hpp @@ -1,5 +1,7 @@ /** - * Material helpers + * @file materials.hpp + * @brief Helper material definitions. + * @deprecated Extremly outdated and isn't even needed. */ #pragma once diff --git a/includes/cavernfall/world/save.hpp b/includes/cavernfall/world/save.hpp index 40904ec7..7f8c23a7 100644 --- a/includes/cavernfall/world/save.hpp +++ b/includes/cavernfall/world/save.hpp @@ -1,5 +1,6 @@ /** - * World saving and loading related definitions + * @file save.hpp + * @brief World saving and loading related definitions. */ #pragma once @@ -22,9 +23,18 @@ namespace cavernfall::world { class Chunk; +/** + * @internal + * @brief An entry containing a block data. + */ typedef struct region_file_data_entry { + /** @brief the block X coordinate */ int x; + + /** @brief the block Z coordinate */ int z; + + /** @brief the block data container for the given block. */ BlockDataContainerBase* container; } region_file_data_entry; @@ -39,62 +49,207 @@ typedef struct region_file_data_entry { */ class region_file_chunk { private: + /** @brief The amount of allocated chunk block entries. */ size_t allocated_entries; + + /** @brief The currently set amount of chunk block entries. */ size_t entry_sz; void __erase_entries_and_setup(size_t entry_count); public: + /** @brief The stored chunk material IDs. */ block_id_t data[WORLD_CHUNK_SIZE * WORLD_CHUNK_SIZE]; + + /** @brief The stored chunk block data entries. */ region_file_data_entry* entries; + /** @brief Creates a new region file chunk instance. */ region_file_chunk(); + + /** + * @brief Destructs the region file chunk. + * @details Destructs the region file chunk instance and the inner helper structures. + * + * @warning Does NOT free or unload the target chunk in the slightless, only this region file chunk instance. + * @warning Does not trigger file update. + * + * @see world_savefile + */ ~region_file_chunk(); + /** + * @brief Reads the chunk from the handle. + * @details Reads the chunk data from the given file handle. + * + * @param handle the file handle. Must be opened from a world save file for position purposes. + */ void read_from(cavernfall::fs::file_handle& handle); + + /** + * @brief Writes the chunk to the handle. + * @details Writes the chunk data to the given file handle. + * + * @param handle the file handle. Must be opened from a world save file for position purposes. + */ void write_to(cavernfall::fs::file_handle& handle); + /** + * @brief Reads the given chunk's data and copies it there. + * @details Reads the given chunk's data and copies it there for saving purposes. + * + * @param chunk the given chunk. + */ void read_from_chunk(Chunk* chunk); + + /** + * @brief Writes the currently stored data to the given chunk. + * @details Copies the currently stored data to the given chunk's instance. + * + * @param chunk the given chunk. + */ void write_to_chunk(Chunk* chunk); }; +/** + * @brief The header for any region file. + * @details Contains all of the region file header metadata to ensure a safe reading and writing format. + */ typedef struct regionfile_header_t { + /** + * @brief The magic world version number. + * @details Represents the Cavernfall major world version. + */ uint32_t magic; } regionfile_header_t; +/** + * @brief A world's save file. + * @details Represents a world chunk region's save file. + */ class world_savefile { private: + /** + * @brief The lock indicating if the save file is in sync with the actual loaded chunk data. + * + * @warning Is currently bypassed with save and isn't updated. + * @deprecated Will soon be deprecated + */ bool save_lock; + + /** + * @brief The file handle representing the region's file. + */ cavernfall::fs::file_handle handle; + /** + * @internal + * @brief Prepares the chunk for a swap. + * @details Prepares the region file chunk at the given index to be modified and it's data to be swapped. + * + * @param ind the chunk index + */ void __prepare_chunk_for_swap(size_t ind); public: + /** @brief The header of the region file. */ regionfile_header_t header; + + /** @brief The chunks stored within the region file. */ region_file_chunk chunks[WOLRD_REGION_SIZE * WOLRD_REGION_SIZE]; + /** + * @brief Creates a world region save file. + * @details Creates a world region save file with the given path. + * + * @param path the region file's path. + */ world_savefile(const std::filesystem::path& path); + + /** + * @brief Destructs the world save file instance. + * @details Also closes the file handle and destructs any inner instances. + * + * @warning Does not trigger save and instantly closes and flushes the file handle. + */ ~world_savefile(); + /** + * @brief Triggers a save of the world save file. + * @details Instantly triggers a save of the world save file, regardless of the chunk's in-memory state. + * + * @warning Does not check for a write lock, use this with caution. + * @warning Does not use the chunk's current loaded state. + */ void save(); + + /** + * @brief Triggers a load of the world save file. + * @details Instantly triggers a load of the world save file, only updates inner data and not actual chunk. + * + * @warning Only do this if the file exists. + * @warning Does not override any in memory chunks, only the chunks inside the region file helpers. + */ void load(); }; +/** + * @brief The manager for the region save files. + */ class world_savefile_manager { private: + /** @brief The currently loaded world save files. */ emhash7::HashMap files; public: + /** @brief The base world region folder. */ std::filesystem::path region_folder; + /** + * @brief Creates a world save file manager. + * @details Crteates a world save file manager with the given world folder. + */ world_savefile_manager(const std::filesystem::path& parent); + + /** + * @brief Destructs the world save file manager and free's every region folder contained within it. + * + * @warning Doesn't trigger a region file save, use with caution. + */ ~world_savefile_manager(); + /** + * @brief Saves the chunk in the according region file. + * @details Saves the chunk in the corresponding file, creates it if it isn't loaded. + * + * @param chunk the chunk to save. + */ void save_chunk(Chunk* chunk); + + /** + * @brief Loads the chunk. + * @details Loads the chunk from the corresponding chunk file. + * + * @param chunk. + * + * @retval true the chunk loading happened. + * @retval false either the chunk loading failed or the region file didn't exist and thus couldn't be loaded. + */ bool load_chunk(Chunk* chunk); + /** + * @brief Get the region file from the given coordinates. + * @details Gets the region file at the given coordinates and potentially create if it doesn't exist. + * + * @param pos the region position. + * @param seek_only determines if the save file should only search and not create if not found. + * + * @return the world save file. + * @retval nullptr the region file didn't exist yet and seek_only was true. + */ world_savefile* get_savefile(cavernfall::utils::regionpos_t pos, bool seek_only = false); + }; } diff --git a/includes/cavernfall/world/world.hpp b/includes/cavernfall/world/world.hpp index 1c2e58a2..68d5e520 100644 --- a/includes/cavernfall/world/world.hpp +++ b/includes/cavernfall/world/world.hpp @@ -1,3 +1,8 @@ +/** + * @file world.hpp + * @brief World-related definitions. + */ + #pragma once #include @@ -31,32 +36,87 @@ class CavernEntity; namespace cavernfall { +/** + * @brief A world within a Cavernfall server / universe. + */ class World { private: + /** @brief The currently loaded chunks inside the world. */ emhash7::HashMap chunks; public: + /** @brief A thread atomic containing whenever the world ticking is running or not. */ std::atomic running; + + /** + * @brief The current world type based on the Cavernfall epoch. + * @warning Is currently unsed. + */ long time; + /** @brief The currently loaded non-ticking entities. */ cavernfall::structs::linked_list entities; + + /** + * @brief The currently loaded ticking entities. + * @deprecated Will soon be removed to use a scheduler based approach to improve entity lookup times. + */ cavernfall::structs::linked_list ticking_entities; + + /** @brief The currently loaded players. */ cavernfall::structs::linked_list players; + + /** @brief The entity tracker for the world. */ cavernfall::entity::EntityTracker entity_tracker; + + /** @brief The world save file manager for the world. */ cavernfall::world::world_savefile_manager manager; + /** @brief Creates a world in the current folder. */ World(): manager("./world/") { this->time = false; this->running = false; } + /** + * @brief Destructs the world. + * @details Destructs the world as well as everything within it, including entities, chunks and more. Absolutely everything inside. + * + * @warning Does not yet trigger chunk saving, will soon. + */ ~World(); + /** + * @brief Gets the chunk at the given coordinates. + * @details Gets or loads the chunk at the given coordinates depending on state. + * + * @param chunkx the chunk X coordinate. + * @param chunkz the chunk Z coordinate. + * @param load should the chunk be loaded if it isn't already. + * + * @return the chunk at the coordinates. + * @retval nullptr the chunk wasn't loaded and either the loading failed or the loading was set to false. + */ cavernfall::world::Chunk* get_chunk(long chunkx, long chunkz, bool load = true); + + /** + * @brief Loads a chunk at the given coordinates. + * @details Loads and creates a chunk at the given coordinates. + * + * @param chunkX the chunk X coordinate. + * @param chunkZ the chunk Z coordinate. + * @param load_from_region should the chunk be loaded from the region files if possible. + * + * @return the loaded chunk. + * @retval nullptr An extremly critical error happened within the chunk loading process. + * + * @warning This doesn't check if the chunk is already loaded. DO NOT USE THIS FUNCTION unless you absolutely know what you are doing or else you WILL cause memory leaks. + */ cavernfall::world::Chunk* load_chunk(long chunkX, long chunkZ, bool load_from_region = true); /** * @brief Gets the current block at the given position. + * @details If the chunk is not loaded, it will not load it and just return air. * * @param pos the given position * @return the current block id at the position @@ -65,7 +125,7 @@ class World { /** * @brief Checks if the current block at the given position has data or not. - * @info If the chunk is not loaded, it will not load it and just return false. + * @details If the chunk is not loaded, it will not load it and just return false. * * @param pos the position */ @@ -73,17 +133,37 @@ class World { /** * @brief Gets the data of the current block at the given position - * @info If the chunk is not loaded, it will not load it and just return null. + * @details If the chunk is not loaded, it will not load it and just return null. * * @param pos the position * @return the block data container or nullptr if there is none */ cavernfall::world::BlockDataContainerBase* get_data(blockpos_t pos); + /** + * @brief Unloads the chunk at the given coordinates. + * @details Cleanly unloads the chunk and triggers saving if enabled. + * + * @param chunkX the X coordinate of the chunk to unload. + * @param chunkZ the Z coordinate of the chunk to unload. + * @param save determines if the chunk should be saved or not. + */ bool unload_chunk(long chunkX, long chunkZ, bool save = true); + /** + * @brief Ticks the world. + * @details Ticks the world. + * + * @warning Does nothing for now. + */ void tick(); + /** + * @brief Starts the ticking of this world. + * @details Creates a thread that calls the chunk ticking function. + * + * @warning Currently tick doesn't do anything thus this function isn't necessary. + */ void startTicking() { this->running = true; diff --git a/includes/utils/macros.hpp b/includes/utils/macros.hpp index ae1ad8f5..d7e7c8b5 100644 --- a/includes/utils/macros.hpp +++ b/includes/utils/macros.hpp @@ -1,13 +1,43 @@ +/** + * @file utils/macros.hpp + * @brief Useful macros definitions. + */ + #pragma once +/** + * @brief Represents an empty value. + */ #define USING_EMPTY -#define USING_VARN(v) v -#define USING_VARDEF(name, type) type name - +/** + * @brief Represents an value that is true. + */ #define USING_TRUE(...) __VA_ARGS__ + +/** + * @brief Represents an value that is false. + */ #define USING_FALSE(...) +/** + * @brief Allows to bundle __VA_ARGS__ inside another macro that uses them. + */ #define USING(...) __VA_ARGS__ + +/** + * @brief Uses a return statement. + * + * @param ret the return value. + * + * @deprecated Will soon be removed as it a bit useless + */ #define USING_RETURN(ret) return ret; + +/** + * @brief Uses a lambda. + * + * @param encloding_vars the enclosing vars + * @param vars the passed variables. + */ #define USING_LAMBDA(enclosing_vars, vars, ...) [enclosing_vars](vars) {__VA_ARGS__} diff --git a/includes/utils/math.hpp b/includes/utils/math.hpp index 100f7d86..035f19d2 100644 --- a/includes/utils/math.hpp +++ b/includes/utils/math.hpp @@ -1,28 +1,87 @@ +/** + * @file math.hpp + * @brief Math related utilities. + */ + #include #pragma once +/** + * @brief Makes min and max variables. + * + * @param x the first number. + * @param x1 the second number. + * @param minVar the variable name for the minimum value. + * @param maxVar the variable name for the maximum value. + * @param type the type of vazriable + */ #define MINMAX(x, x1, minVar, maxVar, type) \ type minVar = x > x1 ? x1 : x; \ type maxVar = x > x1 ? x : x1; +/** + * @brief Returns the maximum value between the two. + * + * @param x the first number. + * @param x1 the second number. + * + * @return the highest number amoungst the two others. + */ #define MAXNUM(x, x1) (x < x1 ? x1 : x) +/** + * @brief Returns the positive version of the integer. + * + * @param x the number. + * + * @return the positive version. + */ #define POSITIVE(x) x < 0 ? -x : x -#define NEGATIVE(x) x < 0 ? x : -x -#define SIGN(s, x) s < 0 ? NEGATIVE(x) : POSITIVE(x) +/** + * @brief Returns the negative version of the integer. + * + * @param x the number. + * + * @return the negative version. + */ +#define NEGATIVE(x) x < 0 ? x : -x +/** + * @brief Clamps the number. + * + * @param val the value. + * @param max_abs the max value to clamp with. + * + * @return the result. + */ inline double clamp(double val, double max_abs) { if (val > max_abs) return max_abs; if (val < -max_abs) return -max_abs; return val; } +/** + * @brief Handles division with flooring. + * + * @param x the number to divide with. + * @param size the divisor. + * + * @return the floor division result. + */ inline long floor_div(long x, long size) { return (x >= 0) ? (x / size) : ((x - size + 1) / size); } +/** + * @brief Compile time power calculation. + * + * @param base the base + * @param exp the exponent + * + * @return the power result. + */ template constexpr T compile_pow(T base, unsigned exp) { static_assert(std::is_arithmetic_v, "T must be a number type!"); diff --git a/includes/utils/platform.hpp b/includes/utils/platform.hpp index caecbe05..3d22460a 100644 --- a/includes/utils/platform.hpp +++ b/includes/utils/platform.hpp @@ -1,3 +1,9 @@ +/** + * @file platform.hpp + * @brief Platform macros. + * @details Provides a few platform-related macros to perform stuff on specific platforms/environments +**/ + #ifdef _WIN32 #define USING_WIN(...) __VA_ARGS__ #define VAL_WIN(t, f) t diff --git a/includes/utils/pos.hpp b/includes/utils/pos.hpp index 36936e89..c5620333 100644 --- a/includes/utils/pos.hpp +++ b/includes/utils/pos.hpp @@ -1,5 +1,6 @@ /** - * Position-related + * @file utils/pos.hpp + * @brief Position related definitions. */ #pragma once @@ -12,7 +13,7 @@ namespace cavernfall::utils { /** - * Represents a position in the 2d or 3d plane. + * @brief Represents a position in the 2d or 3d plane. * Current implementations: * - position_3d (actual position for entities and more) -> pos3d * - blockpos_3d (actual position for blocks) -> pos3d @@ -25,27 +26,107 @@ namespace cavernfall::utils { */ template class pos_t { public: + /** @brief The X position as T */ T x; + + /** @brief The Y position as T */ T y; + + /** @brief the Z position as T. */ T z; + /** + * @brief Creates a position. + * + * @param x the X position. + * @param y the Y position. + * @param z the Z position. + */ pos_t(T x, T y, T z); + + /** + * @brief Creates a position. + * @details The Y positon will be set to 0. + * + * @param x the X position. + * @param z the Z position. + */ pos_t(T x, T z); + /** + * @brief Converts this position to a real position. + * + * @return the position as a real position. + * + * @warning If the current time is the same as the destined type, the function will return this instance. + * @warning The current instance will not be overriden and a new one will be passed as result if any conversions were done. + */ pos_t to_real_pos(); + + /** + * @brief Converts this position to a chunk position. + * + * @return the position as a chunk position. + * + * @warning If the current time is the same as the destined type, the function will return this instance. + * @warning The current instance will not be overriden and a new one will be passed as result if any conversions were done. + */ pos_t to_chunk_pos(); + + /** + * @brief Converts this position to a block position. + * + * @return the position as a block position. + * + * @warning If the current time is the same as the destined type, the function will return this instance. + * @warning The current instance will not be overriden and a new one will be passed as result if any conversions were done. + */ pos_t to_block_pos(); + + /** + * @brief Converts this position to a region position. + * + * @return the position as a region position. + * + * @warning If the current time is the same as the destined type, the function will return this instance. + * @warning The current instance will not be overriden and a new one will be passed as result if any conversions were done. + */ pos_t to_region_pos(); + /** + * @brief Checks for equality amongst two values. + * @details Equality checks the x values for absolute equality. + * + * @warning Will not perform any conversions, meaning if the type is different, the return will be false either way. + */ bool operator==(const pos_t& other) const { - if constexpr(y_axis) return this->x == other.x && this->y == other.y && this->z == other.z; + if constexpr(y_axis) this->x == other.x && this->y == other.y && this->z == other.z; return this->x == other.x && this->z == other.z; } }; +/** + * @brief Represents a real position. + * @details The type of position used for entities and actual real positions. + */ typedef pos_t realpos_t; + +/** + * @brief Represents a chunk position. + * @details The type of position used to know where chunks are. + */ typedef pos_t chunkpos_t; + +/** + * @brief Represents a block position. + * @details The type of position used to know where a block is. + */ typedef pos_t blockpos_t; + +/** + * @brief Represents a region position. + * @details The type of position used to know where a chunk region is. + */ typedef pos_t regionpos_t; } diff --git a/includes/utils/rand.hpp b/includes/utils/rand.hpp index a2ae578a..9e585fb5 100644 --- a/includes/utils/rand.hpp +++ b/includes/utils/rand.hpp @@ -1,3 +1,9 @@ +/** + * @file rand.hpp + * @brief Random utilities + * @details Random functions used across Cavernfall +**/ + #pragma once #include @@ -5,13 +11,39 @@ #include +/** + * @brief generates a random integer within the given max range + * + * @param max The max integer bound + * + * @return the generated integer + * + * @warning randomness is not safe and uses rand() +**/ #define randIntRanged(max) randInt() % (max + 1) +/** + * @brief Generates a random integer + * + * @return the generated integer + * + * @warning randomness is not safe and uses rand() + * @see randIntRanged() +**/ static int randInt() { srand(time(0)); return rand(); } +/** + * @brief Generates a random numeric value of type T + * + * @return the generated numeric value T + * + * @warning randomness is not safe and uses rand() + * @info the returned number will be an int casted to T, the T bounds will thus not be applied onto the given number. + * @deprecated Unused and useless for the most part +**/ template static T random() { return (T)(randInt()); } \ No newline at end of file diff --git a/includes/utils/typetraits.hpp b/includes/utils/typetraits.hpp index cafb9027..7985810c 100644 --- a/includes/utils/typetraits.hpp +++ b/includes/utils/typetraits.hpp @@ -1,12 +1,26 @@ +/** + * @file typetraits.hpp + * @brief Useful type traits. + * @details A few type traits that are used within functions to classify types correctly. +**/ + #pragma once #include namespace cavernfall::utils { +/** + * @brief Represents any number / numeric type. + * @details Represents both integral and floating point numbers. +**/ template concept NumberType = std::integral || std::floating_point; +/** + * @brief Represents a traversable / invokable type. + * @deprecated Unused, unreliable, will soon be removed. +**/ template concept traversable = std::same_as, void>; diff --git a/includes/utils/vec.hpp b/includes/utils/vec.hpp index 7f1cc311..9a2a71d9 100644 --- a/includes/utils/vec.hpp +++ b/includes/utils/vec.hpp @@ -1,3 +1,8 @@ +/** + * @file utils/vec.hpp + * @brief Vector definitions. + */ + #pragma once #include @@ -6,125 +11,161 @@ #include -#define VEC_OPERATION(opName, sign) \ - void opName(double x = 0, double z = 0) { \ - this->x sign x; \ - this->y sign y; \ - this->z sign z; \ - } \ - void opName(double num) { \ - this->x sign num; \ - this->y sign num; \ - this->z sign num; \ - } - namespace cavernfall::maths { /** - * Represents a 3D vector + * @brief Represents a 3D vector. */ class Vec { public: + /** @brief The X value. */ double x; + + /** @brief The Y value. */ double y; + + /** @brief The Z value. */ double z; - Vec(double x = 0, double y = 0, double z = 0) { - this->x = x; - this->y = y; - this->z = z; - } + /** + * @brief Creates a vector. + * + * @param x the X value of the vector. + * @param y the Y value of the vector. + * @param z the Z value of the vector. + */ + Vec(double x, double y, double z); + + /** + * @brief Creates an empty vector. + */ + Vec(); + + /** + * @brief Adds the given values to the vector. + * + * @param x the X value to add. + * @param y the Y value to add. + * @param z the Z value to add. + */ + void add(double x, double y, double z); + + /** + * @brief Adds the given vector to the vector. + * + * @param vec the vector to add. + */ + void add(Vec vec); + + /** + * @brief Removes the given values to vector. + * + * @param x the X value to remove. + * @param y the Y value to remove. + * @param z the Z value to remove. + */ + void remove(double x, double y, double z); + + /** + * @brief Removes the given vector to the vector. + * + * @param vec the vector to remove. + */ + void remove(Vec vec); - VEC_OPERATION(add, +=) - VEC_OPERATION(remove, -=) - VEC_OPERATION(multiply, *=) - VEC_OPERATION(divide, /=) + /** + * @brief Multiplies the vector with the given values + * + * @param x the X value to multiply with. + * @param y the Y value to multiply with. + * @param z the Z value to multiply with. + */ + void multiply(double x, double y, double z); - void remove_signed(double x, double y, double z) { - this->x -= x; - this->y -= y; - this->z -= z; - } + /** + * @brief Multiplies the vector with the given vector. + * + * @param vec the vector to multiply with. + */ + void multiply(Vec vec); /** - * @name dist - * Gets the 2D distance from the given vector points + * @brief Divides the vector with the given values. + * + * @param x the X value to divide with. + * @param y the Y value to divide with. + * @param z the Z value to divide with. + */ + void divide(double x, double y, double z); + + /** + * @brief Divides with the vector with the given vector. + * + * @param vec the vector to divide with. + */ + void divide(Vec vec); + + /** + * @brief Gets the 2D distance from the given vector points + * * @param x the X vector point * @param y the Y vector point * @param z the Z vector point + * * @return the distance in floats */ - float dist(double x, double y, double z) { - MINMAX(this->x, x, minx, maxx, double); - MINMAX(this->y, y, miny, maxy, double); - MINMAX(this->z, z, minz, maxz, double); - - - return std::sqrt(std::pow(maxx - minx, 2) + std::pow(maxy - miny, 2) + std::pow(maxz - minz, 2)); - } + float dist(double x, double y, double z); /** - * @name dist_true - * Gets the "true" distance (basically no min/max checking). + * @brief Gets the "true" distance (basically no min/max checking). + * * @param x the X vector point * @param y the Y vector point * @param z the Z vector point + * * @return the distance in floats */ - float dist_true(double x, double y, double z) { - return std::sqrt(std::pow(x - this->x, 2) + std::pow(y - this->y, 2) + std::pow(z - this->z, 2)); - } + float dist_true(double x, double y, double z); /** - * @name len - * Gets the length of the vector + * @brief Gets the length of the vector + * + * @return the size in float. */ - float len() { - return std::sqrt(std::pow(this->x, 2) + std::pow(this->y, 2) + std::pow(this->z, 2)); - } + float len(); /** - * @name dot - * Calculates the dot product of this vector with another. The dot product - * is defined as x1*x2+y1*y2+z1*z2 + * @brief Calculates the dot product of this vector with another. + * @details The dot product is defined as x1*x2+y1*y2+z1*z2 + * * @param x the X value of the other vector * @param y the Y value of the other vector * @param z the Z value of the other vector + * * @return the dot product */ - double dot(double x, double y, double z) { - return this->x * x + this->y + y + this->z * z; - } + double dot(double x, double y, double z); /** - * @name angle - * Gets the angle between this vector and another in radians + * @brief Gets the angle between this vector and another in radians + * * @param x the X value of the other vector * @param y the Y value of the other vector * @param z the Z value of the other vector + * * @return angle in radians */ - float angle(double x, double y, double z) { - double dot = this->dot(x, y, z) / (this->len() * std::sqrt(std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2))); - - return (float) acos(dot); - } + float angle(double x, double y, double z); /** - * @name normalize - * Converts this vector to an unit vector + * @brief Converts this vector to an unit vector */ - void normalize() { - double length = this->len(); - - this->x /= length; - this->y /= length; - this->z /= length; - } + void normalize(); - bool is_null() { - return this->x == 0 && this->y == 0 && this->z == 0; - } + /** + * @brief Determines if the vector is empty. + */ + bool is_null(); }; diff --git a/src/entity/entity.cpp b/src/entity/entity.cpp index 2fc7dfec..5563bde1 100644 --- a/src/entity/entity.cpp +++ b/src/entity/entity.cpp @@ -49,8 +49,8 @@ void CavernEntity::viewer_remove(Player* player) { } void CavernEntity::set_position(double x, double y, double z) { - long cx = (long) (x / CHUNK_SIDE_SIZE); - long cz = (long) (z / CHUNK_SIDE_SIZE); + long cx = (long) (x / WORLD_CHUNK_SIZE); + long cz = (long) (z / WORLD_CHUNK_SIZE); if(cx != this->get_chunk_x() || cz != get_chunk_z()) { server->world->entity_tracker.entity_move(this, cx, cz); @@ -88,7 +88,7 @@ void CavernEntity::tick() { double motY = clamp(this->velocity.y, MAX_VERTICAL_MOTION_IN_ONE_TICK); double motZ = clamp(this->velocity.z, MAX_MOTION_IN_ONE_TICK); - this->velocity.remove_signed(motX, motY, motZ); + this->velocity.remove(motX, motY, motZ); this->set_position(this->x + motX, this->y + motY, this->z + motZ); } } diff --git a/src/entity/player.cpp b/src/entity/player.cpp index 9947312b..96177de9 100644 --- a/src/entity/player.cpp +++ b/src/entity/player.cpp @@ -88,8 +88,8 @@ void Player::set_position(double x, double y, double z) { cavernfall::entity::EntityTracker* tracker = &server->world->entity_tracker; - long newChunkX = (long) (x / CHUNK_SIDE_SIZE); - long newChunkZ = (long) (z / CHUNK_SIDE_SIZE); + long newChunkX = (long) (x / WORLD_CHUNK_SIZE); + long newChunkZ = (long) (z / WORLD_CHUNK_SIZE); if(this->get_chunk_x() != newChunkX || this->get_chunk_z() != newChunkZ) { // The player changed chunks, update the chunks diff --git a/src/godotlocal/player.cpp b/src/godotlocal/player.cpp index 8700cc99..23f72344 100644 --- a/src/godotlocal/player.cpp +++ b/src/godotlocal/player.cpp @@ -12,7 +12,7 @@ bool LocalPlayerBase::handle_chunk_load(cavernfall::world::Chunk* chunk) { Vector2 pos = Vector2(chunk->x, chunk->z); PackedByteArray arr = PackedByteArray(); - arr.resize(CHUNK_SIZE_TOTAL * chunk->sections.size() + 1); + arr.resize(WORLD_CHUNK_SIZE_TOTAL * chunk->sections.size() + 1); int index = 0; @@ -22,7 +22,7 @@ bool LocalPlayerBase::handle_chunk_load(cavernfall::world::Chunk* chunk) { for(int y = 0; y < chunk->sections.size(); ++y) { cavernfall::world::ChunkSection* sect = &chunk->sections[y]; - for(int i = 0; i < CHUNK_SIZE_TOTAL; ++i) { + for(int i = 0; i < WORLD_CHUNK_SIZE_TOTAL; ++i) { arr[index++] = sect->data[i]; } } diff --git a/src/utils/vec.cpp b/src/utils/vec.cpp new file mode 100644 index 00000000..b0f2621e --- /dev/null +++ b/src/utils/vec.cpp @@ -0,0 +1,102 @@ +#include + +using namespace cavernfall::maths; + +Vec::Vec(double x, double y, double z) { + this->x = x; + this->y = y; + this->z = z; +} + +Vec::Vec() { + this->x = 0; + this->y = 0; + this->z = 0; +} + +void Vec::add(double x, double y, double z) { + this->x += x; + this->y += y; + this->z += z; +} + +void Vec::add(Vec v) { + this->x += v.x; + this->y += v.y; + this->z += v.z; +} + +void Vec::remove(double x, double y, double z) { + this->x -= x; + this->y -= y; + this->z -= z; +} + +void Vec::remove(Vec v) { + this->x -= v.x; + this->y -= v.y; + this->z -= v.z; +} + +void Vec::multiply(double x, double y, double z) { + this->x *= x; + this->y *= y; + this->z *= z; +} + +void Vec::multiply(Vec v) { + this->x *= v.x; + this->y *= v.y; + this->z *= v.z; +} + +void Vec::divide(double x, double y, double z) { + this->x /= x; + this->y /= y; + this->z /= z; +} + +void Vec::divide(Vec v) { + this->x /= v.x; + this->y /= v.y; + this->z /= v.z; +} + +float Vec::dist(double x, double y, double z) { + MINMAX(this->x, x, minx, maxx, double); + MINMAX(this->y, y, miny, maxy, double); + MINMAX(this->z, z, minz, maxz, double); + + + return std::sqrt(std::pow(maxx - minx, 2) + std::pow(maxy - miny, 2) + std::pow(maxz - minz, 2)); +} + +float Vec::dist_true(double x, double y, double z) { + return std::sqrt(std::pow(x - this->x, 2) + std::pow(y - this->y, 2) + std::pow(z - this->z, 2)); +} + +float Vec::len() { + return std::sqrt(std::pow(this->x, 2) + std::pow(this->y, 2) + std::pow(this->z, 2)); +} + +double Vec::dot(double x, double y, double z) { + return this->x * x + this->y + y + this->z * z; +} + +float Vec::angle(double x, double y, double z) { + double dot = this->dot(x, y, z) / (this->len() * std::sqrt(std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2))); + + return (float) acos(dot); +} + +void Vec::normalize() { + double length = this->len(); + + this->x /= length; + this->y /= length; + this->z /= length; +} + +bool Vec::is_null() { + return this->x == 0 && this->y == 0 && this->z == 0; +} \ No newline at end of file diff --git a/testing b/testing new file mode 100644 index 00000000..9347dd39 Binary files /dev/null and b/testing differ