diff --git a/.idea/misc.xml b/.idea/misc.xml index 56bcc68c..fa3f5e2d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -6,14 +6,12 @@ - - - + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17f5a6c4..ab0391aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,321 +1,321 @@ add_library(Zepha_Core - client/Client.cpp - client/Client.h - client/conn/ClientNetworkInterpreter.cpp - client/conn/ClientNetworkInterpreter.h - client/conn/ServerConnection.cpp - client/conn/ServerConnection.h - client/entity/ParticleEntity.cpp - client/entity/ParticleEntity.h - client/entity/PlayerEntity.h - client/entity/WireframeEntity.cpp - client/entity/WireframeEntity.h - client/graph/Camera.cpp - client/graph/Camera.h - client/graph/Drawable.h - client/graph/DrawableGroup.cpp - client/graph/DrawableGroup.h - client/graph/Font.cpp - client/graph/Font.h - client/graph/mesh/ChunkMesh.cpp - client/graph/mesh/ChunkMesh.h - client/graph/mesh/ChunkMeshGenerator.cpp - client/graph/mesh/ChunkMeshGenerator.h - client/graph/mesh/ChunkRenderElem.h - client/graph/mesh/ChunkVertex.h - client/graph/mesh/EntityMesh.cpp - client/graph/mesh/EntityMesh.h - client/graph/mesh/EntityVertex.h - client/graph/mesh/Mesh.cpp - client/graph/mesh/Mesh.h - client/graph/mesh/MeshChunk.cpp - client/graph/mesh/MeshChunk.h - client/graph/Model.cpp - client/graph/Model.h - client/graph/ModelAnimation.cpp - client/graph/ModelAnimation.h - client/graph/ModelBone.cpp - client/graph/ModelBone.h - client/graph/Renderer.cpp - client/graph/Renderer.h - client/graph/shader/BlurShader.cpp - client/graph/shader/BlurShader.h - client/graph/shader/EntityGeometryShader.cpp - client/graph/shader/EntityGeometryShader.h - client/graph/shader/GuiUniforms.h - client/graph/shader/LightingShader.cpp - client/graph/shader/LightingShader.h - client/graph/shader/Shader.cpp - client/graph/shader/Shader.h - client/graph/shader/SSAOShader.cpp - client/graph/shader/SSAOShader.h - client/graph/shader/WorldGeometryShader.cpp - client/graph/shader/WorldGeometryShader.h - client/graph/Texture.cpp - client/graph/Texture.h - client/gui/basic/GuiContainer.cpp - client/gui/basic/GuiContainer.h - client/gui/basic/GuiGraph.cpp - client/gui/basic/GuiGraph.h - client/gui/basic/GuiInventoryItem.cpp - client/gui/basic/GuiInventoryItem.h - client/gui/basic/GuiModel.cpp - client/gui/basic/GuiModel.h - client/gui/basic/GuiRect.cpp - client/gui/basic/GuiRect.h - client/gui/basic/GuiText.cpp - client/gui/basic/GuiText.h - client/gui/compound/GuiImageButton.cpp - client/gui/compound/GuiImageButton.h - client/gui/compound/GuiInventoryList.cpp - client/gui/compound/GuiInventoryList.h - client/gui/compound/GuiLabelledGraph.cpp - client/gui/compound/GuiLabelledGraph.cpp - client/gui/DebugGui.cpp - client/gui/DebugGui.h - client/gui/GameGui.cpp - client/gui/GameGui.h - client/gui/GameGuiBuilder.cpp - client/gui/GameGuiBuilder.h - client/gui/GuiBuilder.cpp - client/gui/GuiBuilder.h - client/gui/GuiComponent.cpp - client/gui/GuiComponent.h - client/gui/SerialGui.h - client/Input.cpp - client/Input.h - client/LocalServerInstance.cpp - client/LocalServerInstance.h - client/menu/MenuSandbox.cpp - client/menu/MenuSandbox.h - client/menu/SubgameConfig.h - client/menu/SubgameDef.h - client/scene/ConnectScene.cpp - client/scene/ConnectScene.h - client/scene/GameScene.cpp - client/scene/GameScene.h - client/scene/LuaErrorScene.cpp - client/scene/LuaErrorScene.h - client/scene/MainMenuScene.cpp - client/scene/MainMenuScene.h - client/scene/Scene.h - client/scene/SceneManager.cpp - client/scene/SceneManager.h - client/stream/ChunkMeshDetails.h - client/stream/MeshGenStream.cpp - client/stream/MeshGenStream.h - client/stream/WorldInterpolationStream.cpp - client/stream/WorldInterpolationStream.h - client/Window.cpp - client/Window.h - game/atlas/asset/AssetStorage.h - game/atlas/asset/AssetType.h - game/atlas/asset/AtlasRef.h - game/atlas/asset/ModelStore.h - game/atlas/asset/SerializedModel.h - game/atlas/asset/ServerTexture.h - game/atlas/BiomeAtlas.cpp - game/atlas/BiomeAtlas.h - game/atlas/DefinitionAtlas.cpp - game/atlas/DefinitionAtlas.h - game/atlas/LocalBiomeAtlas.cpp - game/atlas/LocalBiomeAtlas.h - game/atlas/LocalDefinitionAtlas.cpp - game/atlas/LocalDefinitionAtlas.h - game/atlas/ServerBiomeAtlas.cpp - game/atlas/ServerBiomeAtlas.h - game/atlas/ServerDefinitionAtlas.cpp - game/atlas/ServerDefinitionAtlas.h - game/atlas/TextureAtlas.cpp - game/atlas/TextureAtlas.h + client/Client.cpp + client/Client.h + client/conn/ClientNetworkInterpreter.cpp + client/conn/ClientNetworkInterpreter.h + client/conn/ServerConnection.cpp + client/conn/ServerConnection.h + client/entity/ParticleEntity.cpp + client/entity/ParticleEntity.h + client/entity/PlayerEntity.h + client/entity/WireframeEntity.cpp + client/entity/WireframeEntity.h + client/graph/Camera.cpp + client/graph/Camera.h + client/graph/Drawable.h + client/graph/DrawableGroup.cpp + client/graph/DrawableGroup.h + client/graph/Font.cpp + client/graph/Font.h + client/graph/mesh/ChunkMesh.cpp + client/graph/mesh/ChunkMesh.h + client/graph/mesh/ChunkMeshGenerator.cpp + client/graph/mesh/ChunkMeshGenerator.h + client/graph/mesh/ChunkRenderElem.h + client/graph/mesh/ChunkVertex.h + client/graph/mesh/EntityMesh.cpp + client/graph/mesh/EntityMesh.h + client/graph/mesh/EntityVertex.h + client/graph/mesh/Mesh.cpp + client/graph/mesh/Mesh.h + client/graph/mesh/MeshChunk.cpp + client/graph/mesh/MeshChunk.h + client/graph/Model.cpp + client/graph/Model.h + client/graph/ModelAnimation.cpp + client/graph/ModelAnimation.h + client/graph/ModelBone.cpp + client/graph/ModelBone.h + client/graph/Renderer.cpp + client/graph/Renderer.h + client/graph/shader/BlurShader.cpp + client/graph/shader/BlurShader.h + client/graph/shader/EntityGeometryShader.cpp + client/graph/shader/EntityGeometryShader.h + client/graph/shader/GuiUniforms.h + client/graph/shader/LightingShader.cpp + client/graph/shader/LightingShader.h + client/graph/shader/Shader.cpp + client/graph/shader/Shader.h + client/graph/shader/SSAOShader.cpp + client/graph/shader/SSAOShader.h + client/graph/shader/WorldGeometryShader.cpp + client/graph/shader/WorldGeometryShader.h + client/graph/Texture.cpp + client/graph/Texture.h + client/gui/basic/GuiContainer.cpp + client/gui/basic/GuiContainer.h + client/gui/basic/GuiGraph.cpp + client/gui/basic/GuiGraph.h + client/gui/basic/GuiInventoryItem.cpp + client/gui/basic/GuiInventoryItem.h + client/gui/basic/GuiModel.cpp + client/gui/basic/GuiModel.h + client/gui/basic/GuiRect.cpp + client/gui/basic/GuiRect.h + client/gui/basic/GuiText.cpp + client/gui/basic/GuiText.h + client/gui/compound/GuiImageButton.cpp + client/gui/compound/GuiImageButton.h + client/gui/compound/GuiInventoryList.cpp + client/gui/compound/GuiInventoryList.h + client/gui/compound/GuiLabelledGraph.cpp + client/gui/compound/GuiLabelledGraph.cpp + client/gui/DebugGui.cpp + client/gui/DebugGui.h + client/gui/GameGui.cpp + client/gui/GameGui.h + client/gui/GameGuiBuilder.cpp + client/gui/GameGuiBuilder.h + client/gui/GuiBuilder.cpp + client/gui/GuiBuilder.h + client/gui/GuiComponent.cpp + client/gui/GuiComponent.h + client/gui/SerialGui.h + client/Input.cpp + client/Input.h + client/LocalServerInstance.cpp + client/LocalServerInstance.h + client/menu/MenuSandbox.cpp + client/menu/MenuSandbox.h + client/menu/SubgameConfig.h + client/menu/SubgameDef.h + client/scene/ConnectScene.cpp + client/scene/ConnectScene.h + client/scene/GameScene.cpp + client/scene/GameScene.h + client/scene/LuaErrorScene.cpp + client/scene/LuaErrorScene.h + client/scene/MainMenuScene.cpp + client/scene/MainMenuScene.h + client/scene/Scene.h + client/scene/SceneManager.cpp + client/scene/SceneManager.h + client/stream/ChunkMeshDetails.h + client/stream/MeshGenStream.cpp + client/stream/MeshGenStream.h + client/stream/WorldInterpolationStream.cpp + client/stream/WorldInterpolationStream.h + client/Window.cpp + client/Window.h + game/atlas/asset/AssetStorage.h + game/atlas/asset/AssetType.h + game/atlas/asset/AtlasRef.h + game/atlas/asset/ModelStore.h + game/atlas/asset/SerializedModel.h + game/atlas/asset/ServerTexture.h + game/atlas/BiomeAtlas.cpp + game/atlas/BiomeAtlas.h + game/atlas/DefinitionAtlas.cpp + game/atlas/DefinitionAtlas.h + game/atlas/LocalBiomeAtlas.cpp + game/atlas/LocalBiomeAtlas.h + game/atlas/LocalDefinitionAtlas.cpp + game/atlas/LocalDefinitionAtlas.h + game/atlas/ServerBiomeAtlas.cpp + game/atlas/ServerBiomeAtlas.h + game/atlas/ServerDefinitionAtlas.cpp + game/atlas/ServerDefinitionAtlas.h + game/atlas/TextureAtlas.cpp + game/atlas/TextureAtlas.h game/def/BiomeDef.h - game/def/BlockDef.cpp - game/def/BlockDef.h - game/def/CraftItemDef.cpp - game/def/CraftItemDef.h - game/def/ItemDef.h - game/def/mesh/BlockModel.cpp - game/def/mesh/BlockModel.h - game/def/mesh/BlockModelVertex.h - game/def/mesh/MeshPart.cpp - game/def/mesh/MeshPart.h - game/def/mesh/SelectionBox.h - game/def/mesh/ShaderMod.h - game/LocalSubgame.cpp - game/LocalSubgame.h - game/ServerSubgame.cpp - game/ServerSubgame.h - game/Subgame.h - lua/Callback.h - lua/customization/vec3.hpp - lua/ErrorFormatter.cpp - lua/ErrorFormatter.h - lua/LocalLuaParser.cpp - lua/LocalLuaParser.h - lua/LocalModHandler.cpp - lua/LocalModHandler.h - lua/LuaKeybindHandler.cpp - lua/LuaKeybindHandler.h - lua/LuaMod.cpp - lua/LuaMod.h - lua/LuaParser.cpp - lua/LuaParser.h - lua/modules/BaseModule.h - lua/modules/create_structure.h - lua/modules/Dimension.cpp - lua/modules/Dimension.h - lua/modules/mSetGui.h - lua/modules/mStartGame.h - lua/modules/SubgameModule.cpp - lua/modules/SubgameModule.h - lua/modules/Time.cpp - lua/modules/Time.h - lua/register/RegisterBiome.h + game/def/BlockDef.cpp + game/def/BlockDef.h + game/def/CraftItemDef.cpp + game/def/CraftItemDef.h + game/def/ItemDef.h + game/def/mesh/BlockModel.cpp + game/def/mesh/BlockModel.h + game/def/mesh/BlockModelVertex.h + game/def/mesh/MeshPart.cpp + game/def/mesh/MeshPart.h + game/def/mesh/SelectionBox.h + game/def/mesh/ShaderMod.h + game/LocalSubgame.cpp + game/LocalSubgame.h + game/ServerSubgame.cpp + game/ServerSubgame.h + game/Subgame.h + lua/Callback.h + lua/customization/vec3.hpp + lua/ErrorFormatter.cpp + lua/ErrorFormatter.h + lua/LocalLuaParser.cpp + lua/LocalLuaParser.h + lua/LocalModHandler.cpp + lua/LocalModHandler.h + lua/LuaKeybindHandler.cpp + lua/LuaKeybindHandler.h + lua/LuaMod.cpp + lua/LuaMod.h + lua/LuaParser.cpp + lua/LuaParser.h + lua/modules/BaseModule.h + lua/modules/create_structure.h + lua/modules/Dimension.cpp + lua/modules/Dimension.h + lua/modules/mSetGui.h + lua/modules/mStartGame.h + lua/modules/SubgameModule.cpp + lua/modules/SubgameModule.h + lua/modules/Time.cpp + lua/modules/Time.h + lua/register/RegisterBiome.h lua/register/RegisterBlock.h lua/register/RegisterItem.h - lua/register/RegisterKeybind.h - lua/ServerLuaParser.cpp - lua/ServerLuaParser.h - lua/ServerModHandler.cpp - lua/ServerModHandler.h - lua/usertype/AnimationManager.cpp - lua/usertype/AnimationManager.h - lua/usertype/BaseUsertype.h - lua/usertype/Dimension.cpp - lua/usertype/Dimension.h - lua/usertype/Entity.cpp - lua/usertype/Entity.h - lua/usertype/Inventory.cpp - lua/usertype/Inventory.h - lua/usertype/InventoryList.cpp - lua/usertype/InventoryList.h - lua/usertype/ItemStack.cpp - lua/usertype/ItemStack.h - lua/usertype/LuaGuiElement.cpp - lua/usertype/LuaGuiElement.h - lua/usertype/Player.cpp - lua/usertype/Player.h - lua/usertype/SubgameUsertype.h - lua/usertype/Target.cpp - lua/usertype/Target.h - server/Server.cpp - server/Server.h - server/ServerClient.cpp - server/ServerClient.h - server/ServerClients.cpp - server/ServerClients.h - server/ServerConfig.cpp - server/ServerConfig.h - server/stream/ServerGenStream.cpp - server/stream/ServerGenStream.h - server/stream/ServerPacketStream.cpp - server/stream/ServerPacketStream.h - StartGame.h - util/Any.h - util/CovariantPtr.h - util/frustum/Frustum.cpp - util/frustum/Frustum.h - util/frustum/FrustumAABB.cpp - util/frustum/FrustumAABB.h - util/frustum/FrustumPlane.cpp - util/frustum/FrustumPlane.h - util/Interp.h - util/Lockable.h - util/Log.h - util/Mat4Conv.h - util/net/Address.h - util/net/Deserializer.h - util/net/NetHandler.cpp - util/net/NetHandler.h - util/net/NetState.h - util/net/Packet.cpp - util/net/Packet.h - util/net/PacketView.cpp - util/net/PacketView.h - util/net/Serializer.h - util/Ray.cpp - util/Ray.h - util/RIE.h - util/Schematic.cpp - util/Schematic.h - util/Space.h - util/Target.cpp - util/Target.h - util/Timer.cpp - util/Timer.h - util/Util.h - util/Vec.h - util/Voronoi3D.cpp - util/Voronoi3D.h - world/dim/chunk/Chunk.cpp - world/dim/chunk/Chunk.h - world/dim/chunk/MapBlock.cpp - world/dim/chunk/MapBlock.h - world/dim/chunk/Region.cpp - world/dim/chunk/Region.h - world/dim/Dimension.cpp - world/dim/Dimension.h - world/dim/DimensionBase.cpp - world/dim/DimensionBase.h - world/dim/ent/AnimationSegment.h - world/dim/ent/AnimationState.cpp - world/dim/ent/AnimationState.h - world/dim/ent/AnimChannel.cpp - world/dim/ent/AnimChannel.h - world/dim/ent/Collision.cpp - world/dim/ent/Collision.h - world/dim/ent/DrawableEntity.cpp - world/dim/ent/DrawableEntity.h - world/dim/ent/Entity.cpp - world/dim/ent/Entity.h - world/dim/ent/LocalLuaEntity.cpp - world/dim/ent/LocalLuaEntity.h - world/dim/ent/LuaEntity.cpp - world/dim/ent/LuaEntity.h - world/dim/ent/ServerLuaEntity.cpp - world/dim/ent/ServerLuaEntity.h - world/dim/file/FileManipulator.cpp - world/dim/file/FileManipulator.h - world/dim/LocalDimension.cpp - world/dim/LocalDimension.h - world/dim/ServerDimension.cpp - world/dim/ServerDimension.h - world/gen/MapGen.cpp - world/gen/MapGen.h - world/gen/MapGenProps.cpp - world/gen/MapGenProps.h - world/gen/NoiseSample.cpp - world/gen/NoiseSample.h - world/inv/Inventory.cpp - world/inv/Inventory.h - world/inv/InventoryList.cpp - world/inv/InventoryList.h - world/inv/InventoryRefs.cpp - world/inv/InventoryRefs.h - world/inv/ItemStack.cpp - world/inv/ItemStack.h - world/inv/LocalInventory.cpp - world/inv/LocalInventory.h - world/inv/LocalInventoryRefs.cpp - world/inv/LocalInventoryRefs.h - world/inv/ServerInventory.cpp - world/inv/ServerInventory.h - world/inv/ServerInventoryList.cpp - world/inv/ServerInventoryList.h - world/inv/ServerInventoryRefs.cpp - world/inv/ServerInventoryRefs.h - world/LocalWorld.cpp - world/LocalWorld.h - world/player/LocalPlayer.cpp - world/player/LocalPlayer.h - world/player/Player.cpp - world/player/Player.h - world/player/ServerPlayer.cpp - world/player/ServerPlayer.h - world/ServerWorld.cpp - world/ServerWorld.h - world/World.cpp - world/World.h + lua/register/RegisterKeybind.h + lua/ServerLuaParser.cpp + lua/ServerLuaParser.h + lua/ServerModHandler.cpp + lua/ServerModHandler.h + lua/usertype/AnimationManager.cpp + lua/usertype/AnimationManager.h + lua/usertype/BaseUsertype.h + lua/usertype/Dimension.cpp + lua/usertype/Dimension.h + lua/usertype/Entity.cpp + lua/usertype/Entity.h + lua/usertype/Inventory.cpp + lua/usertype/Inventory.h + lua/usertype/InventoryList.cpp + lua/usertype/InventoryList.h + lua/usertype/ItemStack.cpp + lua/usertype/ItemStack.h + lua/usertype/LuaGuiElement.cpp + lua/usertype/LuaGuiElement.h + lua/usertype/Player.cpp + lua/usertype/Player.h + lua/usertype/SubgameUsertype.h + lua/usertype/Target.cpp + lua/usertype/Target.h + server/Server.cpp + server/Server.h + server/ServerClient.cpp + server/ServerClient.h + server/ServerClients.cpp + server/ServerClients.h + server/ServerConfig.cpp + server/ServerConfig.h + server/stream/ServerGenStream.cpp + server/stream/ServerGenStream.h + server/stream/ServerPacketStream.cpp + server/stream/ServerPacketStream.h + StartGame.h + util/Any.h + util/CovariantPtr.h + util/frustum/Frustum.cpp + util/frustum/Frustum.h + util/frustum/FrustumAABB.cpp + util/frustum/FrustumAABB.h + util/frustum/FrustumPlane.cpp + util/frustum/FrustumPlane.h + util/Interp.h + util/Lockable.h + util/Log.h + util/Mat4Conv.h + util/net/Address.h + util/net/Deserializer.h + util/net/NetHandler.cpp + util/net/NetHandler.h + util/net/NetState.h + util/net/Packet.cpp + util/net/Packet.h + util/net/PacketView.cpp + util/net/PacketView.h + util/net/Serializer.h + util/Ray.cpp + util/Ray.h + util/RIE.h + util/Schematic.cpp + util/Schematic.h + util/Space.h + util/Target.cpp + util/Target.h + util/Timer.cpp + util/Timer.h + util/Util.h + util/Vec.h + util/Voronoi3D.cpp + util/Voronoi3D.h + world/dim/chunk/Chunk.cpp + world/dim/chunk/Chunk.h + world/dim/chunk/MapBlock.cpp + world/dim/chunk/MapBlock.h + world/dim/chunk/Region.cpp + world/dim/chunk/Region.h + world/dim/Dimension.cpp + world/dim/Dimension.h + world/dim/DimensionBase.cpp + world/dim/DimensionBase.h + world/dim/ent/AnimationSegment.h + world/dim/ent/AnimationState.cpp + world/dim/ent/AnimationState.h + world/dim/ent/AnimChannel.cpp + world/dim/ent/AnimChannel.h + world/dim/ent/Collision.cpp + world/dim/ent/Collision.h + world/dim/ent/DrawableEntity.cpp + world/dim/ent/DrawableEntity.h + world/dim/ent/Entity.cpp + world/dim/ent/Entity.h + world/dim/ent/LocalLuaEntity.cpp + world/dim/ent/LocalLuaEntity.h + world/dim/ent/LuaEntity.cpp + world/dim/ent/LuaEntity.h + world/dim/ent/ServerLuaEntity.cpp + world/dim/ent/ServerLuaEntity.h + world/dim/file/FileManipulator.cpp + world/dim/file/FileManipulator.h + world/dim/LocalDimension.cpp + world/dim/LocalDimension.h + world/dim/ServerDimension.cpp + world/dim/ServerDimension.h + world/gen/MapGen.cpp + world/gen/MapGen.h + world/gen/MapGenProps.cpp + world/gen/MapGenProps.h + world/gen/NoiseSample.cpp + world/gen/NoiseSample.h + world/inv/Inventory.cpp + world/inv/Inventory.h + world/inv/InventoryList.cpp + world/inv/InventoryList.h + world/inv/InventoryRefs.cpp + world/inv/InventoryRefs.h + world/inv/ItemStack.cpp + world/inv/ItemStack.h + world/inv/LocalInventory.cpp + world/inv/LocalInventory.h + world/inv/LocalInventoryRefs.cpp + world/inv/LocalInventoryRefs.h + world/inv/ServerInventory.cpp + world/inv/ServerInventory.h + world/inv/ServerInventoryList.cpp + world/inv/ServerInventoryList.h + world/inv/ServerInventoryRefs.cpp + world/inv/ServerInventoryRefs.h + world/LocalWorld.cpp + world/LocalWorld.h + world/player/LocalPlayer.cpp + world/player/LocalPlayer.h + world/player/Player.cpp + world/player/Player.h + world/player/ServerPlayer.cpp + world/player/ServerPlayer.h + world/ServerWorld.cpp + world/ServerWorld.h + world/World.cpp + world/World.h util/net/Address.cpp util/Bounds.cpp util/Bounds.h lua/register/CreateRegister.h lua/register/CreateRegister.cpp) target_include_directories(Zepha_Core PUBLIC .) \ No newline at end of file diff --git a/src/Main.cpp b/src/Main.cpp index 51bc0c5f..f00e3384 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -21,12 +21,13 @@ /** * Main entrance point to the program. (Am I really describing what the main function is?) - * Intentionally kept minimal to allow for testing. Real startup logic is done in StartGame. * + * Intentionally kept minimal to allow for testing. Real startup logic is done in StartGame. + * * @param argc - Argument array length * @param argv - Argument array * @returns - A numerical value indicating exit status. */ int main(int argc, char* argv[]) { - return StartGame(argc, argv); + return StartGame(argc, argv); } diff --git a/src/StartGame.h b/src/StartGame.h index d52444f2..dcaf4421 100644 --- a/src/StartGame.h +++ b/src/StartGame.h @@ -11,7 +11,9 @@ #include "client/Client.h" #include "server/Server.h" -enum class Mode { CLIENT, SERVER }; +enum class Mode { + CLIENT, SERVER +}; /** @@ -23,22 +25,21 @@ enum class Mode { CLIENT, SERVER }; */ std::map ParseArgs(int argc, char* argv[]) { - //Collect arguments into `args` map - std::map args; - for (int i = 1; i < argc; i++) { - - std::string arg(argv[i]); - size_t equals = arg.find('='); - std::string first = (equals == -1) ? arg : arg.substr(0, equals); - - if (args.count(first)) throw std::invalid_argument("Duplicate argument " + first + "."); - - if (equals == -1) args.emplace(first, ""); - else if (equals == arg.length() - 1) throw std::invalid_argument("Empty argument " + first + "."); - else args.emplace(first, arg.substr(equals + 1, arg.length())); - } - - return args; + std::map args; + for (int i = 1; i < argc; i++) { + + std::string arg(argv[i]); + size_t equals = arg.find('='); + std::string first = (equals == -1) ? arg : arg.substr(0, equals); + + if (args.count(first)) throw std::invalid_argument("Duplicate argument " + first + "."); + + if (equals == -1) args.emplace(first, ""); + else if (equals == arg.length() - 1) throw std::invalid_argument("Empty argument " + first + "."); + else args.emplace(first, arg.substr(equals + 1, arg.length())); + } + + return args; } @@ -50,74 +51,63 @@ std::map ParseArgs(int argc, char* argv[]) { */ int StartGame(int argc, char* argv[]) { - Mode mode = Mode::CLIENT; - - try { - unsigned short port = Address::DEFAULT_PORT; - std::string subgame = ""; - bool ascii = true; - - /** - * Handle command line arguments. - * @arg mode ("client" | "server") - Whether to initialize a client instance, or a server. Defaults to "client". - * @arg port (unsigned short) - The port that the server should listen on. Defaults to Address::DEFAULT_PORT. - * @arg subgame (std::string) - The subgame that the server should load. - * @arg noascii - Switch to disable ASCII from the console output. - */ - - for (auto arg : ParseArgs(argc, argv)) { - switch (Util::hash(arg.first.c_str())) { - default: - throw std::runtime_error("Invalid argument '" + arg.first + "'."); - - case Util::hash("--mode"): - if (arg.second == "client") mode = Mode::CLIENT; - else if (arg.second == "server") mode = Mode::SERVER; - else throw std::runtime_error("Invalid mode specified."); - break; + Mode mode = Mode::CLIENT; + + try { + unsigned short port = Address::DEFAULT_PORT; + std::string subgame = ""; + bool ascii = true; + + /** + * Handle command line arguments. + * @arg mode ("client" | "server") - Whether to initialize a client instance, or a server. Defaults to "client". + * @arg port (unsigned short) - The port that the server should listen on. Defaults to Address::DEFAULT_PORT. + * @arg subgame (std::string) - The subgame that the server should load. + * @arg noascii - Switch to disable ASCII from the console output. + */ + + for (auto arg : ParseArgs(argc, argv)) { + switch (Util::hash(arg.first.c_str())) { + default: throw std::runtime_error("Invalid argument '" + arg.first + "'."); + + case Util::hash("--mode"): + if (arg.second == "client") mode = Mode::CLIENT; + else if (arg.second == "server") mode = Mode::SERVER; + else throw std::runtime_error("Invalid mode specified."); + break; // case Util::hash("--address"): // addr.host = arg.second; // break; - - case Util::hash("--port"): - port = static_cast(stoi(arg.second)); - break; - - case Util::hash("--subgame"): - subgame = arg.second; - break; - - case Util::hash("--noascii"): - ascii = false; - break; - } - } - - if (ascii) { - Log::clear(); - std::cout << - "\n" - "\t\t ____ ____ ____ _ _ __ \n" - "\t\t(__ )( __)( _ \\/ )( \\ / _\\ \n" - "\t\t / _/ ) _) ) __/) __ (/ \\\n" - "\t\t(____)(____)(__) \\_)(_/\\_/\\_/\n" << std::endl; - } - - switch (mode) { - case Mode::CLIENT: { - Client c({1366, 768}); - break; } - - case Mode::SERVER: { - Server s(port, subgame); - break; } - } - - return 0; - } - catch (const std::exception& e) { - std::cout << Log::err << "Zepha failed to start.\n" << e.what() << Log::endl; - return 1; - } + + case Util::hash("--port"): port = static_cast(stoi(arg.second)); + break; + + case Util::hash("--subgame"): subgame = arg.second; + break; + + case Util::hash("--noascii"): ascii = false; + break; + } + } + + if (ascii) { + Log::clear(); + std::cout << + "\n" + "\t\t ____ ____ ____ _ _ __ \n" + "\t\t(__ )( __)( _ \\/ )( \\ / _\\ \n" + "\t\t / _/ ) _) ) __/) __ (/ \\\n" + "\t\t(____)(____)(__) \\_)(_/\\_/\\_/\n" << std::endl; + } + + if (mode == Mode::CLIENT) Client({ 1366, 768 }); + else Server(port, subgame); + + return 0; + } + catch (const std::exception& e) { + std::cout << Log::err << "Zepha failed to start.\n" << e.what() << Log::endl; + return 1; + } } diff --git a/src/client/Client.cpp b/src/client/Client.cpp index a603fb92..7edc72d8 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -18,12 +18,12 @@ */ Client::Client(glm::ivec2 window) : - renderer(window) { - - std::cout << Log::info << "Starting Zepha Client." << Log::endl; - - scene.setScene(std::make_unique(*this)); - while (!renderer.window.shouldClose()) loop(); + renderer(window) { + + std::cout << Log::info << "Starting Zepha Client." << Log::endl; + + scene.setScene(std::make_unique(*this)); + while (!renderer.window.shouldClose()) loop(); } @@ -33,7 +33,7 @@ Client::Client(glm::ivec2 window) : */ double Client::getDelta() { - return delta; + return delta; } @@ -44,11 +44,11 @@ double Client::getDelta() { */ void Client::startLocalServer(const std::string& subgame) { - //TODO: Implement Local Server + //TODO: Implement Local Server // localServer = std::make_shared(executablePath, addr.port, state.subgame); // localServer->start(); - - scene.setScene(std::make_unique(*this, Address { "127.0.0.1", Address::DEFAULT_PORT })); + + scene.setScene(std::make_unique(*this, Address{ "127.0.0.1", Address::DEFAULT_PORT })); } @@ -58,12 +58,12 @@ void Client::startLocalServer(const std::string& subgame) { */ void Client::loop() { - double now = glfwGetTime(); - delta = now - timeElapsed; - timeElapsed = now; - - glfwPollEvents(); - - scene.update(); - renderer.update(delta); + double now = glfwGetTime(); + delta = now - timeElapsed; + timeElapsed = now; + + glfwPollEvents(); + + scene.update(); + renderer.update(delta); } \ No newline at end of file diff --git a/src/client/Client.h b/src/client/Client.h index 8d5d5d45..7f10d32e 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -16,26 +16,27 @@ class LocalServerInstance; class Client { -public: - Client(const Client& o) = delete; - explicit Client(glm::ivec2 window); - - double getDelta(); - - void startLocalServer(const std::string& subgame); - - Renderer renderer; - SceneManager scene; - ServerConnection connection {}; - - std::shared_ptr game = std::make_shared("../assets/textures"); - -private: - void loop(); - - std::shared_ptr localServer = nullptr; - - double delta = 0; - double timeElapsed = 0; + public: + Client(const Client& o) = delete; + + explicit Client(glm::ivec2 window); + + double getDelta(); + + void startLocalServer(const std::string& subgame); + + Renderer renderer; + SceneManager scene; + ServerConnection connection{}; + + std::shared_ptr game = std::make_shared("../assets/textures"); + + private: + void loop(); + + std::shared_ptr localServer = nullptr; + + double delta = 0; + double timeElapsed = 0; }; diff --git a/src/client/Input.cpp b/src/client/Input.cpp index 03f9e273..d82913aa 100644 --- a/src/client/Input.cpp +++ b/src/client/Input.cpp @@ -11,161 +11,161 @@ #include "Window.h" Input::Input() { - for (bool& key : keysDown) key = false; - for (bool& key : keysPressed) key = false; - for (bool& key : keysReleased) key = false; - for (bool& key : keysNew) key = false; + for (bool& key : keysDown) key = false; + for (bool& key : keysPressed) key = false; + for (bool& key : keysReleased) key = false; + for (bool& key : keysNew) key = false; } -void Input::init(GLFWwindow *window, glm::ivec2* winDimensions) { - this->window = window; - this->winDimensions = winDimensions; - glfwSetKeyCallback(window, keyCallback); - glfwSetScrollCallback(window, scrollCallback); +void Input::init(GLFWwindow* window, glm::ivec2* winDimensions) { + this->window = window; + this->winDimensions = winDimensions; + glfwSetKeyCallback(window, keyCallback); + glfwSetScrollCallback(window, scrollCallback); } void Input::setCallback(std::function callback) { - this->callback = callback; + this->callback = callback; } void Input::update() { - for (bool &key : keysPressed) key = false; - for (bool &key : keysReleased) key = false; - - for (int i = 0; i < 1024; i++) { - bool key = keysNew[i]; - - if (key) { - if (!keysDown[i]) { - keysPressed[i] = true; - if (callback) callback(true, i); - } - keysDown[i] = true; - } - else { - if (keysDown[i]) { - keysReleased[i] = true; - if (callback) callback(false, i); - } - keysDown[i] = false; - } - } - - for (auto& s : mouseState) { - s.pressed = false; - s.released = false; - } - - for (int i = 0; i < 12; i++) { - keysNew[i] = false; - } - - updateMouse(0); - updateMouse(1); - updateMouse(2); - - if (glfwGetWindowAttrib(window, GLFW_FOCUSED) == GL_FALSE) { - mouseIsLocked = false; - delta = {}; - } - else { - double mouseX, mouseY; - glfwGetCursorPos(window, &mouseX, &mouseY); - - if (!mouseIsLocked) { - if (!forceMouseUnlocked && mousePressed(GLFW_MOUSE_BUTTON_LEFT)) { - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2); - mouseIsLocked = true; - } - } - else { - delta = {mouseX - (winDimensions->x / 2), -(mouseY - (winDimensions->y / 2))}; - glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2); - } - } + for (bool& key : keysPressed) key = false; + for (bool& key : keysReleased) key = false; + + for (int i = 0; i < 1024; i++) { + bool key = keysNew[i]; + + if (key) { + if (!keysDown[i]) { + keysPressed[i] = true; + if (callback) callback(true, i); + } + keysDown[i] = true; + } + else { + if (keysDown[i]) { + keysReleased[i] = true; + if (callback) callback(false, i); + } + keysDown[i] = false; + } + } + + for (auto& s : mouseState) { + s.pressed = false; + s.released = false; + } + + for (int i = 0; i < 12; i++) { + keysNew[i] = false; + } + + updateMouse(0); + updateMouse(1); + updateMouse(2); + + if (glfwGetWindowAttrib(window, GLFW_FOCUSED) == GL_FALSE) { + mouseIsLocked = false; + delta = {}; + } + else { + double mouseX, mouseY; + glfwGetCursorPos(window, &mouseX, &mouseY); + + if (!mouseIsLocked) { + if (!forceMouseUnlocked && mousePressed(GLFW_MOUSE_BUTTON_LEFT)) { + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2); + mouseIsLocked = true; + } + } + else { + delta = { mouseX - (winDimensions->x / 2), -(mouseY - (winDimensions->y / 2)) }; + glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2); + } + } } bool Input::keyDown(int key) { - return keysDown[key]; + return keysDown[key]; } bool Input::keyPressed(int key) { - return keysPressed[key]; + return keysPressed[key]; } bool Input::keyReleased(int key) { - return keysReleased[key]; + return keysReleased[key]; } bool Input::mouseDown(int button) { - return mouseState[button].down; + return mouseState[button].down; } bool Input::mousePressed(int button) { - return mouseState[button].pressed; + return mouseState[button].pressed; } bool Input::mouseReleased(int button) { - return mouseState[button].released; + return mouseState[button].released; } void Input::updateMouse(int button) { - if (glfwGetMouseButton(window, button) == GLFW_PRESS) { - if (!mouseState[button].down) mouseState[button].pressed = true; - mouseState[button].down = true; - } - else { - if (mouseState[button].down) mouseState[button].released = true; - mouseState[button].down = false; - } + if (glfwGetMouseButton(window, button) == GLFW_PRESS) { + if (!mouseState[button].down) mouseState[button].pressed = true; + mouseState[button].down = true; + } + else { + if (mouseState[button].down) mouseState[button].released = true; + mouseState[button].down = false; + } } void Input::keyCallback(GLFWwindow* window, int key, int code, int action, int mode) { - auto w = static_cast(glfwGetWindowUserPointer(window)); - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); - if (key >= 32 && key < 1024) { - if (action == GLFW_PRESS) w->input.keysNew[key] = true; - else if (action == GLFW_RELEASE) w->input.keysNew[key] = false; - } + auto w = static_cast(glfwGetWindowUserPointer(window)); + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); + if (key >= 32 && key < 1024) { + if (action == GLFW_PRESS) w->input.keysNew[key] = true; + else if (action == GLFW_RELEASE) w->input.keysNew[key] = false; + } } -void Input::scrollCallback(GLFWwindow *window, double xO, double yO) { - auto w = static_cast(glfwGetWindowUserPointer(window)); - - if (xO > 0) { - //Right - w->input.keysNew[11] = true; - } - else if (xO < 0) { - // Left - w->input.keysNew[10] = true; - } - - if (yO > 0) { - // Up - w->input.keysNew[8] = true; - } - else if (yO < 0) { - // Down - w->input.keysNew[9] = true; - } +void Input::scrollCallback(GLFWwindow* window, double xO, double yO) { + auto w = static_cast(glfwGetWindowUserPointer(window)); + + if (xO > 0) { + //Right + w->input.keysNew[11] = true; + } + else if (xO < 0) { + // Left + w->input.keysNew[10] = true; + } + + if (yO > 0) { + // Up + w->input.keysNew[8] = true; + } + else if (yO < 0) { + // Down + w->input.keysNew[9] = true; + } } void Input::lockMouse(bool lock) { - forceMouseUnlocked = !lock; - mouseIsLocked = lock; - glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2); - glfwSetInputMode(window, GLFW_CURSOR, (mouseIsLocked ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL)); - delta = {}; + forceMouseUnlocked = !lock; + mouseIsLocked = lock; + glfwSetCursorPos(window, winDimensions->x / 2, winDimensions->y / 2); + glfwSetInputMode(window, GLFW_CURSOR, (mouseIsLocked ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL)); + delta = {}; } glm::ivec2 Input::mousePos() { - double xPos, yPos; - glfwGetCursorPos(window, &xPos, &yPos); - return glm::ivec2 { static_cast(xPos), static_cast(yPos) }; + double xPos, yPos; + glfwGetCursorPos(window, &xPos, &yPos); + return glm::ivec2{ static_cast(xPos), static_cast(yPos) }; } glm::vec2 Input::mouseDelta() { - return delta; + return delta; } diff --git a/src/client/Input.h b/src/client/Input.h index f3e2aae0..afd09b2b 100644 --- a/src/client/Input.h +++ b/src/client/Input.h @@ -9,43 +9,58 @@ #include class Input { -public: - Input(); - void init(GLFWwindow* window, glm::ivec2* winDimensions); - void setCallback(std::function callback); - - void update(); - - bool keyDown(int key); - bool keyPressed(int key); - bool keyReleased(int key); - - bool mouseDown(int button); - bool mousePressed(int button); - bool mouseReleased(int button); - - void lockMouse(bool lock); - glm::ivec2 mousePos(); - glm::vec2 mouseDelta(); -private: - void updateMouse(int key); - static void keyCallback(GLFWwindow* window, int key, int code, int action, int mode); - static void scrollCallback(GLFWwindow* window, double, double yO); - - GLFWwindow* window = nullptr; - glm::ivec2* winDimensions = nullptr; - - bool keysNew[1024] {false}; - bool keysDown[1024] {false}; - bool keysPressed[1024] {false}; - bool keysReleased[1024] {false}; - - struct mouse { bool down = false; bool pressed = false; bool released = false; }; - std::array mouseState {}; - glm::vec2 delta; - - bool mouseIsLocked = false; - bool forceMouseUnlocked = false; - - std::function callback = nullptr; + public: + Input(); + + void init(GLFWwindow* window, glm::ivec2* winDimensions); + + void setCallback(std::function callback); + + void update(); + + bool keyDown(int key); + + bool keyPressed(int key); + + bool keyReleased(int key); + + bool mouseDown(int button); + + bool mousePressed(int button); + + bool mouseReleased(int button); + + void lockMouse(bool lock); + + glm::ivec2 mousePos(); + + glm::vec2 mouseDelta(); + + private: + void updateMouse(int key); + + static void keyCallback(GLFWwindow* window, int key, int code, int action, int mode); + + static void scrollCallback(GLFWwindow* window, double, double yO); + + GLFWwindow* window = nullptr; + glm::ivec2* winDimensions = nullptr; + + bool keysNew[1024]{ false }; + bool keysDown[1024]{ false }; + bool keysPressed[1024]{ false }; + bool keysReleased[1024]{ false }; + + struct mouse { + bool down = false; + bool pressed = false; + bool released = false; + }; + std::array mouseState{}; + glm::vec2 delta; + + bool mouseIsLocked = false; + bool forceMouseUnlocked = false; + + std::function callback = nullptr; }; \ No newline at end of file diff --git a/src/client/LocalServerInstance.cpp b/src/client/LocalServerInstance.cpp index de9a36fb..c498e3e4 100644 --- a/src/client/LocalServerInstance.cpp +++ b/src/client/LocalServerInstance.cpp @@ -7,45 +7,45 @@ #include "server/Server.h" #include -LocalServerInstance::LocalServerInstance(const std::string &path, unsigned short port, const std::string& subgame) : - port(port), - path(path), - subgame(subgame) {} +LocalServerInstance::LocalServerInstance(const std::string& path, unsigned short port, const std::string& subgame) : + port(port), + path(path), + subgame(subgame) {} bool LocalServerInstance::start() { #ifndef _WIN32 - pid = fork(); - if (pid == 0) { - const auto sub = ("--subgame=" + subgame); - char *arr[] = { - const_cast (""), + pid = fork(); + if (pid == 0) { + const auto sub = ("--subgame=" + subgame); + char* arr[] = { + const_cast (""), // const_cast ("-iconic"), - const_cast ("-e"), - const_cast (path.data()), - const_cast ("--mode=server"), - const_cast (sub.data()), - static_cast(nullptr) - }; - - execvp("xterm", arr); - } - return true; + const_cast ("-e"), + const_cast (path.data()), + const_cast ("--mode=server"), + const_cast (sub.data()), + static_cast(nullptr) + }; + + execvp("xterm", arr); + } + return true; #else - std::thread([&]() { - Server s(port, subgame); - }).detach(); - return true; + std::thread([&]() { + Server s(port, subgame); + }).detach(); + return true; #endif } void LocalServerInstance::stop() { - #ifndef _WIN32 - if (pid != 0) kill(pid, SIGKILL); - #else - std::cout << Log::err << "Local Server destructor not implemented on Windows!" << Log::endl; - #endif +#ifndef _WIN32 + if (pid != 0) kill(pid, SIGKILL); +#else + std::cout << Log::err << "Local Server destructor not implemented on Windows!" << Log::endl; +#endif } LocalServerInstance::~LocalServerInstance() { - stop(); + stop(); } \ No newline at end of file diff --git a/src/client/LocalServerInstance.h b/src/client/LocalServerInstance.h index 06c4c05b..582821fb 100644 --- a/src/client/LocalServerInstance.h +++ b/src/client/LocalServerInstance.h @@ -7,23 +7,27 @@ #include #ifndef _WIN32 + #include #include #include + #endif class LocalServerInstance { -public: - LocalServerInstance(const std::string& path, unsigned short port, const std::string& subgame); - - bool start(); - void stop(); - - ~LocalServerInstance(); -private: - std::string path; - std::string subgame; - unsigned short port = 0; - - int pid = 0; + public: + LocalServerInstance(const std::string& path, unsigned short port, const std::string& subgame); + + bool start(); + + void stop(); + + ~LocalServerInstance(); + + private: + std::string path; + std::string subgame; + unsigned short port = 0; + + int pid = 0; }; diff --git a/src/client/Window.cpp b/src/client/Window.cpp index 2b0309ad..352fd7ba 100644 --- a/src/client/Window.cpp +++ b/src/client/Window.cpp @@ -6,85 +6,85 @@ #include "util/Log.h" -Window::Window() : Window({800, 600}) {}; +Window::Window() : Window({ 800, 600 }) {}; Window::Window(glm::ivec2 win) : - win(win), center(win.x / 2, win.y / 2) { - - if (!glfwInit()) { - glfwTerminate(); - throw std::runtime_error("Failed to initialize GLFW context."); - } - - // Version 3.3 - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - - // Compatibility - No Backwards compat, only forwards - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - - // Create the window - if (!(mainWindow = glfwCreateWindow(win.x, win.y, "Zepha", nullptr, nullptr))) { - glfwTerminate(); - throw std::runtime_error("Failed to initialize GLFW window."); - } - - glfwGetFramebufferSize(mainWindow, &win.x, &win.y); - glfwMakeContextCurrent(mainWindow); - glewExperimental = GL_TRUE; - - handCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); - - // Initialize GLEW - GLenum error; - if ((error = glewInit()) != GLEW_OK) { - glfwTerminate(); - glfwDestroyWindow(mainWindow); - printf("%s", reinterpret_cast(glewGetErrorString(error))); - throw std::runtime_error("GLEW Fatal error."); - } - - glEnable(GL_DEPTH_TEST); - glViewport(0, 0, win.x, win.y); - - // Setup callbacks - glfwSetWindowUserPointer(mainWindow, this); - glfwSetScrollCallback(mainWindow, scrollCallback); - glfwSetWindowSizeCallback(mainWindow, resizeCallback); - - glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - glfwMaximizeWindow(mainWindow); - - input.init(mainWindow, &this->win); + win(win), center(win.x / 2, win.y / 2) { + + if (!glfwInit()) { + glfwTerminate(); + throw std::runtime_error("Failed to initialize GLFW context."); + } + + // Version 3.3 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + + // Compatibility - No Backwards compat, only forwards + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + + // Create the window + if (!(mainWindow = glfwCreateWindow(win.x, win.y, "Zepha", nullptr, nullptr))) { + glfwTerminate(); + throw std::runtime_error("Failed to initialize GLFW window."); + } + + glfwGetFramebufferSize(mainWindow, &win.x, &win.y); + glfwMakeContextCurrent(mainWindow); + glewExperimental = GL_TRUE; + + handCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); + + // Initialize GLEW + GLenum error; + if ((error = glewInit()) != GLEW_OK) { + glfwTerminate(); + glfwDestroyWindow(mainWindow); + printf("%s", reinterpret_cast(glewGetErrorString(error))); + throw std::runtime_error("GLEW Fatal error."); + } + + glEnable(GL_DEPTH_TEST); + glViewport(0, 0, win.x, win.y); + + // Setup callbacks + glfwSetWindowUserPointer(mainWindow, this); + glfwSetScrollCallback(mainWindow, scrollCallback); + glfwSetWindowSizeCallback(mainWindow, resizeCallback); + + glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwMaximizeWindow(mainWindow); + + input.init(mainWindow, &this->win); } void Window::update() { - input.update(); + input.update(); } bool Window::shouldClose() { - return static_cast(glfwWindowShouldClose(mainWindow)); + return static_cast(glfwWindowShouldClose(mainWindow)); } void Window::swapBuffers() { - glfwSwapBuffers(mainWindow); + glfwSwapBuffers(mainWindow); } -void Window::addResizeCallback(const std::string &identifier, std::function cb) { - resizeCallbacks.emplace(identifier, cb); +void Window::addResizeCallback(const std::string& identifier, std::function cb) { + resizeCallbacks.emplace(identifier, cb); } -void Window::removeResizeCallback(const std::string &identifier) { - resizeCallbacks.erase(identifier); +void Window::removeResizeCallback(const std::string& identifier) { + resizeCallbacks.erase(identifier); } glm::ivec2 Window::getSize() { - return win; + return win; } void Window::setCursorHand(bool hand) { - glfwSetCursor(mainWindow, hand ? handCursor : nullptr); + glfwSetCursor(mainWindow, hand ? handCursor : nullptr); } void Window::scrollCallback(GLFWwindow* window, double xO, double yO) { @@ -93,16 +93,16 @@ void Window::scrollCallback(GLFWwindow* window, double xO, double yO) { } void Window::resizeCallback(GLFWwindow* window, int width, int height) { - auto w = static_cast(glfwGetWindowUserPointer(window)); - - glfwGetFramebufferSize(window, &w->win.x, &w->win.y); - glViewport(0, 0, w->win.x, w->win.y); - - w->center = glm::ivec2(w->win.x / 2, w->win.y / 2); - for (auto& cb : w->resizeCallbacks) cb.second(w->win); + auto w = static_cast(glfwGetWindowUserPointer(window)); + + glfwGetFramebufferSize(window, &w->win.x, &w->win.y); + glViewport(0, 0, w->win.x, w->win.y); + + w->center = glm::ivec2(w->win.x / 2, w->win.y / 2); + for (auto& cb : w->resizeCallbacks) cb.second(w->win); } Window::~Window() { - glfwDestroyWindow(mainWindow); - glfwTerminate(); + glfwDestroyWindow(mainWindow); + glfwTerminate(); } \ No newline at end of file diff --git a/src/client/Window.h b/src/client/Window.h index 3cc8e446..a25c6259 100644 --- a/src/client/Window.h +++ b/src/client/Window.h @@ -11,36 +11,42 @@ #include "Input.h" class Window { -public: - Window(); - Window(glm::ivec2 win); - - void update(); - bool shouldClose(); - void swapBuffers(); - - void addResizeCallback(const std::string& identifier, std::function cb); - void removeResizeCallback(const std::string& identifier); - - glm::ivec2 getSize(); - void setCursorHand(bool hand); - - ~Window(); - - Input input; - GLFWwindow* mainWindow = nullptr; -private: - static void scrollCallback(GLFWwindow* window, double xO, double yO); - static void resizeCallback(GLFWwindow* window, int width, int height); - - GLFWcursor* handCursor = nullptr; - - glm::ivec2 win; - glm::ivec2 center; - - bool keys[1024] {}; - - std::map> resizeCallbacks; - + public: + Window(); + + Window(glm::ivec2 win); + + void update(); + + bool shouldClose(); + + void swapBuffers(); + + void addResizeCallback(const std::string& identifier, std::function cb); + + void removeResizeCallback(const std::string& identifier); + + glm::ivec2 getSize(); + + void setCursorHand(bool hand); + + ~Window(); + + Input input; + GLFWwindow* mainWindow = nullptr; + private: + static void scrollCallback(GLFWwindow* window, double xO, double yO); + + static void resizeCallback(GLFWwindow* window, int width, int height); + + GLFWcursor* handCursor = nullptr; + + glm::ivec2 win; + glm::ivec2 center; + + bool keys[1024]{}; + + std::map> resizeCallbacks; + }; diff --git a/src/client/conn/ClientNetworkInterpreter.cpp b/src/client/conn/ClientNetworkInterpreter.cpp index 98485bf6..85194efa 100644 --- a/src/client/conn/ClientNetworkInterpreter.cpp +++ b/src/client/conn/ClientNetworkInterpreter.cpp @@ -14,126 +14,131 @@ #include "util/net/NetHandler.h" #include "world/player/LocalPlayer.h" -ClientNetworkInterpreter::ClientNetworkInterpreter(ServerConnection &connection, LocalWorld& world) : - world(world), connection(connection) {} +ClientNetworkInterpreter::ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world) : + world(world), connection(connection) {} void ClientNetworkInterpreter::init(std::function)> invCallback) { - this->onInvPacket = invCallback; + this->onInvPacket = invCallback; } void ClientNetworkInterpreter::update() { - recvPackets = 0; - - ENetEvent event; - while (connection.pollEvents(&event)) { - recvPackets++; - - switch (event.type) { - default: break; - case ENET_EVENT_TYPE_CONNECT: { - std::cout << Log::info << "Connected to server " - << NetHandler::intToIPString(event.peer->address.host) - << ":" << event.peer->address.port << "." << Log::endl; - break; - } - case ENET_EVENT_TYPE_RECEIVE: { - std::unique_ptr p = std::make_unique(event.packet); - receivedPacket(std::move(p)); - break; - } - case ENET_EVENT_TYPE_DISCONNECT: { - std::cout << Log::info << "Disconnected from server " - << event.peer->address.host << ":" << event.peer->address.port << "." << Log::endl; - break; - } - } - } - - auto player = world.getPlayer(); - if (player) Serializer() - .appendE(NetField::POS).append(player->getPos()) - .appendE(NetField::VEL).append(player->getVel()) - .appendE(NetField::LOOK_PITCH).append(player->getPitch()) - .appendE(NetField::LOOK_YAW).append(player->getYaw()) - .packet(Packet::Type::THIS_PLAYER_INFO, false).sendTo(connection.getPeer(), Packet::Channel::INTERACT); + recvPackets = 0; + + ENetEvent event; + while (connection.pollEvents(&event)) { + recvPackets++; + + switch (event.type) { + default: break; + case ENET_EVENT_TYPE_CONNECT: { + std::cout << Log::info << "Connected to server " + << NetHandler::intToIPString(event.peer->address.host) + << ":" << event.peer->address.port << "." << Log::endl; + break; + } + case ENET_EVENT_TYPE_RECEIVE: { + std::unique_ptr p = std::make_unique(event.packet); + receivedPacket(std::move(p)); + break; + } + case ENET_EVENT_TYPE_DISCONNECT: { + std::cout << Log::info << "Disconnected from server " + << event.peer->address.host << ":" << event.peer->address.port << "." << Log::endl; + break; + } + } + } + + auto player = world.getPlayer(); + if (player) + Serializer() + .appendE(NetField::POS).append(player->getPos()) + .appendE(NetField::VEL).append(player->getVel()) + .appendE(NetField::LOOK_PITCH).append(player->getPitch()) + .appendE(NetField::LOOK_YAW).append(player->getYaw()) + .packet(Packet::Type::THIS_PLAYER_INFO, false).sendTo(connection.getPeer(), Packet::Channel::INTERACT); } void ClientNetworkInterpreter::receivedPacket(std::unique_ptr p) { - switch (p->type) { - default: - std::cout << Log::err << "Received unknown packet of type " << static_cast(p->type) - << ". Is the server on a different protocol version?" << Log::endl; break; - - case Packet::Type::SERVER_INFO: - serverSideChunkGens = p->d.read(); break; - - case Packet::Type::THIS_PLAYER_INFO: - world.getPlayer()->handleAssertion(p->d); break; - - case Packet::Type::PLAYER_ENT_INFO: - world.handlePlayerEntPacket(std::move(p)); break; - - case Packet::Type::CHUNK: - case Packet::Type::MAPBLOCK: - world.handleWorldPacket(std::move(p)); break; - - case Packet::Type::BLOCK_SET: { - auto pos = p->d.read(); - auto block = p->d.read(); - world.getActiveDimension()->setBlock(pos, block); - break; } - - case Packet::Type::ENTITY_INFO: - world.getActiveDimension().l()->serverEntitiesInfo(p->d); break; - - case Packet::Type::ENTITY_REMOVED: - world.getActiveDimension().l()->serverEntitiesRemoved(p->d); break; - - case Packet::Type::INV_DATA: - onInvPacket(std::move(p)); break; - - case Packet::Type::INV_INVALID: { - std::string source = p->d.read(); - std::string list = p->d.read(); - throw std::runtime_error("Invalid inventory " + source + ":" + list + " was request by client."); } - } + switch (p->type) { + default: + std::cout << Log::err << "Received unknown packet of type " << static_cast(p->type) + << ". Is the server on a different protocol version?" << Log::endl; + break; + + case Packet::Type::SERVER_INFO:serverSideChunkGens = p->d.read(); + break; + + case Packet::Type::THIS_PLAYER_INFO:world.getPlayer()->handleAssertion(p->d); + break; + + case Packet::Type::PLAYER_ENT_INFO:world.handlePlayerEntPacket(std::move(p)); + break; + + case Packet::Type::CHUNK: + case Packet::Type::MAPBLOCK:world.handleWorldPacket(std::move(p)); + break; + + case Packet::Type::BLOCK_SET: { + auto pos = p->d.read(); + auto block = p->d.read(); + world.getActiveDimension()->setBlock(pos, block); + break; + } + + case Packet::Type::ENTITY_INFO:world.getActiveDimension().l()->serverEntitiesInfo(p->d); + break; + + case Packet::Type::ENTITY_REMOVED:world.getActiveDimension().l()->serverEntitiesRemoved(p->d); + break; + + case Packet::Type::INV_DATA:onInvPacket(std::move(p)); + break; + + case Packet::Type::INV_INVALID: { + std::string source = p->d.read(); + std::string list = p->d.read(); + throw std::runtime_error("Invalid inventory " + source + ":" + list + " was request by client."); + } + } } -void ClientNetworkInterpreter::blockHit(const Target &target) { - Serializer().append(target.pos).append(static_cast(target.face)) - .packet(Packet::Type::BLOCK_HIT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); +void ClientNetworkInterpreter::blockHit(const Target& target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(Packet::Type::BLOCK_HIT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); } -void ClientNetworkInterpreter::blockPlace(const Target &target) { - Serializer().append(target.pos).append(static_cast(target.face)) - .packet(Packet::Type::BLOCK_PLACE).sendTo(connection.getPeer(), Packet::Channel::INTERACT); +void ClientNetworkInterpreter::blockPlace(const Target& target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(Packet::Type::BLOCK_PLACE).sendTo(connection.getPeer(), Packet::Channel::INTERACT); } -void ClientNetworkInterpreter::blockInteract(const Target &target) { - Serializer().append(target.pos).append(static_cast(target.face)) - .packet(Packet::Type::BLOCK_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); +void ClientNetworkInterpreter::blockInteract(const Target& target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(Packet::Type::BLOCK_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); } -void ClientNetworkInterpreter::blockPlaceOrInteract(const Target &target) { - Serializer().append(target.pos).append(static_cast(target.face)) - .packet(Packet::Type::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); +void ClientNetworkInterpreter::blockPlaceOrInteract(const Target& target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(Packet::Type::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); } void ClientNetworkInterpreter::invWatch(const std::string& inv, const std::string& list) { - Serializer().append(inv).append(list).packet(Packet::Type::INV_WATCH) - .sendTo(connection.getPeer(), Packet::Channel::INTERACT); + Serializer().append(inv).append(list).packet(Packet::Type::INV_WATCH) + .sendTo(connection.getPeer(), Packet::Channel::INTERACT); } void ClientNetworkInterpreter::invUnwatch(const std::string& inv, const std::string& list) { - Serializer().append(inv).append(list).packet(Packet::Type::INV_UNWATCH) - .sendTo(connection.getPeer(), Packet::Channel::INTERACT); + Serializer().append(inv).append(list).packet(Packet::Type::INV_UNWATCH) + .sendTo(connection.getPeer(), Packet::Channel::INTERACT); } -void ClientNetworkInterpreter::invInteract(const std::string &inv, const std::string &list, bool primary, unsigned short ind) { - Serializer().append(primary).append(inv).append(list).append(ind) - .packet(Packet::Type::INV_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); +void ClientNetworkInterpreter::invInteract(const std::string& inv, const std::string& list, bool primary, + unsigned short ind) { + Serializer().append(primary).append(inv).append(list).append(ind) + .packet(Packet::Type::INV_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT); } -void ClientNetworkInterpreter::sendPacket(const Packet &packet, Packet::Channel channel) { - packet.sendTo(connection.getPeer(), channel); +void ClientNetworkInterpreter::sendPacket(const Packet& packet, Packet::Channel channel) { + packet.sendTo(connection.getPeer(), channel); } diff --git a/src/client/conn/ClientNetworkInterpreter.h b/src/client/conn/ClientNetworkInterpreter.h index 33947749..c347dbd3 100644 --- a/src/client/conn/ClientNetworkInterpreter.h +++ b/src/client/conn/ClientNetworkInterpreter.h @@ -13,40 +13,53 @@ #include "client/conn/ServerConnection.h" class Model; + class Target; + class LocalWorld; + class PacketView; + class LocalPlayer; + class LocalSubgame; + enum class NetPlayerField; class ClientNetworkInterpreter { -public: - ClientNetworkInterpreter(const ClientNetworkInterpreter& other) = delete; - ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world); - - void init(std::function)> invCallback); - void update(); - - void blockHit(const Target& target); - void blockPlace(const Target& target); - void blockInteract(const Target& target); - void blockPlaceOrInteract(const Target& target); - - void invWatch(const std::string& inv, const std::string& list); - void invUnwatch(const std::string& inv, const std::string& list); - void invInteract(const std::string& inv, const std::string& list, bool primary, unsigned short ind); - - void sendPacket(const Packet& packet, Packet::Channel channel); - - int recvPackets = 0; - int serverSideChunkGens = 0; -private: - void receivedPacket(std::unique_ptr ePacket); - - LocalWorld& world; - ServerConnection& connection; - - std::function)> onInvPacket; + public: + ClientNetworkInterpreter(const ClientNetworkInterpreter& other) = delete; + + ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world); + + void init(std::function)> invCallback); + + void update(); + + void blockHit(const Target& target); + + void blockPlace(const Target& target); + + void blockInteract(const Target& target); + + void blockPlaceOrInteract(const Target& target); + + void invWatch(const std::string& inv, const std::string& list); + + void invUnwatch(const std::string& inv, const std::string& list); + + void invInteract(const std::string& inv, const std::string& list, bool primary, unsigned short ind); + + void sendPacket(const Packet& packet, Packet::Channel channel); + + int recvPackets = 0; + int serverSideChunkGens = 0; + private: + void receivedPacket(std::unique_ptr ePacket); + + LocalWorld& world; + ServerConnection& connection; + + std::function)> onInvPacket; }; diff --git a/src/client/conn/ServerConnection.cpp b/src/client/conn/ServerConnection.cpp index 2679d995..af9be53a 100644 --- a/src/client/conn/ServerConnection.cpp +++ b/src/client/conn/ServerConnection.cpp @@ -12,94 +12,94 @@ #include "util/net/NetHandler.h" void ServerConnection::attemptConnect(Address addr) { - if (state != State::UNCONNECTED) { - disconnect(); - } - - if (enet_initialize() != 0) { - std::cout << Log::err << "Failed to Initialize ENet." << Log::endl; - state = State::ENET_ERROR; - return; - } - - host = enet_host_create(nullptr, 1, NetHandler::PACKET_CHANNELS, 0, 0); - - if (host == nullptr) { - std::cout << Log::err << "Failed to create ENet client." << Log::endl; - state = State::ENET_ERROR; - return; - } - - ENetAddress eNetAddr; - enet_address_set_host(&eNetAddr, addr.host.c_str()); - eNetAddr.port = addr.port; - - peer = enet_host_connect(host, &eNetAddr, NetHandler::PACKET_CHANNELS, 0); - - if (peer == nullptr) { - std::cout << Log::err << "Failed to initialize ENet peer." << Log::endl; - state = State::ENET_ERROR; - return; - } - - connectionTime = std::chrono::high_resolution_clock::now(); - state = State::ATTEMPTING_CONNECT; + if (state != State::UNCONNECTED) { + disconnect(); + } + + if (enet_initialize() != 0) { + std::cout << Log::err << "Failed to Initialize ENet." << Log::endl; + state = State::ENET_ERROR; + return; + } + + host = enet_host_create(nullptr, 1, NetHandler::PACKET_CHANNELS, 0, 0); + + if (host == nullptr) { + std::cout << Log::err << "Failed to create ENet client." << Log::endl; + state = State::ENET_ERROR; + return; + } + + ENetAddress eNetAddr; + enet_address_set_host(&eNetAddr, addr.host.c_str()); + eNetAddr.port = addr.port; + + peer = enet_host_connect(host, &eNetAddr, NetHandler::PACKET_CHANNELS, 0); + + if (peer == nullptr) { + std::cout << Log::err << "Failed to initialize ENet peer." << Log::endl; + state = State::ENET_ERROR; + return; + } + + connectionTime = std::chrono::high_resolution_clock::now(); + state = State::ATTEMPTING_CONNECT; } void ServerConnection::processConnecting() { - if (state == State::ATTEMPTING_CONNECT) { - ENetEvent event; - - auto time = std::chrono::high_resolution_clock::now(); - long elapsedMs = std::chrono::duration_cast(time - connectionTime).count(); - - if (elapsedMs < timeout) { - if (enet_host_service(host, &event, 0) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { - std::cout << Log::info << "Connected to " - << NetHandler::intToIPString(event.peer->address.host) - << ":" << event.peer->address.port << "." << Log::endl; - - state = State::CONNECTED; - } - } - else { - enet_peer_reset(peer); - if (attempt < attempts) { - std::cout << Log::info << "Failed to connect to server, retrying." << Log::endl; - connectionTime = std::chrono::high_resolution_clock::now(); - attempt ++; - } - else { - std::cout << Log::err << "Failed to connect to server." << Log::endl; - state = State::FAILED_CONNECT; - } - } - } + if (state == State::ATTEMPTING_CONNECT) { + ENetEvent event; + + auto time = std::chrono::high_resolution_clock::now(); + long elapsedMs = std::chrono::duration_cast(time - connectionTime).count(); + + if (elapsedMs < timeout) { + if (enet_host_service(host, &event, 0) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { + std::cout << Log::info << "Connected to " + << NetHandler::intToIPString(event.peer->address.host) + << ":" << event.peer->address.port << "." << Log::endl; + + state = State::CONNECTED; + } + } + else { + enet_peer_reset(peer); + if (attempt < attempts) { + std::cout << Log::info << "Failed to connect to server, retrying." << Log::endl; + connectionTime = std::chrono::high_resolution_clock::now(); + attempt++; + } + else { + std::cout << Log::err << "Failed to connect to server." << Log::endl; + state = State::FAILED_CONNECT; + } + } + } } ServerConnection::State ServerConnection::getConnectionStatus() { - return state; + return state; } void ServerConnection::disconnect() { - if (state == State::CONNECTED) { - std::cout << Log::info << "Disconnecting from server." << Log::endl; - enet_peer_disconnect(peer, 0); - enet_host_flush(host); - state = State::DISCONNECTED; - } + if (state == State::CONNECTED) { + std::cout << Log::info << "Disconnecting from server." << Log::endl; + enet_peer_disconnect(peer, 0); + enet_host_flush(host); + state = State::DISCONNECTED; + } } -bool ServerConnection::pollEvents(ENetEvent *event) { - return enet_host_service(host, event, 0) > 0; +bool ServerConnection::pollEvents(ENetEvent* event) { + return enet_host_service(host, event, 0) > 0; } -ENetPeer *ServerConnection::getPeer() { - return peer; +ENetPeer* ServerConnection::getPeer() { + return peer; } ServerConnection::~ServerConnection() { - disconnect(); - delete host; - delete peer; + disconnect(); + delete host; + delete peer; } diff --git a/src/client/conn/ServerConnection.h b/src/client/conn/ServerConnection.h index 0d2c940b..3cd99108 100644 --- a/src/client/conn/ServerConnection.h +++ b/src/client/conn/ServerConnection.h @@ -10,38 +10,41 @@ class Address; class ServerConnection { -public: - enum class State { - UNCONNECTED, - ATTEMPTING_CONNECT, - CONNECTED, - FAILED_CONNECT, - DISCONNECTED, - ENET_ERROR - }; - - ServerConnection() = default; - - void attemptConnect(Address addr); - State getConnectionStatus(); - void disconnect(); - - void processConnecting(); - bool pollEvents(ENetEvent* event); - - ENetPeer* getPeer(); - - ~ServerConnection(); - -private: - unsigned long timeout = 1000; - unsigned int attempts = 10; - - ENetHost* host = nullptr; - ENetPeer* peer = nullptr; - - State state = State::UNCONNECTED; - unsigned int attempt = 0; - std::chrono::time_point connectionTime; + public: + enum class State { + UNCONNECTED, + ATTEMPTING_CONNECT, + CONNECTED, + FAILED_CONNECT, + DISCONNECTED, + ENET_ERROR + }; + + ServerConnection() = default; + + void attemptConnect(Address addr); + + State getConnectionStatus(); + + void disconnect(); + + void processConnecting(); + + bool pollEvents(ENetEvent* event); + + ENetPeer* getPeer(); + + ~ServerConnection(); + + private: + unsigned long timeout = 1000; + unsigned int attempts = 10; + + ENetHost* host = nullptr; + ENetPeer* peer = nullptr; + + State state = State::UNCONNECTED; + unsigned int attempt = 0; + std::chrono::time_point connectionTime; }; diff --git a/src/client/entity/ParticleEntity.cpp b/src/client/entity/ParticleEntity.cpp index 9e7cd5df..896dc6fa 100644 --- a/src/client/entity/ParticleEntity.cpp +++ b/src/client/entity/ParticleEntity.cpp @@ -9,65 +9,65 @@ #include "game/def/BlockDef.h" #include "game/atlas/asset/AtlasRef.h" -ParticleEntity::ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef &block) : - DrawableEntity(game, dim, std::make_shared()), Entity(game, dim) { - setPos(pos + glm::vec3(.5,.3,.5)); - - std::set>& textureRefs = block.model.textureRefs; - auto it = textureRefs.cbegin(); - advance(it, rand() % textureRefs.size()); - - auto uv = (*it)->uv; - - auto spanX = uv.z - uv.x; - auto spanY = uv.w - uv.y; - - float offX = spanX / 16 * (rand() % 12); - float offY = spanX / 16 * (rand() % 12); - - uv -= glm::vec4(0, 0, spanX * 0.75, spanY * 0.75); - uv += glm::vec4(offX, offY, offX, offY); - - std::vector vertices { - {{-0.05, -0.05, 0}, {uv.x, uv.w, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}}, - {{-0.05, 0.05, 0}, {uv.x, uv.y, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}}, - {{ 0.05, 0.05, 0}, {uv.z, uv.y, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}}, - {{ 0.05, -0.05, 0}, {uv.z, uv.w, 0, 1}, {1, 1, 1}, true, {0, 0, 1}, {}, {}}, - }; - std::vector indices { - 0, 1, 2, 2, 3, 0, - 0, 2, 1, 2, 0, 3, - }; - - auto dir = glm::radians(static_cast(rand() % 360)); - float xDir = sinf(dir); - float zDir = cosf(dir); - - float horiScale = 0.5f + (rand() % 100 / 100.f); - - velocity.y = 6.f; - velocity.x = xDir * 2.f * horiScale; - velocity.z = zDir * 2.f * horiScale; - - setPos(getPos() + glm::vec3(xDir, 0, zDir) / 4.f); - - std::unique_ptr mesh = std::make_unique(); - mesh->create(vertices, indices); - this->model->fromMesh(std::move(mesh)); - this->setScale(0.75f + (rand() % 10 / 20.f)); +ParticleEntity::ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef& block) : + DrawableEntity(game, dim, std::make_shared()), Entity(game, dim) { + setPos(pos + glm::vec3(.5, .3, .5)); + + std::set>& textureRefs = block.model.textureRefs; + auto it = textureRefs.cbegin(); + advance(it, rand() % textureRefs.size()); + + auto uv = (*it)->uv; + + auto spanX = uv.z - uv.x; + auto spanY = uv.w - uv.y; + + float offX = spanX / 16 * (rand() % 12); + float offY = spanX / 16 * (rand() % 12); + + uv -= glm::vec4(0, 0, spanX * 0.75, spanY * 0.75); + uv += glm::vec4(offX, offY, offX, offY); + + std::vector vertices{ + {{ -0.05, -0.05, 0 }, { uv.x, uv.w, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}}, + {{ -0.05, 0.05, 0 }, { uv.x, uv.y, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}}, + {{ 0.05, 0.05, 0 }, { uv.z, uv.y, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}}, + {{ 0.05, -0.05, 0 }, { uv.z, uv.w, 0, 1 }, { 1, 1, 1 }, true, { 0, 0, 1 }, {}, {}}, + }; + std::vector indices{ + 0, 1, 2, 2, 3, 0, + 0, 2, 1, 2, 0, 3, + }; + + auto dir = glm::radians(static_cast(rand() % 360)); + float xDir = sinf(dir); + float zDir = cosf(dir); + + float horiScale = 0.5f + (rand() % 100 / 100.f); + + velocity.y = 6.f; + velocity.x = xDir * 2.f * horiScale; + velocity.z = zDir * 2.f * horiScale; + + setPos(getPos() + glm::vec3(xDir, 0, zDir) / 4.f); + + std::unique_ptr mesh = std::make_unique(); + mesh->create(vertices, indices); + this->model->fromMesh(std::move(mesh)); + this->setScale(0.75f + (rand() % 10 / 20.f)); } void ParticleEntity::update(double delta, glm::vec3 player) { - time += delta; - - setPos(getPos() + velocity * glm::vec3(static_cast(delta))); - - double angle = -glm::degrees(std::atan2(player.z - pos.z, player.x - pos.x)) + 90.f; - setRotateY(static_cast(angle)); - - velocity.y -= 32.f * delta; + time += delta; + + setPos(getPos() + velocity * glm::vec3(static_cast(delta))); + + double angle = -glm::degrees(std::atan2(player.z - pos.z, player.x - pos.x)) + 90.f; + setRotateY(static_cast(angle)); + + velocity.y -= 32.f * delta; } -void ParticleEntity::draw(Renderer &renderer) { - DrawableEntity::draw(renderer); +void ParticleEntity::draw(Renderer& renderer) { + DrawableEntity::draw(renderer); } \ No newline at end of file diff --git a/src/client/entity/ParticleEntity.h b/src/client/entity/ParticleEntity.h index 97a4cc26..82b62ee4 100644 --- a/src/client/entity/ParticleEntity.h +++ b/src/client/entity/ParticleEntity.h @@ -9,14 +9,15 @@ class BlockDef; class ParticleEntity : public DrawableEntity { -public: - ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef& block); - - void update(double delta, glm::vec3 player); - void draw(Renderer& renderer) override; - - float time = 0; -private: - glm::vec3 velocity {}; + public: + ParticleEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, BlockDef& block); + + void update(double delta, glm::vec3 player); + + void draw(Renderer& renderer) override; + + float time = 0; + private: + glm::vec3 velocity{}; }; diff --git a/src/client/entity/PlayerEntity.h b/src/client/entity/PlayerEntity.h index b9312304..437931bd 100644 --- a/src/client/entity/PlayerEntity.h +++ b/src/client/entity/PlayerEntity.h @@ -7,16 +7,17 @@ #include "world/dim/ent/DrawableEntity.h" class PlayerEntity : public DrawableEntity { -public: - PlayerEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, unsigned int id, const std::shared_ptr& model) : - DrawableEntity(game, dim, model), Entity(game, dim), id(id) { - setPos(pos); - } - - unsigned int getId() { - return id; - } - -private: - unsigned int id; + public: + PlayerEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 pos, unsigned int id, const std::shared_ptr& model) + : + DrawableEntity(game, dim, model), Entity(game, dim), id(id) { + setPos(pos); + } + + unsigned int getId() { + return id; + } + + private: + unsigned int id; }; \ No newline at end of file diff --git a/src/client/entity/WireframeEntity.cpp b/src/client/entity/WireframeEntity.cpp index d39dbec2..c485cc11 100644 --- a/src/client/entity/WireframeEntity.cpp +++ b/src/client/entity/WireframeEntity.cpp @@ -7,71 +7,83 @@ #include "world/dim/ent/DrawableEntity.h" void WireframeEntity::updateMesh(const std::vector& boxes, float width) { - this->width = width; - buildMesh(boxes); + this->width = width; + buildMesh(boxes); } void WireframeEntity::buildMesh(const std::vector& boxes) { - indOffset = 0; - - vertices.clear(); - indices.clear(); - - for (auto& box : boxes) { - glm::vec3 a = box.a; - glm::vec3 b = box.b - box.a; - - createBox(a, b, 0, 0, 0, 0, b.y, 0); - createBox(a, b, b.x, 0, 0, 0, b.y, 0); - createBox(a, b, b.x, 0, b.z, 0, b.y, 0); - createBox(a, b, 0, 0, b.z, 0, b.y, 0); - - createBox(a, b, 0, 0, 0, b.x, 0, 0); - createBox(a, b, 0, b.y, 0, b.x, 0, 0); - createBox(a, b, 0, b.y, b.z, b.x, 0, 0); - createBox(a, b, 0, 0, b.z, b.x, 0, 0); - - createBox(a, b, 0, 0, 0, 0, 0, b.z); - createBox(a, b, 0, b.y, 0, 0, 0, b.z); - createBox(a, b, b.x, b.y, 0, 0, 0, b.z); - createBox(a, b, b.x, 0, 0, 0, 0, b.z); - } - - - std::unique_ptr mesh = std::make_unique(); - mesh->create(vertices, indices); - this->model->fromMesh(std::move(mesh)); + indOffset = 0; + + vertices.clear(); + indices.clear(); + + for (auto& box : boxes) { + glm::vec3 a = box.a; + glm::vec3 b = box.b - box.a; + + createBox(a, b, 0, 0, 0, 0, b.y, 0); + createBox(a, b, b.x, 0, 0, 0, b.y, 0); + createBox(a, b, b.x, 0, b.z, 0, b.y, 0); + createBox(a, b, 0, 0, b.z, 0, b.y, 0); + + createBox(a, b, 0, 0, 0, b.x, 0, 0); + createBox(a, b, 0, b.y, 0, b.x, 0, 0); + createBox(a, b, 0, b.y, b.z, b.x, 0, 0); + createBox(a, b, 0, 0, b.z, b.x, 0, 0); + + createBox(a, b, 0, 0, 0, 0, 0, b.z); + createBox(a, b, 0, b.y, 0, 0, 0, b.z); + createBox(a, b, b.x, b.y, 0, 0, 0, b.z); + createBox(a, b, b.x, 0, 0, 0, 0, b.z); + } + + + std::unique_ptr mesh = std::make_unique(); + mesh->create(vertices, indices); + this->model->fromMesh(std::move(mesh)); } -void WireframeEntity::createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize) { - float hw = (width/2.0f); - float w = width; - glm::vec3 c = color; - - std::vector myVerts { - /*0*/ {{x - hw + a.x, y - hw + a.y, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - /*1*/ {{x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - /*2*/ {{x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - /*3*/ {{x - hw + a.x, y - hw + a.y, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - - /*4*/ {{x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - /*5*/ {{x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z }, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - /*6*/ {{x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - /*7*/ {{x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w}, {c.x, c.y, c.z, 1}, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - }; - - std::vector myInds { - 0, 1, 2, 2, 3, 0, - 4, 7, 6, 6, 5, 4, - 0, 4, 5, 5, 1, 0, - 3, 2, 6, 6, 7, 3, - 0, 3, 7, 7, 4, 0, - 1, 5, 6, 6, 2, 1, - }; - - vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); - for (auto i : myInds) indices.push_back(i + indOffset); - - indOffset += 8; +void +WireframeEntity::createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize) { + float hw = (width / 2.0f); + float w = width; + glm::vec3 c = color; + + std::vector myVerts{ + /*0*/ + {{ x - hw + a.x, y - hw + a.y, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}}, + /*1*/{{ x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, + { 0, 1, 0 }, {}, {}}, + /*2*/ + {{ x - hw + a.x + xSize + w, y - hw + a.y, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, + { 0, 1, 0 }, {}, {}}, + /*3*/{{ x - hw + a.x, y - hw + a.y, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, + { 0, 1, 0 }, {}, {}}, + + /*4*/{{ x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, + { 0, 1, 0 }, {}, {}}, + /*5*/ + {{ x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, + { 0, 1, 0 }, {}, {}}, + /*6*/{{ x - hw + a.x + xSize + w, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, + { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}}, + /*7*/ + {{ x - hw + a.x, y - hw + a.y + ySize + w, z - hw + a.z + zSize + w }, { c.x, c.y, c.z, 1 }, { 1, 1, 1 }, false, + { 0, 1, 0 }, {}, {}}, + }; + + std::vector myInds{ + 0, 1, 2, 2, 3, 0, + 4, 7, 6, 6, 5, 4, + 0, 4, 5, 5, 1, 0, + 3, 2, 6, 6, 7, 3, + 0, 3, 7, 7, 4, 0, + 1, 5, 6, 6, 2, 1, + }; + + vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); + for (auto i : myInds) indices.push_back(i + indOffset); + + indOffset += 8; } \ No newline at end of file diff --git a/src/client/entity/WireframeEntity.h b/src/client/entity/WireframeEntity.h index fe0ca8db..86a4f1db 100644 --- a/src/client/entity/WireframeEntity.h +++ b/src/client/entity/WireframeEntity.h @@ -10,21 +10,23 @@ #include "client/graph/mesh/EntityVertex.h" class WireframeEntity : public DrawableEntity { -public: - WireframeEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 color) : - DrawableEntity(game, dim, std::make_shared()), Entity(game, dim), - color(color) {}; - - void updateMesh(const std::vector& boxes, float width); -private: - std::vector vertices {}; - std::vector indices {}; - - void buildMesh(const std::vector& boxes); - void createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize); - - glm::vec3 color {}; - - float width = 0.5; - int indOffset = 0; + public: + WireframeEntity(SubgamePtr game, DimensionPtr dim, glm::vec3 color) : + DrawableEntity(game, dim, std::make_shared()), Entity(game, dim), + color(color) {}; + + void updateMesh(const std::vector& boxes, float width); + + private: + std::vector vertices{}; + std::vector indices{}; + + void buildMesh(const std::vector& boxes); + + void createBox(glm::vec3 a, glm::vec3 b, float x, float y, float z, float xSize, float ySize, float zSize); + + glm::vec3 color{}; + + float width = 0.5; + int indOffset = 0; }; diff --git a/src/client/graph/Camera.cpp b/src/client/graph/Camera.cpp index 2a09959f..afc3c57b 100644 --- a/src/client/graph/Camera.cpp +++ b/src/client/graph/Camera.cpp @@ -9,91 +9,91 @@ Camera::Camera() = default; void Camera::create(float buffWidth, float buffHeight, glm::vec3 up) { - this->bufferDimensions = glm::vec2(buffWidth, buffHeight); - - this->position = glm::vec3(0, 0, 0); - - this->worldUp = up; - this->yaw = 0; - this->pitch = 0; - this->front = glm::vec3(0.0f, 0.0f, -1.0f); - - createMatrices(); + this->bufferDimensions = glm::vec2(buffWidth, buffHeight); + + this->position = glm::vec3(0, 0, 0); + + this->worldUp = up; + this->yaw = 0; + this->pitch = 0; + this->front = glm::vec3(0.0f, 0.0f, -1.0f); + + createMatrices(); } void Camera::createMatrices() { - ratio = bufferDimensions.x / bufferDimensions.y; - - projectionMatrix = glm::perspective(glm::radians(fov), ratio, nearClip, farClip); - frustum.setCamInternals(glm::radians(fov) / 1.2f, ratio, nearClip, farClip); - - orthographicMatrix = glm::ortho(0.0f, bufferDimensions.x, bufferDimensions.y, 0.0f, -1000.0f, 1000.0f); + ratio = bufferDimensions.x / bufferDimensions.y; + + projectionMatrix = glm::perspective(glm::radians(fov), ratio, nearClip, farClip); + frustum.setCamInternals(glm::radians(fov) / 1.2f, ratio, nearClip, farClip); + + orthographicMatrix = glm::ortho(0.0f, bufferDimensions.x, bufferDimensions.y, 0.0f, -1000.0f, 1000.0f); } void Camera::changeWindowDimensions(glm::vec2 size) { - this->bufferDimensions = size; - createMatrices(); + this->bufferDimensions = size; + createMatrices(); } glm::mat4 Camera::getProjectionMatrix() { - return projectionMatrix; + return projectionMatrix; } glm::mat4 Camera::getOrthographicMatrix() { - return orthographicMatrix; + return orthographicMatrix; } glm::mat4 Camera::getViewMatrix() { - update(); - return glm::lookAt(position, position + front, up); + update(); + return glm::lookAt(position, position + front, up); } void Camera::setPos(glm::vec3 pos) { - position = pos; + position = pos; } glm::vec3 Camera::getPos() { - return position; + return position; } void Camera::setYaw(double yaw) { - this->yaw = yaw; + this->yaw = yaw; } void Camera::setPitch(double pitch) { - this->pitch = pitch; + this->pitch = pitch; } void Camera::update() { - front.x = (float)(cos(glm::radians(yaw)) * cos(glm::radians(pitch))); - front.y = (float)(sin(glm::radians(pitch))); - front.z = (float)(sin(glm::radians(yaw)) * cos(glm::radians(pitch))); - front = glm::normalize(front); - - right = glm::normalize(glm::cross(front, worldUp)); - up = glm::normalize(glm::cross(right, front)); - - frustum.update(position, front, up, right); + front.x = (float) (cos(glm::radians(yaw)) * cos(glm::radians(pitch))); + front.y = (float) (sin(glm::radians(pitch))); + front.z = (float) (sin(glm::radians(yaw)) * cos(glm::radians(pitch))); + front = glm::normalize(front); + + right = glm::normalize(glm::cross(front, worldUp)); + up = glm::normalize(glm::cross(right, front)); + + frustum.update(position, front, up, right); } glm::vec3 Camera::getFront() { - return front; + return front; } glm::vec3 Camera::getRight() { - return right; + return right; } glm::vec2 Camera::getBufferDimensions() { - return bufferDimensions; + return bufferDimensions; } -bool Camera::inFrustum(glm::vec3 &p) { - return frustum.pointInFrustum(p) == Frustum::INSIDE; +bool Camera::inFrustum(glm::vec3& p) { + return frustum.pointInFrustum(p) == Frustum::INSIDE; } -int Camera::inFrustum(FrustumAABB &b) { - return frustum.boxInFrustum(b); +int Camera::inFrustum(FrustumAABB& b) { + return frustum.boxInFrustum(b); } Camera::~Camera() = default; diff --git a/src/client/graph/Camera.h b/src/client/graph/Camera.h index f801af17..4d548dab 100644 --- a/src/client/graph/Camera.h +++ b/src/client/graph/Camera.h @@ -11,61 +11,69 @@ #include "util/frustum/Frustum.h" class Camera { -public: - Camera(); - void create(float buffWidth, float buffHeight, glm::vec3 up); - - void changeWindowDimensions(glm::vec2 size); - - glm::vec3 getPos(); - void setPos(glm::vec3 pos); - - void setYaw(double yaw); - void setPitch(double pitch); - - glm::mat4 getProjectionMatrix(); - glm::mat4 getOrthographicMatrix(); - - glm::mat4 getViewMatrix(); - - glm::vec3 getFront(); - glm::vec3 getRight(); - - glm::vec2 getBufferDimensions(); - - bool inFrustum(glm::vec3 &p); - int inFrustum(FrustumAABB &b); - - ~Camera(); -private: - //Window Size - glm::vec2 bufferDimensions; - - //Matrices - glm::mat4 projectionMatrix; - glm::mat4 orthographicMatrix; - - //Perspective Matrix Properties - float fov = 80.0f; - float ratio; - float nearClip = 0.1f; - float farClip = 1000.0f; - - //View Frustum - Frustum frustum; - - //Movement translation variables - glm::vec3 front; - glm::vec3 up; - glm::vec3 right; - glm::vec3 worldUp; - - //Angle and Position - glm::vec3 position; - double yaw; - double pitch; - - void createMatrices(); - void update(); + public: + Camera(); + + void create(float buffWidth, float buffHeight, glm::vec3 up); + + void changeWindowDimensions(glm::vec2 size); + + glm::vec3 getPos(); + + void setPos(glm::vec3 pos); + + void setYaw(double yaw); + + void setPitch(double pitch); + + glm::mat4 getProjectionMatrix(); + + glm::mat4 getOrthographicMatrix(); + + glm::mat4 getViewMatrix(); + + glm::vec3 getFront(); + + glm::vec3 getRight(); + + glm::vec2 getBufferDimensions(); + + bool inFrustum(glm::vec3& p); + + int inFrustum(FrustumAABB& b); + + ~Camera(); + + private: + //Window Size + glm::vec2 bufferDimensions; + + //Matrices + glm::mat4 projectionMatrix; + glm::mat4 orthographicMatrix; + + //Perspective Matrix Properties + float fov = 80.0f; + float ratio; + float nearClip = 0.1f; + float farClip = 1000.0f; + + //View Frustum + Frustum frustum; + + //Movement translation variables + glm::vec3 front; + glm::vec3 up; + glm::vec3 right; + glm::vec3 worldUp; + + //Angle and Position + glm::vec3 position; + double yaw; + double pitch; + + void createMatrices(); + + void update(); }; diff --git a/src/client/graph/Drawable.h b/src/client/graph/Drawable.h index 0918f3c8..3eb1caa0 100644 --- a/src/client/graph/Drawable.h +++ b/src/client/graph/Drawable.h @@ -7,15 +7,18 @@ class Renderer; class Drawable { -public: - virtual void update(double delta) {}; - virtual void draw(Renderer& renderer) {}; - - virtual bool isVisible() { return visible; } - virtual void setVisible(bool visible) { this->visible = visible; } - - virtual ~Drawable() = default; -protected: - bool visible = true; + public: + virtual void update(double delta) {}; + + virtual void draw(Renderer& renderer) {}; + + virtual bool isVisible() { return visible; } + + virtual void setVisible(bool visible) { this->visible = visible; } + + virtual ~Drawable() = default; + + protected: + bool visible = true; }; diff --git a/src/client/graph/DrawableGroup.cpp b/src/client/graph/DrawableGroup.cpp index 83990ab3..a0deec8e 100644 --- a/src/client/graph/DrawableGroup.cpp +++ b/src/client/graph/DrawableGroup.cpp @@ -4,37 +4,37 @@ #include "DrawableGroup.h" -void DrawableGroup::draw(Renderer &renderer) { - for (auto drawable : children) { - drawable->draw(renderer); - } +void DrawableGroup::draw(Renderer& renderer) { + for (auto drawable : children) { + drawable->draw(renderer); + } } -void DrawableGroup::addDrawable(Drawable *drawable) { - children.push_back(drawable); +void DrawableGroup::addDrawable(Drawable* drawable) { + children.push_back(drawable); } -void DrawableGroup::removeDrawable(Drawable *drawable) { - for (auto it = children.begin(); it < children.end(); ++it) { - if (*it == drawable) { - children.erase(it); - delete *it; - return; - } - } +void DrawableGroup::removeDrawable(Drawable* drawable) { + for (auto it = children.begin(); it < children.end(); ++it) { + if (*it == drawable) { + children.erase(it); + delete *it; + return; + } + } } void DrawableGroup::clearDrawables() { - for (auto drawable : children) { - delete drawable; - } - children.clear(); + for (auto drawable : children) { + delete drawable; + } + children.clear(); } DrawableGroup::~DrawableGroup() { - clearDrawables(); + clearDrawables(); } -std::vector &DrawableGroup::getChildren() { - return children; +std::vector& DrawableGroup::getChildren() { + return children; } diff --git a/src/client/graph/DrawableGroup.h b/src/client/graph/DrawableGroup.h index 4a435c20..95fd9731 100644 --- a/src/client/graph/DrawableGroup.h +++ b/src/client/graph/DrawableGroup.h @@ -9,17 +9,20 @@ #include "Drawable.h" class DrawableGroup : public Drawable { -public: - void draw(Renderer& renderer) override; - - void addDrawable(Drawable* drawable); - void removeDrawable(Drawable* drawable); - void clearDrawables(); - - std::vector& getChildren(); - - ~DrawableGroup() override; -protected: - std::vector children {}; + public: + void draw(Renderer& renderer) override; + + void addDrawable(Drawable* drawable); + + void removeDrawable(Drawable* drawable); + + void clearDrawables(); + + std::vector& getChildren(); + + ~DrawableGroup() override; + + protected: + std::vector children{}; }; diff --git a/src/client/graph/Font.cpp b/src/client/graph/Font.cpp index 9e00b3ff..e13a95c8 100644 --- a/src/client/graph/Font.cpp +++ b/src/client/graph/Font.cpp @@ -10,62 +10,62 @@ #include "game/atlas/TextureAtlas.h" Font::Font(TextureAtlas& atlas, std::shared_ptr tex) : - fontTex(std::move(tex)), - atlasSize(atlas.pixelSize) { - - getCharWidths(atlas); + fontTex(std::move(tex)), + atlasSize(atlas.pixelSize) { + + getCharWidths(atlas); } unsigned int Font::getCharWidth(char c) { - unsigned int index = static_cast(c) - 32; - if (index >= amountOfChars) throw std::runtime_error("Invalid char index."); - return charWidths[index]; + unsigned int index = static_cast(c) - 32; + if (index >= amountOfChars) throw std::runtime_error("Invalid char index."); + return charWidths[index]; } -void Font::getCharWidths(TextureAtlas &atlas) { - auto& data = atlas.atlasData; - - charWidths[0] = 2; - - for (unsigned int i = 1; i < amountOfChars; i++) { - glm::vec2 charPos = {i % 18 * charWidth, std::floor(i / 18) * charHeight}; - - unsigned int xBase = static_cast(fontTex->pos.x) + static_cast(charPos.x); - unsigned int yBase = static_cast(fontTex->pos.y) + static_cast(charPos.y); - - unsigned short width = 0; - - for (unsigned int j = 0; j < charWidth; j++) { - bool empty = true; - for (unsigned int k = 0; k < charHeight; k++) { - unsigned int xx = xBase + j; - unsigned int yy = yBase + k; - - unsigned int offset = yy * static_cast(atlasSize.x) * 4 + xx * 4 + 3; - - if (data[offset] != 0) { - empty = false; - break; - } - } - if (!empty) width = static_cast(j); - } - - charWidths[i] = width; - } +void Font::getCharWidths(TextureAtlas& atlas) { + auto& data = atlas.atlasData; + + charWidths[0] = 2; + + for (unsigned int i = 1; i < amountOfChars; i++) { + glm::vec2 charPos = { i % 18 * charWidth, std::floor(i / 18) * charHeight }; + + unsigned int xBase = static_cast(fontTex->pos.x) + static_cast(charPos.x); + unsigned int yBase = static_cast(fontTex->pos.y) + static_cast(charPos.y); + + unsigned short width = 0; + + for (unsigned int j = 0; j < charWidth; j++) { + bool empty = true; + for (unsigned int k = 0; k < charHeight; k++) { + unsigned int xx = xBase + j; + unsigned int yy = yBase + k; + + unsigned int offset = yy * static_cast(atlasSize.x) * 4 + xx * 4 + 3; + + if (data[offset] != 0) { + empty = false; + break; + } + } + if (!empty) width = static_cast(j); + } + + charWidths[i] = width; + } } glm::vec4 Font::getCharUVs(char c) { - unsigned int index = static_cast(c) - 32; - if (index >= amountOfChars) throw std::runtime_error("Invalid char index."); - - glm::vec2 charPos = {(index % 18) * charWidth, std::floor(index / 18) * charHeight}; - glm::vec4 uv = { - fontTex->uv.x + (charPos.x) / atlasSize.x, - fontTex->uv.y + (charPos.y) / atlasSize.y, - fontTex->uv.x + (charPos.x + getCharWidth(c) + 1) / atlasSize.x, - fontTex->uv.y + (charPos.y + charHeight) / atlasSize.y - }; - - return uv; + unsigned int index = static_cast(c) - 32; + if (index >= amountOfChars) throw std::runtime_error("Invalid char index."); + + glm::vec2 charPos = { (index % 18) * charWidth, std::floor(index / 18) * charHeight }; + glm::vec4 uv = { + fontTex->uv.x + (charPos.x) / atlasSize.x, + fontTex->uv.y + (charPos.y) / atlasSize.y, + fontTex->uv.x + (charPos.x + getCharWidth(c) + 1) / atlasSize.x, + fontTex->uv.y + (charPos.y + charHeight) / atlasSize.y + }; + + return uv; } diff --git a/src/client/graph/Font.h b/src/client/graph/Font.h index 93c1eb97..ac7f6688 100644 --- a/src/client/graph/Font.h +++ b/src/client/graph/Font.h @@ -9,23 +9,27 @@ #include class AtlasRef; + class TextureAtlas; class Font { -public: - Font() = default; - Font(TextureAtlas& atlas, std::shared_ptr tex); - unsigned int getCharWidth(char c); - glm::vec4 getCharUVs(char c); - - const static unsigned int amountOfChars = 95; - const static unsigned int charWidth = 7; - const static unsigned int charHeight = 9; -private: - void getCharWidths(TextureAtlas& atlas); - - glm::vec2 atlasSize {}; - - std::shared_ptr fontTex = nullptr; - std::array charWidths {}; + public: + Font() = default; + + Font(TextureAtlas& atlas, std::shared_ptr tex); + + unsigned int getCharWidth(char c); + + glm::vec4 getCharUVs(char c); + + const static unsigned int amountOfChars = 95; + const static unsigned int charWidth = 7; + const static unsigned int charHeight = 9; + private: + void getCharWidths(TextureAtlas& atlas); + + glm::vec2 atlasSize{}; + + std::shared_ptr fontTex = nullptr; + std::array charWidths{}; }; diff --git a/src/client/graph/Model.cpp b/src/client/graph/Model.cpp index 4fbcc399..49216aa4 100644 --- a/src/client/graph/Model.cpp +++ b/src/client/graph/Model.cpp @@ -17,56 +17,57 @@ #include "game/atlas/asset/SerializedModel.h" void Model::fromMesh(std::unique_ptr mesh) { - meshes.clear(); - meshes.push_back(std::move(mesh)); + meshes.clear(); + meshes.push_back(std::move(mesh)); } -int Model::fromFile(const std::string &path, const std::vector> &textures) { - this->textures = textures; - - Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl; - return 1; - } - - loadModelMeshes(scene->mRootNode, scene); - loadAnimations(scene); - - calcBoneHeirarchy(scene->mRootNode, scene, -1); - - globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation)); - - return 0; +int Model::fromFile(const std::string& path, const std::vector>& textures) { + this->textures = textures; + + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { + std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl; + return 1; + } + + loadModelMeshes(scene->mRootNode, scene); + loadAnimations(scene); + + calcBoneHeirarchy(scene->mRootNode, scene, -1); + + globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation)); + + return 0; } int Model::fromSerialized(const SerializedModel& model, const std::vector>& textures) { - this->textures = textures; - - Assimp::Importer importer; - const aiScene* scene = importer.ReadFileFromMemory(model.data.data(), model.data.length(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals, "B3D"); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl; - return 1; - } - - loadModelMeshes(scene->mRootNode, scene); - loadAnimations(scene); - - calcBoneHeirarchy(scene->mRootNode, scene, -1); - globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation)); - return 0; + this->textures = textures; + + Assimp::Importer importer; + const aiScene* scene = importer.ReadFileFromMemory(model.data.data(), model.data.length(), + aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals, "B3D"); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { + std::cout << Log::err << "ERROR::ASSIMP::" << importer.GetErrorString() << Log::endl; + return 1; + } + + loadModelMeshes(scene->mRootNode, scene); + loadAnimations(scene); + + calcBoneHeirarchy(scene->mRootNode, scene, -1); + globalInverseTransform = glm::inverse(MatConv::AiToGLMMat4(scene->mRootNode->mTransformation)); + return 0; } void Model::getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector& transforms) { - transforms.resize(bones.size()); - - if (!rootBones.empty()) - for (auto bone : rootBones) - calcBoneTransformation(frame, *bone, glm::mat4(1.0f), bounds, transforms); + transforms.resize(bones.size()); + + if (!rootBones.empty()) + for (auto bone : rootBones) + calcBoneTransformation(frame, *bone, glm::mat4(1.0f), bounds, transforms); } //void Model::getTransformsByTime(double time, std::vector& transforms) { @@ -76,187 +77,191 @@ void Model::getTransformsByFrame(double frame, glm::ivec2 bounds, std::vectormNumMeshes; i++) { - aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - meshes.emplace_back(std::make_unique()); - loadMeshAndBone(mesh, meshes[i]); - } - - for (unsigned int i = 0; i < node->mNumChildren; i++) { - loadModelMeshes(node->mChildren[i], scene); //Recurse down - } +void Model::loadModelMeshes(aiNode* node, const aiScene* scene) { + for (unsigned int i = 0; i < node->mNumMeshes; i++) { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.emplace_back(std::make_unique()); + loadMeshAndBone(mesh, meshes[i]); + } + + for (unsigned int i = 0; i < node->mNumChildren; i++) { + loadModelMeshes(node->mChildren[i], scene); //Recurse down + } } -void Model::loadMeshAndBone(aiMesh *mesh, std::unique_ptr& target) { - std::vector vertices; - std::vector indices; - - //Process Vertices - for (unsigned int i = 0; i < mesh->mNumVertices; i++) { - EntityVertex vertex {}; - - vertex.position = {mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z}; - vertex.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z}; - vertex.colorBlend = {1, 1, 1}; - - assert(mesh->mMaterialIndex >= 0 && mesh->mMaterialIndex < textures.size()); - - if (mesh->mTextureCoords[0]) { - auto& texture = textures[mesh->mMaterialIndex]; - - //Set texture coordinates - vertex.useTex = true; - vertex.colorData = { - texture->uv.x + mesh->mTextureCoords[0][i].x * (texture->uv.z - texture->uv.x), - texture->uv.y + mesh->mTextureCoords[0][i].y * (texture->uv.w - texture->uv.y), 0, 1 //Alpha - }; - } - else vertex.colorData = {1, 1, 1, 1}; - - vertices.push_back(vertex); - } - - //Process Indices - for (unsigned int i = 0; i < mesh->mNumFaces; i++) { - aiFace face = mesh->mFaces[i]; - for (unsigned int j = 0; j < face.mNumIndices; j++) { - indices.push_back(face.mIndices[j]); - } - } - - //Process Mesh Bones and add to bone list - bones.resize(mesh->mNumBones); - for (unsigned int i = 0; i < mesh->mNumBones; i++) { - aiBone* bone = mesh->mBones[i]; - - bones[i] = ModelBone(static_cast(i), -1, {bone->mName.data}); - bones[i].offsetMatrix = glm::transpose(MatConv::AiToGLMMat4(bone->mOffsetMatrix)); - - for (unsigned int j = 0; j < bone->mNumWeights; j++) { - aiVertexWeight* weight = &bone->mWeights[j]; - if (weight->mVertexId >= vertices.size()) assert(0); - - unsigned int bid = 0; - while (vertices[weight->mVertexId].boneWeights[bid] != 0) { - bid++; - assert(bid < 4); - } - - vertices[weight->mVertexId].boneIDs[bid] = i; - vertices[weight->mVertexId].boneWeights[bid] = weight->mWeight; - } - } - - //Create mesh - target->create(vertices, indices); +void Model::loadMeshAndBone(aiMesh* mesh, std::unique_ptr& target) { + std::vector vertices; + std::vector indices; + + //Process Vertices + for (unsigned int i = 0; i < mesh->mNumVertices; i++) { + EntityVertex vertex{}; + + vertex.position = { mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z }; + vertex.normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z }; + vertex.colorBlend = { 1, 1, 1 }; + + assert(mesh->mMaterialIndex >= 0 && mesh->mMaterialIndex < textures.size()); + + if (mesh->mTextureCoords[0]) { + auto& texture = textures[mesh->mMaterialIndex]; + + //Set texture coordinates + vertex.useTex = true; + vertex.colorData = { + texture->uv.x + mesh->mTextureCoords[0][i].x * (texture->uv.z - texture->uv.x), + texture->uv.y + mesh->mTextureCoords[0][i].y * (texture->uv.w - texture->uv.y), 0, 1 //Alpha + }; + } + else vertex.colorData = { 1, 1, 1, 1 }; + + vertices.push_back(vertex); + } + + //Process Indices + for (unsigned int i = 0; i < mesh->mNumFaces; i++) { + aiFace face = mesh->mFaces[i]; + for (unsigned int j = 0; j < face.mNumIndices; j++) { + indices.push_back(face.mIndices[j]); + } + } + + //Process Mesh Bones and add to bone list + bones.resize(mesh->mNumBones); + for (unsigned int i = 0; i < mesh->mNumBones; i++) { + aiBone* bone = mesh->mBones[i]; + + bones[i] = ModelBone(static_cast(i), -1, { bone->mName.data }); + bones[i].offsetMatrix = glm::transpose(MatConv::AiToGLMMat4(bone->mOffsetMatrix)); + + for (unsigned int j = 0; j < bone->mNumWeights; j++) { + aiVertexWeight* weight = &bone->mWeights[j]; + if (weight->mVertexId >= vertices.size()) assert(0); + + unsigned int bid = 0; + while (vertices[weight->mVertexId].boneWeights[bid] != 0) { + bid++; + assert(bid < 4); + } + + vertices[weight->mVertexId].boneIDs[bid] = i; + vertices[weight->mVertexId].boneWeights[bid] = weight->mWeight; + } + } + + //Create mesh + target->create(vertices, indices); } -void Model::loadAnimations(const aiScene *scene) { - assert(scene->mNumAnimations <= 1); - - if (scene->mNumAnimations == 1) { - const aiAnimation* aiAnim = scene->mAnimations[0]; - - animation = ModelAnimation(aiAnim->mName.data); - - animation.duration = static_cast(aiAnim->mDuration); - animation.ticksPerSecond = aiAnim->mTicksPerSecond; - - animation.channels.resize(bones.size()); - - for (unsigned int j = 0; j < aiAnim->mNumChannels; j++) { - const aiNodeAnim* aiChannel = aiAnim->mChannels[j]; - - int index = -1; - for (unsigned int k = 0; k < bones.size(); k++) { - if (std::string {aiChannel->mNodeName.data} == bones[k].name) { - index = k; - continue; - } - } - - if (index == -1) { +void Model::loadAnimations(const aiScene* scene) { + assert(scene->mNumAnimations <= 1); + + if (scene->mNumAnimations == 1) { + const aiAnimation* aiAnim = scene->mAnimations[0]; + + animation = ModelAnimation(aiAnim->mName.data); + + animation.duration = static_cast(aiAnim->mDuration); + animation.ticksPerSecond = aiAnim->mTicksPerSecond; + + animation.channels.resize(bones.size()); + + for (unsigned int j = 0; j < aiAnim->mNumChannels; j++) { + const aiNodeAnim* aiChannel = aiAnim->mChannels[j]; + + int index = -1; + for (unsigned int k = 0; k < bones.size(); k++) { + if (std::string{ aiChannel->mNodeName.data } == bones[k].name) { + index = k; + continue; + } + } + + if (index == -1) { // std::cout << aiChannel->mNodeName.data << std::endl; - } - else { - animation.channels[index] = AnimChannel(static_cast(index), aiChannel->mNodeName.data); - AnimChannel &channel = animation.channels[index]; - - //Copy Rotation Keys - channel.rotationKeys.reserve(aiChannel->mNumRotationKeys); - for (unsigned int k = 0; k < aiChannel->mNumRotationKeys; k++) { - aiQuatKey *key = &aiChannel->mRotationKeys[k]; - channel.rotationKeys.emplace_back(key->mTime, key->mValue); - } - - //Copy Position Keys - channel.positionKeys.reserve(aiChannel->mNumPositionKeys); - for (unsigned int k = 0; k < aiChannel->mNumPositionKeys; k++) { - aiVectorKey *key = &aiChannel->mPositionKeys[k]; - channel.positionKeys.emplace_back(key->mTime, - glm::vec3{key->mValue.x, key->mValue.y, key->mValue.z}); - } - - //Copy Scale Keys - channel.scaleKeys.reserve(aiChannel->mNumScalingKeys); - for (unsigned int k = 0; k < aiChannel->mNumScalingKeys; k++) { - aiVectorKey *key = &aiChannel->mScalingKeys[k]; - channel.scaleKeys.emplace_back(key->mTime, glm::vec3{key->mValue.x, key->mValue.y, key->mValue.z}); - } - } - } - } + } + else { + animation.channels[index] = AnimChannel(static_cast(index), aiChannel->mNodeName.data); + AnimChannel& channel = animation.channels[index]; + + //Copy Rotation Keys + channel.rotationKeys.reserve(aiChannel->mNumRotationKeys); + for (unsigned int k = 0; k < aiChannel->mNumRotationKeys; k++) { + aiQuatKey* key = &aiChannel->mRotationKeys[k]; + channel.rotationKeys.emplace_back(key->mTime, key->mValue); + } + + //Copy Position Keys + channel.positionKeys.reserve(aiChannel->mNumPositionKeys); + for (unsigned int k = 0; k < aiChannel->mNumPositionKeys; k++) { + aiVectorKey* key = &aiChannel->mPositionKeys[k]; + channel.positionKeys.emplace_back(key->mTime, + glm::vec3{ key->mValue.x, key->mValue.y, key->mValue.z }); + } + + //Copy Scale Keys + channel.scaleKeys.reserve(aiChannel->mNumScalingKeys); + for (unsigned int k = 0; k < aiChannel->mNumScalingKeys; k++) { + aiVectorKey* key = &aiChannel->mScalingKeys[k]; + channel.scaleKeys.emplace_back(key->mTime, + glm::vec3{ key->mValue.x, key->mValue.y, key->mValue.z }); + } + } + } + } } -void Model::calcBoneHeirarchy(aiNode *node, const aiScene *scene, int parentBoneIndex) { - int index = -1; - - for (auto &bone : bones) { - if (bone.name == std::string(node->mName.data)) { - bone.parent = parentBoneIndex; - index = bone.index; - if (parentBoneIndex == -1) rootBones.push_back(&bone); - else bones[bone.parent].children.push_back(&bone); - break; - } - } - - for (unsigned int i = 0; i < node->mNumChildren; i++) calcBoneHeirarchy(node->mChildren[i], scene, index); +void Model::calcBoneHeirarchy(aiNode* node, const aiScene* scene, int parentBoneIndex) { + int index = -1; + + for (auto& bone : bones) { + if (bone.name == std::string(node->mName.data)) { + bone.parent = parentBoneIndex; + index = bone.index; + if (parentBoneIndex == -1) rootBones.push_back(&bone); + else bones[bone.parent].children.push_back(&bone); + break; + } + } + + for (unsigned int i = 0; i < node->mNumChildren; i++) calcBoneHeirarchy(node->mChildren[i], scene, index); } -void Model::calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, std::vector& transforms) { - AnimChannel* channel = nullptr; - for (auto &i : animation.channels) { - if (i.index == bone.index) { - channel = &i; - break; - } - } - - glm::mat4 boneTransformation(1.0f); - if (channel) { - glm::mat4 position = glm::translate(glm::mat4(1.0), calcBoneVal(animTime, bounds, channel->positionKeys, {}, - [](const glm::vec3 &a, const glm::vec3 &b, float factor) { return glm::mix(a, b, factor); })); - glm::mat4 scale = glm::scale(glm::mat4(1.0), calcBoneVal(animTime, bounds, channel->scaleKeys, {}, - [](const glm::vec3 &a, const glm::vec3 &b, float factor) { return glm::mix(a, b, factor); })); - glm::mat4 rotation = glm::transpose(glm::mat4(MatConv::AiToGLMMat3( - calcBoneVal(animTime, bounds, channel->rotationKeys, {}, - [](const aiQuaternion& a, const aiQuaternion& b, float factor) { - aiQuaternion result; - aiQuaternion::Interpolate(result, a, b, factor); - return result.Normalize(); - }).GetMatrix()))); - - boneTransformation = position * rotation * scale; - } - - glm::mat4 globalTransformation = parentTransform * boneTransformation; - transforms[bone.index] = globalInverseTransform * globalTransformation * bone.offsetMatrix; - - for (auto& child : bone.children) calcBoneTransformation(animTime, *child, globalTransformation, bounds, transforms); +void Model::calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, + std::vector& transforms) { + AnimChannel* channel = nullptr; + for (auto& i : animation.channels) { + if (i.index == bone.index) { + channel = &i; + break; + } + } + + glm::mat4 boneTransformation(1.0f); + if (channel) { + glm::mat4 position = glm::translate(glm::mat4(1.0), + calcBoneVal(animTime, bounds, channel->positionKeys, {}, + [](const glm::vec3& a, const glm::vec3& b, float factor) { return glm::mix(a, b, factor); })); + glm::mat4 scale = glm::scale(glm::mat4(1.0), calcBoneVal(animTime, bounds, channel->scaleKeys, {}, + [](const glm::vec3& a, const glm::vec3& b, float factor) { return glm::mix(a, b, factor); })); + glm::mat4 rotation = glm::transpose(glm::mat4(MatConv::AiToGLMMat3( + calcBoneVal(animTime, bounds, channel->rotationKeys, {}, + [](const aiQuaternion& a, const aiQuaternion& b, float factor) { + aiQuaternion result; + aiQuaternion::Interpolate(result, a, b, factor); + return result.Normalize(); + }).GetMatrix()))); + + boneTransformation = position * rotation * scale; + } + + glm::mat4 globalTransformation = parentTransform * boneTransformation; + transforms[bone.index] = globalInverseTransform * globalTransformation * bone.offsetMatrix; + + for (auto& child : bone.children) + calcBoneTransformation(animTime, *child, globalTransformation, bounds, transforms); } \ No newline at end of file diff --git a/src/client/graph/Model.h b/src/client/graph/Model.h index 65c4c47d..963238ed 100644 --- a/src/client/graph/Model.h +++ b/src/client/graph/Model.h @@ -16,60 +16,68 @@ #include "client/graph/mesh/EntityMesh.h" class AtlasRef; + class SerializedModel; class Model { -public: - Model() = default; - - void fromMesh(std::unique_ptr mesh); - int fromFile(const std::string &path, const std::vector> &texture); - int fromSerialized(const SerializedModel &model, const std::vector> &texture); - - void getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector& transforms); + public: + Model() = default; + + void fromMesh(std::unique_ptr mesh); + + int fromFile(const std::string& path, const std::vector>& texture); + + int fromSerialized(const SerializedModel& model, const std::vector>& texture); + + void getTransformsByFrame(double frame, glm::ivec2 bounds, std::vector& transforms); // void getTransformsByTime(double time, std::tuple bounds, std::vector& transforms); - - const ModelAnimation& getAnimation(); - - std::vector> meshes; -private: - void loadModelMeshes(aiNode *node, const aiScene *scene); - void loadMeshAndBone(aiMesh *mesh, std::unique_ptr &target); - void loadAnimations(const aiScene *scene); - - void calcBoneHeirarchy(aiNode *node, const aiScene *scene, int parentBoneIndex); - void calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, std::vector& transforms); - - template static inline T calcBoneVal( - double animTime, glm::ivec2 bounds, const std::vector>& keysArray, - const T& def, std::function merge) { - - if (keysArray.empty()) return def; - if (keysArray.size() == 1) return keysArray[0].second; - - unsigned int index = 0; - for (unsigned int i = 1; i < keysArray.size(); i++) { - if (keysArray[i].first > animTime) { - index = i - 1; - break; - } - } - float factor = 1; - unsigned int nextIndex = index + 1; - if (nextIndex >= keysArray.size() || nextIndex > bounds.y) nextIndex = bounds.x; - else { - double delta = keysArray[nextIndex].first - keysArray[index].first; - factor = (animTime - keysArray[index].first) / delta; - } - - return merge(keysArray[index].second, keysArray[nextIndex].second, factor); - } - - ModelAnimation animation {}; - std::vector rootBones {}; - std::vector bones {}; - std::vector> textures {}; - - glm::mat4 globalInverseTransform {}; + + const ModelAnimation& getAnimation(); + + std::vector> meshes; + private: + void loadModelMeshes(aiNode* node, const aiScene* scene); + + void loadMeshAndBone(aiMesh* mesh, std::unique_ptr& target); + + void loadAnimations(const aiScene* scene); + + void calcBoneHeirarchy(aiNode* node, const aiScene* scene, int parentBoneIndex); + + void calcBoneTransformation(double animTime, ModelBone& bone, glm::mat4 parentTransform, glm::ivec2 bounds, + std::vector& transforms); + + template + static inline T calcBoneVal( + double animTime, glm::ivec2 bounds, const std::vector>& keysArray, + const T& def, std::function merge) { + + if (keysArray.empty()) return def; + if (keysArray.size() == 1) return keysArray[0].second; + + unsigned int index = 0; + for (unsigned int i = 1; i < keysArray.size(); i++) { + if (keysArray[i].first > animTime) { + index = i - 1; + break; + } + } + float factor = 1; + unsigned int nextIndex = index + 1; + if (nextIndex >= keysArray.size() || nextIndex > bounds.y) nextIndex = bounds.x; + else { + double delta = keysArray[nextIndex].first - keysArray[index].first; + factor = (animTime - keysArray[index].first) / delta; + } + + return merge(keysArray[index].second, keysArray[nextIndex].second, factor); + } + + ModelAnimation animation{}; + std::vector rootBones{}; + std::vector bones{}; + std::vector> textures{}; + + glm::mat4 globalInverseTransform{}; }; diff --git a/src/client/graph/ModelAnimation.cpp b/src/client/graph/ModelAnimation.cpp index 85ebf676..ad807f4c 100644 --- a/src/client/graph/ModelAnimation.cpp +++ b/src/client/graph/ModelAnimation.cpp @@ -5,4 +5,4 @@ #include "ModelAnimation.h" ModelAnimation::ModelAnimation(const std::string& name) - : name(name) {} + : name(name) {} diff --git a/src/client/graph/ModelAnimation.h b/src/client/graph/ModelAnimation.h index 7d8c9265..35a7215e 100644 --- a/src/client/graph/ModelAnimation.h +++ b/src/client/graph/ModelAnimation.h @@ -10,12 +10,13 @@ #include "world/dim/ent/AnimChannel.h" class ModelAnimation { -public: - ModelAnimation() = default; - explicit ModelAnimation(const std::string& name); - - std::string name = ""; - std::vector channels {}; - unsigned int duration = 0; - double ticksPerSecond = 0; + public: + ModelAnimation() = default; + + explicit ModelAnimation(const std::string& name); + + std::string name = ""; + std::vector channels{}; + unsigned int duration = 0; + double ticksPerSecond = 0; }; diff --git a/src/client/graph/ModelBone.cpp b/src/client/graph/ModelBone.cpp index 0d8a8275..041daf9c 100644 --- a/src/client/graph/ModelBone.cpp +++ b/src/client/graph/ModelBone.cpp @@ -5,6 +5,6 @@ #include "ModelBone.h" ModelBone::ModelBone(unsigned int index, int parent, const std::string& name) : - index(index), - parent(parent), - name(name) {} \ No newline at end of file + index(index), + parent(parent), + name(name) {} \ No newline at end of file diff --git a/src/client/graph/ModelBone.h b/src/client/graph/ModelBone.h index bb360b72..53152656 100644 --- a/src/client/graph/ModelBone.h +++ b/src/client/graph/ModelBone.h @@ -9,15 +9,16 @@ #include class ModelBone { -public: - ModelBone() = default; - ModelBone(unsigned int index, int parent, const std::string& name); - - std::string name {}; - unsigned int index = 0; - int parent = 0; - - glm::mat4 offsetMatrix {}; - - std::vector children; + public: + ModelBone() = default; + + ModelBone(unsigned int index, int parent, const std::string& name); + + std::string name{}; + unsigned int index = 0; + int parent = 0; + + glm::mat4 offsetMatrix{}; + + std::vector children; }; diff --git a/src/client/graph/Renderer.cpp b/src/client/graph/Renderer.cpp index 786ed242..350a08a3 100644 --- a/src/client/graph/Renderer.cpp +++ b/src/client/graph/Renderer.cpp @@ -6,229 +6,232 @@ #include "Renderer.h" -Renderer::Renderer() : Renderer({1366, 768}) {}; +Renderer::Renderer() : Renderer({ 1366, 768 }) {}; Renderer::Renderer(glm::ivec2 win) : - activeTexture(nullptr), - window(win), - - world (win, 2), - entity(win, 2), - ssao (win, 1, 24), - blur (win, 1), - light (win, 2) { - - camera.create(window.getSize().x, window.getSize().y, glm::vec3(0, 1, 0)); - - ssao.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoCalc.fs"); - blur.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoBlur.fs"); - light.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/deferredLighting.fs"); - world.createFromFile("../assets/shader/world/world.vs", "../assets/shader/world/world.fs", "../assets/shader/world/world.gs"); - entity.createFromFile("../assets/shader/world/entity.vs", "../assets/shader/world/entity.fs"); - - guiShader = Shader(); - guiShader.createFromFile("../assets/shader/ortho/hud.vs", "../assets/shader/ortho/hud.fs"); - - gu.matrix = camera.getOrthographicMatrix(); - gu.ortho = guiShader.get("ortho"); - gu.model = guiShader.get("model"); - gu.bones = guiShader.get("uBones"); - gu.clipBounds = guiShader.get("uClipBounds"); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - window.addResizeCallback("renderer", [&](glm::ivec2 win) { - ssao.windowResized(win); - blur.windowResized(win); - light.windowResized(win); - world.windowResized(win); - - camera.changeWindowDimensions(win); - - gu.matrix = camera.getOrthographicMatrix(); - }); + activeTexture(nullptr), + window(win), + + world(win, 2), + entity(win, 2), + ssao(win, 1, 24), + blur(win, 1), + light(win, 2) { + + camera.create(window.getSize().x, window.getSize().y, glm::vec3(0, 1, 0)); + + ssao.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoCalc.fs"); + blur.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/ssaoBlur.fs"); + light.createFromFile("../assets/shader/post/passThrough.vs", "../assets/shader/post/deferredLighting.fs"); + world.createFromFile("../assets/shader/world/world.vs", "../assets/shader/world/world.fs", + "../assets/shader/world/world.gs"); + entity.createFromFile("../assets/shader/world/entity.vs", "../assets/shader/world/entity.fs"); + + guiShader = Shader(); + guiShader.createFromFile("../assets/shader/ortho/hud.vs", "../assets/shader/ortho/hud.fs"); + + gu.matrix = camera.getOrthographicMatrix(); + gu.ortho = guiShader.get("ortho"); + gu.model = guiShader.get("model"); + gu.bones = guiShader.get("uBones"); + gu.clipBounds = guiShader.get("uClipBounds"); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + window.addResizeCallback("renderer", [&](glm::ivec2 win) { + ssao.windowResized(win); + blur.windowResized(win); + light.windowResized(win); + world.windowResized(win); + + camera.changeWindowDimensions(win); + + gu.matrix = camera.getOrthographicMatrix(); + }); } void Renderer::update(double delta) { - //VSync 1 = On, 0 = Off - glfwSwapInterval(1); - elapsedTime += delta; - - window.update(); - world.updateSwayMap(delta); + //VSync 1 = On, 0 = Off + glfwSwapInterval(1); + elapsedTime += delta; + + window.update(); + world.updateSwayMap(delta); } void Renderer::beginChunkDeferredCalls() { - activeTexture = nullptr; - currentModelUniform = world.uniforms.model; - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glDisable(GL_BLEND); - - glViewport(0, 0, static_cast(world.windowSize.x * world.bufferScale), static_cast(world.windowSize.y * world.bufferScale)); - - glBindFramebuffer(GL_FRAMEBUFFER, light.gBuffer); - glClear(GL_DEPTH_BUFFER_BIT); - - const float skyColor[] = {clearColor.x, clearColor.y, clearColor.z, 1}; - static const float clearTransparent[] = {0, 0, 0, 1}; - glClearBufferfv(GL_COLOR, 0, clearTransparent); - glClearBufferfv(GL_COLOR, 1, clearTransparent); - glClearBufferfv(GL_COLOR, 2, skyColor); - - setShader(world); - world.set(world.uniforms.proj, camera.getProjectionMatrix()); - world.set(world.uniforms.view, camera.getViewMatrix()); - world.set(world.uniforms.time, static_cast(elapsedTime)); - world.swayTex.use(1); + activeTexture = nullptr; + currentModelUniform = world.uniforms.model; + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDisable(GL_BLEND); + + glViewport(0, 0, static_cast(world.windowSize.x * world.bufferScale), + static_cast(world.windowSize.y * world.bufferScale)); + + glBindFramebuffer(GL_FRAMEBUFFER, light.gBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + const float skyColor[] = { clearColor.x, clearColor.y, clearColor.z, 1 }; + static const float clearTransparent[] = { 0, 0, 0, 1 }; + glClearBufferfv(GL_COLOR, 0, clearTransparent); + glClearBufferfv(GL_COLOR, 1, clearTransparent); + glClearBufferfv(GL_COLOR, 2, skyColor); + + setShader(world); + world.set(world.uniforms.proj, camera.getProjectionMatrix()); + world.set(world.uniforms.view, camera.getViewMatrix()); + world.set(world.uniforms.time, static_cast(elapsedTime)); + world.swayTex.use(1); } void Renderer::beginEntityDeferredCalls() { - currentModelUniform = entity.uniforms.model; - - setShader(entity); - entity.set(entity.uniforms.proj, camera.getProjectionMatrix()); - entity.set(entity.uniforms.view, camera.getViewMatrix()); + currentModelUniform = entity.uniforms.model; + + setShader(entity); + entity.set(entity.uniforms.proj, camera.getProjectionMatrix()); + entity.set(entity.uniforms.view, camera.getViewMatrix()); } void Renderer::endDeferredCalls() { - activeTexture = nullptr; - - glBindFramebuffer(GL_FRAMEBUFFER, ssao.fbo); - glClearColor(clearColor.x, clearColor.y, clearColor.z, 0); - glClear(GL_COLOR_BUFFER_BIT); - - setShader(ssao); - ssao.set(ssao.uniforms.proj, camera.getProjectionMatrix()); - ssao.set(ssao.uniforms.view, camera.getViewMatrix()); - ssao.set(ssao.uniforms.kernelCount, ssao.kernelCount); - - for (unsigned int i = 0; i < ssao.kernelCount; i++) { - GLint uni = ssao.get("samples[" + std::to_string(i) + "]"); - ssao.set(uni, ssao.kernels[i]); - } - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, light.gPosition); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, light.gNormal); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, ssao.tex); - - renderQuad(); - - auto winSize = window.getSize(); - glViewport(0, 0, static_cast(winSize.x), static_cast(winSize.y)); - - glBindFramebuffer(GL_FRAMEBUFFER, blur.fbo); - glClear(GL_COLOR_BUFFER_BIT); - setShader(blur); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, ssao.colorBuffer); - renderQuad(); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - setShader(light); - light.set(light.uniforms.camPosition, camera.getPos()); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, light.gPosition); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, light.gNormal); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, light.gColorSpec); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, blur.colorBuffer); - - glEnable(GL_BLEND); - renderQuad(); + activeTexture = nullptr; + + glBindFramebuffer(GL_FRAMEBUFFER, ssao.fbo); + glClearColor(clearColor.x, clearColor.y, clearColor.z, 0); + glClear(GL_COLOR_BUFFER_BIT); + + setShader(ssao); + ssao.set(ssao.uniforms.proj, camera.getProjectionMatrix()); + ssao.set(ssao.uniforms.view, camera.getViewMatrix()); + ssao.set(ssao.uniforms.kernelCount, ssao.kernelCount); + + for (unsigned int i = 0; i < ssao.kernelCount; i++) { + GLint uni = ssao.get("samples[" + std::to_string(i) + "]"); + ssao.set(uni, ssao.kernels[i]); + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, light.gPosition); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, light.gNormal); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, ssao.tex); + + renderQuad(); + + auto winSize = window.getSize(); + glViewport(0, 0, static_cast(winSize.x), static_cast(winSize.y)); + + glBindFramebuffer(GL_FRAMEBUFFER, blur.fbo); + glClear(GL_COLOR_BUFFER_BIT); + setShader(blur); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, ssao.colorBuffer); + renderQuad(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + setShader(light); + light.set(light.uniforms.camPosition, camera.getPos()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, light.gPosition); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, light.gNormal); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, light.gColorSpec); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, blur.colorBuffer); + + glEnable(GL_BLEND); + renderQuad(); } void Renderer::beginGUIDrawCalls() { - activeTexture = nullptr; - currentModelUniform = gu.model; - - glClear(GL_DEPTH_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - - setShader(guiShader); - guiShader.set(gu.ortho, gu.matrix); + activeTexture = nullptr; + currentModelUniform = gu.model; + + glClear(GL_DEPTH_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + + setShader(guiShader); + guiShader.set(gu.ortho, gu.matrix); } void Renderer::swapBuffers() { - Shader::clearShader(); - window.swapBuffers(); + Shader::clearShader(); + window.swapBuffers(); } void Renderer::setShader(Shader& s) { - s.use(); - this->currentShader = &s; + s.use(); + this->currentShader = &s; } void Renderer::setClearColor(unsigned char r, unsigned char g, unsigned char b) { - clearColor = {static_cast(r)/255.f, static_cast(g)/255.f, static_cast(b)/255.f, 1}; + clearColor = { static_cast(r) / 255.f, static_cast(g) / 255.f, static_cast(b) / 255.f, 1 }; } void Renderer::toggleDepthTest(bool enable) { - enable ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); + enable ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); } void Renderer::clearDepthBuffer() { - glClear(GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); } void Renderer::setModelMatrix(const glm::mat4& modelMatrix) { - glUniformMatrix4fv(currentModelUniform, 1, GL_FALSE, glm::value_ptr(modelMatrix)); + glUniformMatrix4fv(currentModelUniform, 1, GL_FALSE, glm::value_ptr(modelMatrix)); } -void Renderer::setBones(std::vector &transforms) { - if (transforms.empty()) return; - currentShader->setArr((currentShader == &entity ? entity.uniforms.bones : gu.bones), static_cast(transforms.size()), transforms.at(0)); +void Renderer::setBones(std::vector& transforms) { + if (transforms.empty()) return; + currentShader->setArr((currentShader == &entity ? entity.uniforms.bones : gu.bones), + static_cast(transforms.size()), transforms.at(0)); } void Renderer::setClipBounds(glm::vec4 bounds) { - guiShader.set(gu.clipBounds, {bounds.x, window.getSize().y - bounds.w, bounds.z, window.getSize().y - bounds.y}); + guiShader.set(gu.clipBounds, { bounds.x, window.getSize().y - bounds.w, bounds.z, window.getSize().y - bounds.y }); } -void Renderer::enableTexture(Texture *texture) { - if (texture != activeTexture) { - activeTexture = texture; - texture->use(0); - } +void Renderer::enableTexture(Texture* texture) { + if (texture != activeTexture) { + activeTexture = texture; + texture->use(0); + } } void Renderer::renderQuad() { - if (quadVAO == 0) { - float quadVertices[] = { - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - }; - - glGenVertexArrays(1, &quadVAO); - glGenBuffers(1, &quadVBO); - glBindVertexArray(quadVAO); - glBindBuffer(GL_ARRAY_BUFFER, quadVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *) nullptr); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *) (3 * sizeof(float))); - } - - glBindVertexArray(quadVAO); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (quadVAO == 0) { + float quadVertices[] = { + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*) nullptr); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*) (3 * sizeof(float))); + } + + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/src/client/graph/Renderer.h b/src/client/graph/Renderer.h index 0b6c58f5..b881fb42 100644 --- a/src/client/graph/Renderer.h +++ b/src/client/graph/Renderer.h @@ -17,52 +17,62 @@ #include "shader/GuiUniforms.h" class Renderer { -public: - Renderer(); - Renderer(glm::ivec2 win); - - void update(double delta); - - void beginChunkDeferredCalls(); - void beginEntityDeferredCalls(); - void endDeferredCalls(); - void beginGUIDrawCalls(); - void swapBuffers(); - - void setShader(Shader& s); - void setClearColor(unsigned char r, unsigned char g, unsigned char b); - - static void toggleDepthTest(bool enable); - static void clearDepthBuffer(); - - void setModelMatrix(const glm::mat4& modelMatrix); - void setBones(std::vector& transforms); - void setClipBounds(glm::vec4 bounds); - void enableTexture(Texture* texture); - - Window window; - Camera camera; -private: - void renderQuad(); - - unsigned int quadVAO = 0; - unsigned int quadVBO = 0; - - glm::vec4 clearColor {0, 0, 0, 1}; - Texture* activeTexture; - - WorldGeometryShader world; - EntityGeometryShader entity; - SSAOShader ssao; - BlurShader blur; - LightingShader light; - - Shader guiShader; - GuiUniforms gu; - - Shader* currentShader; - - GLint currentModelUniform; - double elapsedTime = 0; + public: + Renderer(); + + Renderer(glm::ivec2 win); + + void update(double delta); + + void beginChunkDeferredCalls(); + + void beginEntityDeferredCalls(); + + void endDeferredCalls(); + + void beginGUIDrawCalls(); + + void swapBuffers(); + + void setShader(Shader& s); + + void setClearColor(unsigned char r, unsigned char g, unsigned char b); + + static void toggleDepthTest(bool enable); + + static void clearDepthBuffer(); + + void setModelMatrix(const glm::mat4& modelMatrix); + + void setBones(std::vector& transforms); + + void setClipBounds(glm::vec4 bounds); + + void enableTexture(Texture* texture); + + Window window; + Camera camera; + private: + void renderQuad(); + + unsigned int quadVAO = 0; + unsigned int quadVBO = 0; + + glm::vec4 clearColor{ 0, 0, 0, 1 }; + Texture* activeTexture; + + WorldGeometryShader world; + EntityGeometryShader entity; + SSAOShader ssao; + BlurShader blur; + LightingShader light; + + Shader guiShader; + GuiUniforms gu; + + Shader* currentShader; + + GLint currentModelUniform; + double elapsedTime = 0; }; diff --git a/src/client/graph/Texture.cpp b/src/client/graph/Texture.cpp index 14048200..90681183 100644 --- a/src/client/graph/Texture.cpp +++ b/src/client/graph/Texture.cpp @@ -8,59 +8,59 @@ #include "Texture.h" Texture::Texture(const std::string& file) : - fileLocation(file) { - loadFromFile(this->fileLocation); + fileLocation(file) { + loadFromFile(this->fileLocation); } void Texture::loadFromFile(std::string file) { - unsigned char *texData = stbi_load(file.c_str(), &width, &height, &bitDepth, 0); - if (!texData) throw std::runtime_error("Failed to find texture at " + file + "."); - loadFromBytes(texData, width, height); - stbi_image_free(texData); + unsigned char* texData = stbi_load(file.c_str(), &width, &height, &bitDepth, 0); + if (!texData) throw std::runtime_error("Failed to find texture at " + file + "."); + loadFromBytes(texData, width, height); + stbi_image_free(texData); } void Texture::loadFromBytes(unsigned char* bytes, int width, int height, GLint interpolation, GLint repeatMode) { - if (textureID != 0) clear(); - - this->width = width; - this->height = height; - - glGenTextures(1, &textureID); - glBindTexture(GL_TEXTURE_2D, textureID); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatMode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatMode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolation); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bytes); - glGenerateMipmap(GL_TEXTURE_2D); - - //Unbind current texture - glBindTexture(GL_TEXTURE_2D, 0); + if (textureID != 0) clear(); + + this->width = width; + this->height = height; + + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_2D, textureID); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatMode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolation); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bytes); + glGenerateMipmap(GL_TEXTURE_2D); + + //Unbind current texture + glBindTexture(GL_TEXTURE_2D, 0); } -void Texture::updateTexture(int x, int y, int width, int height, unsigned char *bytes) { - glBindTexture(GL_TEXTURE_2D, textureID); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes); +void Texture::updateTexture(int x, int y, int width, int height, unsigned char* bytes) { + glBindTexture(GL_TEXTURE_2D, textureID); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes); } void Texture::use(GLuint position) { - glActiveTexture(GL_TEXTURE0 + position); - glBindTexture(GL_TEXTURE_2D, textureID); + glActiveTexture(GL_TEXTURE0 + position); + glBindTexture(GL_TEXTURE_2D, textureID); } void Texture::clear() { - glDeleteTextures(1, &textureID); - textureID = 0; - fileLocation = ""; - - width = 0; - height = 0; - bitDepth = 0; + glDeleteTextures(1, &textureID); + textureID = 0; + fileLocation = ""; + + width = 0; + height = 0; + bitDepth = 0; } Texture::~Texture() { - clear(); + clear(); } \ No newline at end of file diff --git a/src/client/graph/Texture.h b/src/client/graph/Texture.h index 4a65cea7..014ec903 100644 --- a/src/client/graph/Texture.h +++ b/src/client/graph/Texture.h @@ -8,25 +8,30 @@ #include class Texture { -public: - Texture() = default; - explicit Texture(const std::string& file); - - void loadFromFile(std::string file); - void loadFromBytes(unsigned char* bytes, int width, int height, GLint interpolation = GL_NEAREST, GLint repeatMode = GL_CLAMP_TO_EDGE); - void updateTexture(int x, int y, int width, int height, unsigned char* bytes); - - void use(GLuint position = 0); - void clear(); - - ~Texture(); - -protected: - unsigned int textureID = 0; - int width = 0; - int height = 0; - int bitDepth = 0; - - std::string fileLocation; + public: + Texture() = default; + + explicit Texture(const std::string& file); + + void loadFromFile(std::string file); + + void loadFromBytes(unsigned char* bytes, int width, int height, GLint interpolation = GL_NEAREST, + GLint repeatMode = GL_CLAMP_TO_EDGE); + + void updateTexture(int x, int y, int width, int height, unsigned char* bytes); + + void use(GLuint position = 0); + + void clear(); + + ~Texture(); + + protected: + unsigned int textureID = 0; + int width = 0; + int height = 0; + int bitDepth = 0; + + std::string fileLocation; }; diff --git a/src/client/graph/mesh/ChunkMesh.cpp b/src/client/graph/mesh/ChunkMesh.cpp index 55d3a598..d80b55ec 100644 --- a/src/client/graph/mesh/ChunkMesh.cpp +++ b/src/client/graph/mesh/ChunkMesh.cpp @@ -7,23 +7,23 @@ #include "ChunkVertex.h" void ChunkMesh::create(const std::vector& vertices, const std::vector& indices) { - indCount = static_cast(indices.size()); - - genArrays(static_cast(vertices.size() * sizeof(ChunkVertex)), - static_cast(indices.size() * sizeof(unsigned int)), - &vertices.front(), &indices.front()); - - unsigned int idx = 0; - createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(position)); - createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(texCoords)); - createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor)); - createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords)); - createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal)); - createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_CHUNK(light)); - createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod)); - createVertexAttrib(idx , 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues)); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + indCount = static_cast(indices.size()); + + genArrays(static_cast(vertices.size() * sizeof(ChunkVertex)), + static_cast(indices.size() * sizeof(unsigned int)), + &vertices.front(), &indices.front()); + + unsigned int idx = 0; + createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(position)); + createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(texCoords)); + createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor)); + createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords)); + createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal)); + createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_CHUNK(light)); + createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod)); + createVertexAttrib(idx, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); } \ No newline at end of file diff --git a/src/client/graph/mesh/ChunkMesh.h b/src/client/graph/mesh/ChunkMesh.h index 953fd0ac..98d7de7a 100644 --- a/src/client/graph/mesh/ChunkMesh.h +++ b/src/client/graph/mesh/ChunkMesh.h @@ -12,11 +12,12 @@ class ChunkVertex; class ChunkMesh : public Mesh { -public: - ChunkMesh() = default; - ChunkMesh(const ChunkMesh& o) { throw std::runtime_error("No copy constructor for ChunkMeshes"); }; - - void create(const std::vector& vertices, const std::vector& indices); - - ~ChunkMesh() = default; + public: + ChunkMesh() = default; + + ChunkMesh(const ChunkMesh& o) { throw std::runtime_error("No copy constructor for ChunkMeshes"); }; + + void create(const std::vector& vertices, const std::vector& indices); + + ~ChunkMesh() = default; }; diff --git a/src/client/graph/mesh/ChunkMeshGenerator.cpp b/src/client/graph/mesh/ChunkMeshGenerator.cpp index e26c13bd..0cda75e2 100644 --- a/src/client/graph/mesh/ChunkMeshGenerator.cpp +++ b/src/client/graph/mesh/ChunkMeshGenerator.cpp @@ -5,6 +5,7 @@ #include #define GLM_ENABLE_EXPERIMENTAL + #include #include "ChunkMeshGenerator.h" @@ -21,129 +22,141 @@ #include "game/atlas/LocalBiomeAtlas.h" #include "game/atlas/LocalDefinitionAtlas.h" -ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes, - std::shared_ptr chunk, std::array, 6> adjacent, std::array& blockOffsets) : - meshDetails(meshDetails), - adjacent(adjacent), - biomes(biomes), - chunk(chunk), - defs(defs) { - - Timer t("Mesh generation"); - - meshDetails->vertices.reserve(5000); - meshDetails->indices.reserve(7000); - - auto l = chunk->getReadLock(); - RIE::expand(chunk->cGetBlocks(), eBlocks); - RIE::expand(chunk->cGetBiomes(), eBiomes); - l.unlock(); - - BlockDef* block = nullptr; - BiomeDef* biome = nullptr; - - for (unsigned short i = 0; i < 4096; i++) { - if (!block || block->index != eBlocks[i]) block = &defs.blockFromId(eBlocks[i]); - if (!biome || biome->index != eBiomes[i]) biome = &biomes.biomeFromId(eBiomes[i]); - - BlockModel& model = block->model; - glm::vec3 biomeTint = biome->tint; - - if (!model.visible) continue; - - glm::ivec3 off = Space::Block::fromIndex(i); - glm::vec3 vis = off; - - for (auto& mod : model.meshMods) { - switch (mod.first) { - default: break; - case MeshMod::OFFSET_X: vis.x += blockOffsets[0].get(vis / 16.f) * mod.second; break; - case MeshMod::OFFSET_Y: vis.y += blockOffsets[1].get(vis / 16.f) * mod.second; break; - case MeshMod::OFFSET_Z: vis.z += blockOffsets[2].get(vis / 16.f) * mod.second; break; - } - } - - glm::ivec3 pos = { off.x - 1, off.y, off.z }; - if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast(EVec::XNEG)], biomeTint, getLightAt(pos)); - pos = { off.x + 1, off.y, off.z }; - if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast(EVec::XPOS)], biomeTint, getLightAt(pos)); - pos = { off.x, off.y - 1, off.z }; - if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast(EVec::YNEG)], biomeTint, getLightAt(pos)); - pos = { off.x, off.y + 1, off.z }; - if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast(EVec::YPOS)], biomeTint, getLightAt(pos)); - pos = { off.x, off.y, off.z - 1 }; - if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast(EVec::ZNEG)], biomeTint, getLightAt(pos)); - pos = { off.x, off.y, off.z + 1 }; - if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast(EVec::ZPOS)], biomeTint, getLightAt(pos)); - - addFaces(vis, model.parts[static_cast(EVec::NO_CULL)], biomeTint, getLightAt(vis)); - } - - meshDetails->vertices.shrink_to_fit(); - meshDetails->indices.shrink_to_fit(); +ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, + LocalBiomeAtlas& biomes, + std::shared_ptr chunk, std::array, 6> adjacent, + std::array& blockOffsets) : + meshDetails(meshDetails), + adjacent(adjacent), + biomes(biomes), + chunk(chunk), + defs(defs) { + + Timer t("Mesh generation"); + + meshDetails->vertices.reserve(5000); + meshDetails->indices.reserve(7000); + + auto l = chunk->getReadLock(); + RIE::expand(chunk->cGetBlocks(), eBlocks); + RIE::expand(chunk->cGetBiomes(), eBiomes); + l.unlock(); + + BlockDef* block = nullptr; + BiomeDef* biome = nullptr; + + for (unsigned short i = 0; i < 4096; i++) { + if (!block || block->index != eBlocks[i]) block = &defs.blockFromId(eBlocks[i]); + if (!biome || biome->index != eBiomes[i]) biome = &biomes.biomeFromId(eBiomes[i]); + + BlockModel& model = block->model; + glm::vec3 biomeTint = biome->tint; + + if (!model.visible) continue; + + glm::ivec3 off = Space::Block::fromIndex(i); + glm::vec3 vis = off; + + for (auto& mod : model.meshMods) { + switch (mod.first) { + default: break; + case MeshMod::OFFSET_X: vis.x += blockOffsets[0].get(vis / 16.f) * mod.second; + break; + case MeshMod::OFFSET_Y: vis.y += blockOffsets[1].get(vis / 16.f) * mod.second; + break; + case MeshMod::OFFSET_Z: vis.z += blockOffsets[2].get(vis / 16.f) * mod.second; + break; + } + } + + glm::ivec3 pos = { off.x - 1, off.y, off.z }; + if (!getBlockAt(pos).culls) + addFaces(vis, model.parts[static_cast(EVec::XNEG)], biomeTint, getLightAt(pos)); + pos = { off.x + 1, off.y, off.z }; + if (!getBlockAt(pos).culls) + addFaces(vis, model.parts[static_cast(EVec::XPOS)], biomeTint, getLightAt(pos)); + pos = { off.x, off.y - 1, off.z }; + if (!getBlockAt(pos).culls) + addFaces(vis, model.parts[static_cast(EVec::YNEG)], biomeTint, getLightAt(pos)); + pos = { off.x, off.y + 1, off.z }; + if (!getBlockAt(pos).culls) + addFaces(vis, model.parts[static_cast(EVec::YPOS)], biomeTint, getLightAt(pos)); + pos = { off.x, off.y, off.z - 1 }; + if (!getBlockAt(pos).culls) + addFaces(vis, model.parts[static_cast(EVec::ZNEG)], biomeTint, getLightAt(pos)); + pos = { off.x, off.y, off.z + 1 }; + if (!getBlockAt(pos).culls) + addFaces(vis, model.parts[static_cast(EVec::ZPOS)], biomeTint, getLightAt(pos)); + + addFaces(vis, model.parts[static_cast(EVec::NO_CULL)], biomeTint, getLightAt(vis)); + } + + meshDetails->vertices.shrink_to_fit(); + meshDetails->indices.shrink_to_fit(); // t.printElapsedMs(); } BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3& pos) { - glm::ivec3 dir = {(pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0), - (pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0)}; - - if (dir != glm::ivec3 {0, 0, 0}) { - unsigned int ind = static_cast(Vec::TO_ENUM.at(dir)); - auto& chunk = adjacent[ind]; - return defs.blockFromId(chunk->getBlock(Space::Block::index(pos - dir * 16))); - } - - return defs.blockFromId(eBlocks[Space::Block::index(pos)]); + glm::ivec3 dir = { (pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0), + (pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0) }; + + if (dir != glm::ivec3{ 0, 0, 0 }) { + unsigned int ind = static_cast(Vec::TO_ENUM.at(dir)); + auto& chunk = adjacent[ind]; + return defs.blockFromId(chunk->getBlock(Space::Block::index(pos - dir * 16))); + } + + return defs.blockFromId(eBlocks[Space::Block::index(pos)]); } glm::vec4 ChunkMeshGenerator::getLightAt(const glm::ivec3& pos) { - glm::ivec3 dir = {(pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0), - (pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0)}; - - if (dir != glm::ivec3 {0, 0, 0}) { - unsigned int ind = static_cast(Vec::TO_ENUM.at(dir)); - auto& chunk = adjacent[ind]; - return chunk->getLight(Space::Block::index(pos - dir * 16)); - } - - return chunk->getLight(Space::Block::index(pos)); + glm::ivec3 dir = { (pos.x < 0 ? -1 : pos.x > 15 ? 1 : 0), + (pos.y < 0 ? -1 : pos.y > 15 ? 1 : 0), (pos.z < 0 ? -1 : pos.z > 15 ? 1 : 0) }; + + if (dir != glm::ivec3{ 0, 0, 0 }) { + unsigned int ind = static_cast(Vec::TO_ENUM.at(dir)); + auto& chunk = adjacent[ind]; + return chunk->getLight(Space::Block::index(pos - dir * 16)); + } + + return chunk->getLight(Space::Block::index(pos)); } -void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector &meshParts, const glm::vec3& tint, glm::vec4 light) { - for (const MeshPart& mp : meshParts) { - glm::vec3 modData = {}; - - switch (mp.shaderMod) { - default: break; - - case ShaderMod::ROTATE_X: - case ShaderMod::ROTATE_Y: - case ShaderMod::ROTATE_Z: - case ShaderMod::SWAY_ATTACHED: - case ShaderMod::SWAY_FULL_BLOCK: - modData = { Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0 }; - break; - } - - for (const BlockModelVertex &vertex : mp.vertices) { - meshDetails->vertices.push_back({ - vertex.pos + offset, - vertex.tex, - mp.blendInd ? tint : glm::vec3 {1, 1, 1}, - mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}, - Util::packFloat(vertex.nml), - glm::vec4(light), - static_cast(mp.shaderMod), - modData - }); - } - - for (unsigned int index : mp.indices) { - meshDetails->indices.push_back(indOffset + index); - } - - indOffset += mp.vertices.size(); - } +void +ChunkMeshGenerator::addFaces(const glm::vec3& offset, const std::vector& meshParts, const glm::vec3& tint, + glm::vec4 light) { + for (const MeshPart& mp : meshParts) { + glm::vec3 modData = {}; + + switch (mp.shaderMod) { + default: break; + + case ShaderMod::ROTATE_X: + case ShaderMod::ROTATE_Y: + case ShaderMod::ROTATE_Z: + case ShaderMod::SWAY_ATTACHED: + case ShaderMod::SWAY_FULL_BLOCK:modData = { Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0 }; + break; + } + + for (const BlockModelVertex& vertex : mp.vertices) { + meshDetails->vertices.push_back({ + vertex.pos + offset, + vertex.tex, + mp.blendInd ? tint : glm::vec3{ 1, 1, 1 }, + mp.blendInd ? vertex.blendMask : glm::vec2{ -1, -1 }, + Util::packFloat(vertex.nml), + glm::vec4(light), + static_cast(mp.shaderMod), + modData + }); + } + + for (unsigned int index : mp.indices) { + meshDetails->indices.push_back(indOffset + index); + } + + indOffset += mp.vertices.size(); + } } \ No newline at end of file diff --git a/src/client/graph/mesh/ChunkMeshGenerator.h b/src/client/graph/mesh/ChunkMeshGenerator.h index fe3be29f..d046bd09 100644 --- a/src/client/graph/mesh/ChunkMeshGenerator.h +++ b/src/client/graph/mesh/ChunkMeshGenerator.h @@ -9,33 +9,42 @@ #include class Chunk; + class MeshPart; + class BlockDef; + class NoiseSample; + class LocalBiomeAtlas; + class ChunkMeshDetails; + class LocalDefinitionAtlas; class ChunkMeshGenerator { -public: - ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes, - std::shared_ptr chunk, std::array, 6> adjacent, - std::array& blockOffsets); -private: - inline BlockDef& getBlockAt(const glm::ivec3& pos); - inline glm::vec4 getLightAt(const glm::ivec3& pos); - - void addFaces(const glm::vec3 &offset, const std::vector &meshParts, const glm::vec3& tint, glm::vec4 light); - - LocalDefinitionAtlas& defs; - LocalBiomeAtlas& biomes; - - unsigned int indOffset = 0; - ChunkMeshDetails* meshDetails; - - std::shared_ptr chunk; - std::array, 6> adjacent; - - std::array eBlocks; - std::array eBiomes; + public: + ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes, + std::shared_ptr chunk, std::array, 6> adjacent, + std::array& blockOffsets); + + private: + inline BlockDef& getBlockAt(const glm::ivec3& pos); + + inline glm::vec4 getLightAt(const glm::ivec3& pos); + + void + addFaces(const glm::vec3& offset, const std::vector& meshParts, const glm::vec3& tint, glm::vec4 light); + + LocalDefinitionAtlas& defs; + LocalBiomeAtlas& biomes; + + unsigned int indOffset = 0; + ChunkMeshDetails* meshDetails; + + std::shared_ptr chunk; + std::array, 6> adjacent; + + std::array eBlocks; + std::array eBiomes; }; \ No newline at end of file diff --git a/src/client/graph/mesh/ChunkRenderElem.h b/src/client/graph/mesh/ChunkRenderElem.h index d91bc083..3bc4ac20 100644 --- a/src/client/graph/mesh/ChunkRenderElem.h +++ b/src/client/graph/mesh/ChunkRenderElem.h @@ -9,10 +9,12 @@ class Renderer; struct ChunkRenderElem { - virtual void draw(Renderer& renderer) = 0; - virtual glm::vec3 getPos() = 0; - // Used to determine if the RenderElem should be deleted. - // Bool is if the RenderElem should be kept alive. - // True = keep, False = remove - virtual bool updateChunkUse(glm::vec3 chunk, bool used) = 0; + virtual void draw(Renderer& renderer) = 0; + + virtual glm::vec3 getPos() = 0; + + // Used to determine if the RenderElem should be deleted. + // Bool is if the RenderElem should be kept alive. + // True = keep, False = remove + virtual bool updateChunkUse(glm::vec3 chunk, bool used) = 0; }; diff --git a/src/client/graph/mesh/ChunkVertex.h b/src/client/graph/mesh/ChunkVertex.h index acdf4078..97561be2 100644 --- a/src/client/graph/mesh/ChunkVertex.h +++ b/src/client/graph/mesh/ChunkVertex.h @@ -9,14 +9,14 @@ #include struct ChunkVertex { - glm::vec3 position; - glm::vec2 texCoords; - glm::vec3 blendColor; - glm::vec2 blendMaskCoords; - float normal; - glm::vec4 light; - float shaderMod; - glm::vec3 modValues; + glm::vec3 position; + glm::vec2 texCoords; + glm::vec3 blendColor; + glm::vec2 blendMaskCoords; + float normal; + glm::vec4 light; + float shaderMod; + glm::vec3 modValues; }; #define STRIDE_OFFSET_CHUNK(m) sizeof(struct ChunkVertex), (void *)offsetof(struct ChunkVertex, m) diff --git a/src/client/graph/mesh/EntityMesh.cpp b/src/client/graph/mesh/EntityMesh.cpp index 3fbcfd96..1c1df552 100644 --- a/src/client/graph/mesh/EntityMesh.cpp +++ b/src/client/graph/mesh/EntityMesh.cpp @@ -4,38 +4,38 @@ #include "EntityMesh.h" -EntityMesh::EntityMesh(const EntityMesh &o) : - vertices(o.vertices), - indices(o.indices) { - this->indCount = o.indCount; - if (indCount > 0) initModel(); +EntityMesh::EntityMesh(const EntityMesh& o) : + vertices(o.vertices), + indices(o.indices) { + this->indCount = o.indCount; + if (indCount > 0) initModel(); } void EntityMesh::create(const std::vector& vertices, const std::vector& indices) { - indCount = static_cast(indices.size()); - this->vertices = vertices; - this->indices = indices; - - initModel(); + indCount = static_cast(indices.size()); + this->vertices = vertices; + this->indices = indices; + + initModel(); } void EntityMesh::initModel() { - if (vertices.size() == 0) return; - - genArrays(static_cast(vertices.size() * sizeof(EntityVertex)), - static_cast(indices.size() * sizeof(unsigned int)), - &vertices.front(), &indices.front()); - - unsigned int idx = 0; - createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(position)); - createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorData)); - createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorBlend)); - createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_ENTITY(useTex)); - createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(normal)); - createVertexAttrib(idx++, 4, GL_INT, STRIDE_OFFSET_ENTITY(boneIDs)); - createVertexAttrib(idx , 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(boneWeights)); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (vertices.size() == 0) return; + + genArrays(static_cast(vertices.size() * sizeof(EntityVertex)), + static_cast(indices.size() * sizeof(unsigned int)), + &vertices.front(), &indices.front()); + + unsigned int idx = 0; + createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(position)); + createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorData)); + createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(colorBlend)); + createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_ENTITY(useTex)); + createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_ENTITY(normal)); + createVertexAttrib(idx++, 4, GL_INT, STRIDE_OFFSET_ENTITY(boneIDs)); + createVertexAttrib(idx, 4, GL_FLOAT, STRIDE_OFFSET_ENTITY(boneWeights)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); } \ No newline at end of file diff --git a/src/client/graph/mesh/EntityMesh.h b/src/client/graph/mesh/EntityMesh.h index 34fa05f8..2ea741e8 100644 --- a/src/client/graph/mesh/EntityMesh.h +++ b/src/client/graph/mesh/EntityMesh.h @@ -11,14 +11,18 @@ #include "EntityVertex.h" class EntityMesh : public Mesh { -public: - EntityMesh() = default; - EntityMesh(const EntityMesh& o); - void create(const std::vector& vertices, const std::vector& indices); - ~EntityMesh() = default; -private: - void initModel(); - - std::vector vertices {}; - std::vector indices {}; + public: + EntityMesh() = default; + + EntityMesh(const EntityMesh& o); + + void create(const std::vector& vertices, const std::vector& indices); + + ~EntityMesh() = default; + + private: + void initModel(); + + std::vector vertices{}; + std::vector indices{}; }; diff --git a/src/client/graph/mesh/EntityVertex.h b/src/client/graph/mesh/EntityVertex.h index d15b5577..98fd1db9 100644 --- a/src/client/graph/mesh/EntityVertex.h +++ b/src/client/graph/mesh/EntityVertex.h @@ -8,19 +8,20 @@ #include class EntityVertex { -public: - EntityVertex() = default; - EntityVertex(glm::vec3 position, glm::vec4 colorData, glm::vec3 colorBlend, float useTex, glm::vec3 normal, - glm::ivec4 boneIDs, glm::vec4 boneWeights) : position(position), colorData(colorData), - colorBlend(colorBlend), useTex(useTex), normal(normal), boneIDs(boneIDs), boneWeights(boneWeights) {}; - - glm::vec3 position {}; - glm::vec4 colorData {}; - glm::vec3 colorBlend {}; - float useTex = false; - glm::vec3 normal {}; - glm::ivec4 boneIDs {}; - glm::vec4 boneWeights {}; + public: + EntityVertex() = default; + + EntityVertex(glm::vec3 position, glm::vec4 colorData, glm::vec3 colorBlend, float useTex, glm::vec3 normal, + glm::ivec4 boneIDs, glm::vec4 boneWeights) : position(position), colorData(colorData), + colorBlend(colorBlend), useTex(useTex), normal(normal), boneIDs(boneIDs), boneWeights(boneWeights) {}; + + glm::vec3 position{}; + glm::vec4 colorData{}; + glm::vec3 colorBlend{}; + float useTex = false; + glm::vec3 normal{}; + glm::ivec4 boneIDs{}; + glm::vec4 boneWeights{}; }; #define STRIDE_OFFSET_ENTITY(m) sizeof(struct EntityVertex), (void *)offsetof(struct EntityVertex, m) diff --git a/src/client/graph/mesh/Mesh.cpp b/src/client/graph/mesh/Mesh.cpp index db92f880..ea83abf1 100644 --- a/src/client/graph/mesh/Mesh.cpp +++ b/src/client/graph/mesh/Mesh.cpp @@ -5,44 +5,44 @@ #include "Mesh.h" void Mesh::cleanup() { - if (VAO != 0) glDeleteVertexArrays(1, &VAO); - if (VBO != 0) glDeleteBuffers(1, &VBO); - if (IBO != 0) glDeleteBuffers(1, &IBO); - - IBO = 0; - VBO = 0; - VAO = 0; - indCount = 0; + if (VAO != 0) glDeleteVertexArrays(1, &VAO); + if (VBO != 0) glDeleteBuffers(1, &VBO); + if (IBO != 0) glDeleteBuffers(1, &IBO); + + IBO = 0; + VBO = 0; + VAO = 0; + indCount = 0; } -void Mesh::genArrays(GLuint vboLength, GLuint iboLength, const void *verticesPtr, const void *indicesPtr) { - glGenVertexArrays(1, &VAO); - glBindVertexArray(VAO); - - glGenBuffers(1, &IBO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboLength, indicesPtr, GL_STATIC_DRAW); - - glGenBuffers(1, &VBO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, vboLength, verticesPtr, GL_STATIC_DRAW); +void Mesh::genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr) { + glGenVertexArrays(1, &VAO); + glBindVertexArray(VAO); + + glGenBuffers(1, &IBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboLength, indicesPtr, GL_STATIC_DRAW); + + glGenBuffers(1, &VBO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, vboLength, verticesPtr, GL_STATIC_DRAW); } -void Mesh::createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void *pointer) { - glEnableVertexAttribArray(offset); - if (type == GL_INT) - glVertexAttribIPointer(offset, size, type, stride, pointer); - else - glVertexAttribPointer(offset, size, type, GL_FALSE, stride, pointer); +void Mesh::createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer) { + glEnableVertexAttribArray(offset); + if (type == GL_INT) + glVertexAttribIPointer(offset, size, type, stride, pointer); + else + glVertexAttribPointer(offset, size, type, GL_FALSE, stride, pointer); } void Mesh::draw() const { - glBindVertexArray(VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); - - glDrawElements(GL_TRIANGLES, indCount, GL_UNSIGNED_INT, nullptr); + glBindVertexArray(VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); + + glDrawElements(GL_TRIANGLES, indCount, GL_UNSIGNED_INT, nullptr); } Mesh::~Mesh() { - cleanup(); + cleanup(); } \ No newline at end of file diff --git a/src/client/graph/mesh/Mesh.h b/src/client/graph/mesh/Mesh.h index 661016ee..701fb316 100644 --- a/src/client/graph/mesh/Mesh.h +++ b/src/client/graph/mesh/Mesh.h @@ -7,19 +7,22 @@ #include class Mesh { -public: - Mesh() = default; - - void cleanup(); - virtual void draw() const; - - ~Mesh(); -protected: - void genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr); - void createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer); - - GLuint VAO = 0; - GLuint VBO = 0; - GLuint IBO = 0; - GLsizei indCount = 0; + public: + Mesh() = default; + + void cleanup(); + + virtual void draw() const; + + ~Mesh(); + + protected: + void genArrays(GLuint vboLength, GLuint iboLength, const void* verticesPtr, const void* indicesPtr); + + void createVertexAttrib(GLuint offset, GLuint size, GLenum type, GLsizei stride, const void* pointer); + + GLuint VAO = 0; + GLuint VBO = 0; + GLuint IBO = 0; + GLsizei indCount = 0; }; diff --git a/src/client/graph/mesh/MeshChunk.cpp b/src/client/graph/mesh/MeshChunk.cpp index 19cd4942..833703ad 100644 --- a/src/client/graph/mesh/MeshChunk.cpp +++ b/src/client/graph/mesh/MeshChunk.cpp @@ -10,26 +10,26 @@ #include "client/graph/Renderer.h" #include "client/graph/mesh/ChunkMesh.h" -void MeshChunk::create(std::vector &vertices, std::vector &indices) { - this->mesh = std::make_shared(); - mesh->create(vertices, indices); +void MeshChunk::create(std::vector& vertices, std::vector& indices) { + this->mesh = std::make_shared(); + mesh->create(vertices, indices); } void MeshChunk::draw(Renderer& renderer) { - glm::mat4 model = glm::mat4(1.0); - model = glm::translate(model, pos * static_cast(16)); - renderer.setModelMatrix(model); - mesh->draw(); + glm::mat4 model = glm::mat4(1.0); + model = glm::translate(model, pos * static_cast(16)); + renderer.setModelMatrix(model); + mesh->draw(); } void MeshChunk::setPos(glm::vec3 pos) { - this->pos = pos; + this->pos = pos; } glm::vec3 MeshChunk::getPos() { - return pos; + return pos; } bool MeshChunk::updateChunkUse(glm::vec3 pos, bool used) { - return used; + return used; } \ No newline at end of file diff --git a/src/client/graph/mesh/MeshChunk.h b/src/client/graph/mesh/MeshChunk.h index da527267..704f5b11 100644 --- a/src/client/graph/mesh/MeshChunk.h +++ b/src/client/graph/mesh/MeshChunk.h @@ -11,19 +11,24 @@ #include "client/graph/Drawable.h" class ChunkMesh; + class ChunkVertex; class MeshChunk : public ChunkRenderElem, Drawable { -public: - MeshChunk() = default; - void create(std::vector &vertices, std::vector &indices); - void draw(Renderer& renderer) override; - - bool updateChunkUse(glm::vec3 chunk, bool used) override; - - void setPos(glm::vec3 pos); - glm::vec3 getPos() override; -private: - std::shared_ptr mesh = nullptr; - glm::vec3 pos {}; + public: + MeshChunk() = default; + + void create(std::vector& vertices, std::vector& indices); + + void draw(Renderer& renderer) override; + + bool updateChunkUse(glm::vec3 chunk, bool used) override; + + void setPos(glm::vec3 pos); + + glm::vec3 getPos() override; + + private: + std::shared_ptr mesh = nullptr; + glm::vec3 pos{}; }; \ No newline at end of file diff --git a/src/client/graph/shader/BlurShader.cpp b/src/client/graph/shader/BlurShader.cpp index e4c72cab..1487caa6 100644 --- a/src/client/graph/shader/BlurShader.cpp +++ b/src/client/graph/shader/BlurShader.cpp @@ -5,32 +5,34 @@ #include "BlurShader.h" BlurShader::BlurShader(glm::ivec2 windowSize, float bufferScale) : Shader(), - windowSize(windowSize), - bufferScale(bufferScale) {} + windowSize(windowSize), + bufferScale(bufferScale) {} void BlurShader::postCreate() { - uniforms.sampleScale = get("sampleScale"); - - use(); - set(uniforms.sampleScale, 1.f); - - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glGenTextures(1, &colorBuffer); - glBindTexture(GL_TEXTURE_2D, colorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); - glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + uniforms.sampleScale = get("sampleScale"); + + use(); + set(uniforms.sampleScale, 1.f); + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glGenTextures(1, &colorBuffer); + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void BlurShader::windowResized(glm::ivec2 windowSize) { - this->windowSize = windowSize; - - glBindTexture(GL_TEXTURE_2D, colorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); - glBindTexture(GL_TEXTURE_2D, 0); + this->windowSize = windowSize; + + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); + glBindTexture(GL_TEXTURE_2D, 0); } \ No newline at end of file diff --git a/src/client/graph/shader/BlurShader.h b/src/client/graph/shader/BlurShader.h index 6a3a9f19..a30b4ae6 100644 --- a/src/client/graph/shader/BlurShader.h +++ b/src/client/graph/shader/BlurShader.h @@ -9,22 +9,23 @@ #include "Shader.h" class BlurShader : public Shader { -public: - explicit BlurShader(glm::ivec2 windowSize, float bufferScale); - void postCreate() override; - - void windowResized(glm::ivec2 windowSize); - - struct Uniforms { - GLint sampleScale; - }; - - Uniforms uniforms {}; - - unsigned int fbo = 0; - unsigned int colorBuffer = 0; - -private: - glm::ivec2 windowSize {}; - float bufferScale = 1; + public: + explicit BlurShader(glm::ivec2 windowSize, float bufferScale); + + void postCreate() override; + + void windowResized(glm::ivec2 windowSize); + + struct Uniforms { + GLint sampleScale; + }; + + Uniforms uniforms{}; + + unsigned int fbo = 0; + unsigned int colorBuffer = 0; + + private: + glm::ivec2 windowSize{}; + float bufferScale = 1; }; diff --git a/src/client/graph/shader/EntityGeometryShader.cpp b/src/client/graph/shader/EntityGeometryShader.cpp index 6fc415ad..500faa53 100644 --- a/src/client/graph/shader/EntityGeometryShader.cpp +++ b/src/client/graph/shader/EntityGeometryShader.cpp @@ -5,15 +5,15 @@ #include "EntityGeometryShader.h" EntityGeometryShader::EntityGeometryShader(glm::ivec2 windowSize, float bufferScale) : Shader(), - windowSize(windowSize), - bufferScale(bufferScale) {} + windowSize(windowSize), + bufferScale(bufferScale) {} void EntityGeometryShader::postCreate() { - uniforms.proj = get("projection"); - uniforms.model = get("model"); - uniforms.view = get("view"); - - uniforms.bones = get("uBones"); + uniforms.proj = get("projection"); + uniforms.model = get("model"); + uniforms.view = get("view"); + + uniforms.bones = get("uBones"); } diff --git a/src/client/graph/shader/EntityGeometryShader.h b/src/client/graph/shader/EntityGeometryShader.h index 1561fccf..d50221c1 100644 --- a/src/client/graph/shader/EntityGeometryShader.h +++ b/src/client/graph/shader/EntityGeometryShader.h @@ -9,21 +9,22 @@ #include "Shader.h" class EntityGeometryShader : public Shader { -public: - explicit EntityGeometryShader(glm::ivec2 windowSize, float bufferScale); - void postCreate() override; - - struct Uniforms { - GLint proj; - GLint model; - GLint view; - - GLint bones; - }; - - Uniforms uniforms {}; - -private: - glm::ivec2 windowSize {}; - float bufferScale = 1; + public: + explicit EntityGeometryShader(glm::ivec2 windowSize, float bufferScale); + + void postCreate() override; + + struct Uniforms { + GLint proj; + GLint model; + GLint view; + + GLint bones; + }; + + Uniforms uniforms{}; + + private: + glm::ivec2 windowSize{}; + float bufferScale = 1; }; diff --git a/src/client/graph/shader/GuiUniforms.h b/src/client/graph/shader/GuiUniforms.h index b13a2a88..2e8f9de9 100644 --- a/src/client/graph/shader/GuiUniforms.h +++ b/src/client/graph/shader/GuiUniforms.h @@ -8,11 +8,11 @@ #include struct GuiUniforms { - glm::mat4 matrix; - - GLint ortho; - GLint model; - - GLint bones; - GLint clipBounds; + glm::mat4 matrix; + + GLint ortho; + GLint model; + + GLint bones; + GLint clipBounds; }; diff --git a/src/client/graph/shader/LightingShader.cpp b/src/client/graph/shader/LightingShader.cpp index a7c79d79..48f1be71 100644 --- a/src/client/graph/shader/LightingShader.cpp +++ b/src/client/graph/shader/LightingShader.cpp @@ -7,94 +7,102 @@ #include "LightingShader.h" LightingShader::LightingShader(glm::ivec2 windowSize, float bufferScale) : Shader(), - windowSize(windowSize), - bufferScale(bufferScale) {} + windowSize(windowSize), + bufferScale(bufferScale) {} void LightingShader::postCreate() { - uniforms.gPosition = get("gPosition"); - uniforms.gNormal = get("gNormal"); - uniforms.gColorSpec = get("gColorSpec"); - uniforms.ssaoSampler = get("ssaoSampler"); - uniforms.camPosition = get("camPosition"); - - use(); - set(uniforms.gPosition, 0); - set(uniforms.gNormal, 1); - set(uniforms.gColorSpec, 2); - set(uniforms.ssaoSampler, 3); - - glGenFramebuffers(1, &gBuffer); - glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); - - glGenTextures(1, &gPosition); - glBindTexture(GL_TEXTURE_2D, gPosition); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); - - glGenTextures(1, &gNormal); - glBindTexture(GL_TEXTURE_2D, gNormal); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); - - glGenTextures(1, &gColorSpec); - glBindTexture(GL_TEXTURE_2D, gColorSpec); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(windowSize.x), static_cast(windowSize.y), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0); - - unsigned int attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2}; - glDrawBuffers(3, attachments); - - glGenRenderbuffers(1, &rDepth); - glBindRenderbuffer(GL_RENDERBUFFER, rDepth); - - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale)); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth); - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw std::runtime_error("Lighting framebuffer incomplete."); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); + uniforms.gPosition = get("gPosition"); + uniforms.gNormal = get("gNormal"); + uniforms.gColorSpec = get("gColorSpec"); + uniforms.ssaoSampler = get("ssaoSampler"); + uniforms.camPosition = get("camPosition"); + + use(); + set(uniforms.gPosition, 0); + set(uniforms.gNormal, 1); + set(uniforms.gColorSpec, 2); + set(uniforms.ssaoSampler, 3); + + glGenFramebuffers(1, &gBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); + + glGenTextures(1, &gPosition); + glBindTexture(GL_TEXTURE_2D, gPosition); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); + + glGenTextures(1, &gNormal); + glBindTexture(GL_TEXTURE_2D, gNormal); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); + + glGenTextures(1, &gColorSpec); + glBindTexture(GL_TEXTURE_2D, gColorSpec); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(windowSize.x), static_cast(windowSize.y), 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0); + + unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + glDrawBuffers(3, attachments); + + glGenRenderbuffers(1, &rDepth); + glBindRenderbuffer(GL_RENDERBUFFER, rDepth); + + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale)); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error("Lighting framebuffer incomplete."); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void LightingShader::windowResized(glm::ivec2 windowSize) { - this->windowSize = windowSize; - - glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); - - glBindTexture(GL_TEXTURE_2D, gPosition); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); - - glBindTexture(GL_TEXTURE_2D, gNormal); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); - - glBindTexture(GL_TEXTURE_2D, gColorSpec); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0); - - unsigned int attachments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2}; - glDrawBuffers(3, attachments); - - glBindRenderbuffer(GL_RENDERBUFFER, rDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale)); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth); - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - throw std::runtime_error("Lighting framebuffer incomplete."); - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); + this->windowSize = windowSize; + + glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); + + glBindTexture(GL_TEXTURE_2D, gPosition); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0); + + glBindTexture(GL_TEXTURE_2D, gNormal); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0); + + glBindTexture(GL_TEXTURE_2D, gColorSpec); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpec, 0); + + unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + glDrawBuffers(3, attachments); + + glBindRenderbuffer(GL_RENDERBUFFER, rDepth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale)); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rDepth); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + throw std::runtime_error("Lighting framebuffer incomplete."); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/client/graph/shader/LightingShader.h b/src/client/graph/shader/LightingShader.h index 38ac6c13..9e5cb871 100644 --- a/src/client/graph/shader/LightingShader.h +++ b/src/client/graph/shader/LightingShader.h @@ -9,30 +9,31 @@ #include "Shader.h" class LightingShader : public Shader { -public: - explicit LightingShader(glm::ivec2 windowSize, float bufferScale); - void postCreate() override; - - void windowResized(glm::ivec2 windowSize); - - struct Uniforms { - GLint gPosition; - GLint gNormal; - GLint gColorSpec; - GLint ssaoSampler; - - GLint camPosition; - }; - - Uniforms uniforms {}; - - unsigned int gBuffer = 0; - unsigned int gPosition = 0; - unsigned int gNormal = 0; - unsigned int gColorSpec = 0; - unsigned int rDepth = 0; - -private: - glm::ivec2 windowSize {}; - float bufferScale = 1; + public: + explicit LightingShader(glm::ivec2 windowSize, float bufferScale); + + void postCreate() override; + + void windowResized(glm::ivec2 windowSize); + + struct Uniforms { + GLint gPosition; + GLint gNormal; + GLint gColorSpec; + GLint ssaoSampler; + + GLint camPosition; + }; + + Uniforms uniforms{}; + + unsigned int gBuffer = 0; + unsigned int gPosition = 0; + unsigned int gNormal = 0; + unsigned int gColorSpec = 0; + unsigned int rDepth = 0; + + private: + glm::ivec2 windowSize{}; + float bufferScale = 1; }; diff --git a/src/client/graph/shader/SSAOShader.cpp b/src/client/graph/shader/SSAOShader.cpp index 403169b8..12243c51 100644 --- a/src/client/graph/shader/SSAOShader.cpp +++ b/src/client/graph/shader/SSAOShader.cpp @@ -7,73 +7,75 @@ #include "SSAOShader.h" SSAOShader::SSAOShader(glm::ivec2 windowSize, float bufferScale, unsigned int kernelCount) : Shader(), - windowSize(windowSize), - bufferScale(bufferScale), - kernelCount(kernelCount) {} + windowSize(windowSize), + bufferScale(bufferScale), + kernelCount(kernelCount) {} float lerp(float a, float b, float f) { - return a + f * (b - a); + return a + f * (b - a); } void SSAOShader::postCreate() { - uniforms.proj = get("projection"); - uniforms.view = get("view"); - uniforms.kernelCount = get("kernels"); - uniforms.sampleScale = get("sampleScale"); - - use(); - set(uniforms.sampleScale, 2.0f); - - std::uniform_real_distribution rand(0.0, 1.0); - std::default_random_engine generator; - - for (unsigned int i = 0; i < kernelCount; i++) { - glm::vec3 sample { - rand(generator) * 2.0 - 1.0, - rand(generator) * 2.0 - 1.0, - rand(generator) - }; - - sample = glm::normalize(sample); - sample *= rand(generator); - - float scale = static_cast(i / kernelCount); - scale = lerp(0.1f, 1.0f, scale * scale); - sample *= scale; - - kernels.push_back(sample); - } - - for (unsigned int i = 0; i < sampleCount; i++) { - noise.emplace_back(rand(generator) * 2.0 - 1.0, rand(generator) * 2.0 - 1.0, 0.0f); - } - - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, &noise[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glBindTexture(GL_TEXTURE_2D, 0); - - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glGenTextures(1, &colorBuffer); - glBindTexture(GL_TEXTURE_2D, colorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); - glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + uniforms.proj = get("projection"); + uniforms.view = get("view"); + uniforms.kernelCount = get("kernels"); + uniforms.sampleScale = get("sampleScale"); + + use(); + set(uniforms.sampleScale, 2.0f); + + std::uniform_real_distribution rand(0.0, 1.0); + std::default_random_engine generator; + + for (unsigned int i = 0; i < kernelCount; i++) { + glm::vec3 sample{ + rand(generator) * 2.0 - 1.0, + rand(generator) * 2.0 - 1.0, + rand(generator) + }; + + sample = glm::normalize(sample); + sample *= rand(generator); + + float scale = static_cast(i / kernelCount); + scale = lerp(0.1f, 1.0f, scale * scale); + sample *= scale; + + kernels.push_back(sample); + } + + for (unsigned int i = 0; i < sampleCount; i++) { + noise.emplace_back(rand(generator) * 2.0 - 1.0, rand(generator) * 2.0 - 1.0, 0.0f); + } + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, &noise[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glGenTextures(1, &colorBuffer); + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_FLOAT, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void SSAOShader::windowResized(glm::ivec2 windowSize) { - this->windowSize = windowSize; - - glBindTexture(GL_TEXTURE_2D, colorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); - glBindTexture(GL_TEXTURE_2D, 0); + this->windowSize = windowSize; + + glBindTexture(GL_TEXTURE_2D, colorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(windowSize.x * bufferScale), + static_cast(windowSize.y * bufferScale), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); + glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/src/client/graph/shader/SSAOShader.h b/src/client/graph/shader/SSAOShader.h index f10106fa..0c00d4bf 100644 --- a/src/client/graph/shader/SSAOShader.h +++ b/src/client/graph/shader/SSAOShader.h @@ -10,32 +10,33 @@ #include "Shader.h" class SSAOShader : public Shader { -public: - explicit SSAOShader(glm::ivec2 windowSize, float bufferScale, unsigned int kernelCount); - void postCreate() override; - - void windowResized(glm::ivec2 windowSize); - - struct Uniforms { - GLint proj; - GLint view; - GLint kernelCount; - GLint sampleScale; - }; - - Uniforms uniforms {}; - - unsigned int kernelCount = 32; - unsigned int sampleCount = 16; - - std::vector kernels {}; - std::vector noise {}; - - unsigned int tex = 0; - unsigned int fbo = 0; - unsigned int colorBuffer = 0; - -private: - glm::ivec2 windowSize {}; - float bufferScale = 1; + public: + explicit SSAOShader(glm::ivec2 windowSize, float bufferScale, unsigned int kernelCount); + + void postCreate() override; + + void windowResized(glm::ivec2 windowSize); + + struct Uniforms { + GLint proj; + GLint view; + GLint kernelCount; + GLint sampleScale; + }; + + Uniforms uniforms{}; + + unsigned int kernelCount = 32; + unsigned int sampleCount = 16; + + std::vector kernels{}; + std::vector noise{}; + + unsigned int tex = 0; + unsigned int fbo = 0; + unsigned int colorBuffer = 0; + + private: + glm::ivec2 windowSize{}; + float bufferScale = 1; }; diff --git a/src/client/graph/shader/Shader.cpp b/src/client/graph/shader/Shader.cpp index cbfaf4a5..683b766d 100644 --- a/src/client/graph/shader/Shader.cpp +++ b/src/client/graph/shader/Shader.cpp @@ -11,140 +11,143 @@ #include "../../../util/Log.h" void Shader::createFromString(std::string& vertexSource, std::string& fragmentSource, const std::string& geoSource) { - compileShader(vertexSource, fragmentSource); + compileShader(vertexSource, fragmentSource); } -void Shader::createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile) { - compileShader(readFile(vertexFile), readFile(fragmentFile), - geoFile == "" ? "" : readFile(geoFile)); - postCreate(); +void +Shader::createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile) { + compileShader(readFile(vertexFile), readFile(fragmentFile), + geoFile == "" ? "" : readFile(geoFile)); + postCreate(); } std::string Shader::readFile(const std::string& fileLocation) { - std::string contents; - - std::ifstream fileStream(fileLocation, std::ios::in); - - if (!fileStream.is_open()) throw std::runtime_error("Failed to open shader file " + fileLocation + "."); - - std::string line; - while (!fileStream.eof()) { - std::getline(fileStream, line); - contents.append(line + "\n"); - } - - fileStream.close(); - return contents; + std::string contents; + + std::ifstream fileStream(fileLocation, std::ios::in); + + if (!fileStream.is_open()) throw std::runtime_error("Failed to open shader file " + fileLocation + "."); + + std::string line; + while (!fileStream.eof()) { + std::getline(fileStream, line); + contents.append(line + "\n"); + } + + fileStream.close(); + return contents; } void Shader::use() { - glUseProgram(shaderID); + glUseProgram(shaderID); } void Shader::clearShader() { - glUseProgram(0); + glUseProgram(0); } -GLint Shader::get(const std::string &name) { - return glGetUniformLocation(shaderID, name.c_str()); +GLint Shader::get(const std::string& name) { + return glGetUniformLocation(shaderID, name.c_str()); } void Shader::set(int loc, unsigned int val) { - checkActive(); - glUniform1ui(loc, val); + checkActive(); + glUniform1ui(loc, val); } void Shader::set(int loc, int val) { - checkActive(); - glUniform1i(loc, val); + checkActive(); + glUniform1i(loc, val); } void Shader::set(int loc, float val) { - checkActive(); - glUniform1f(loc, val); + checkActive(); + glUniform1f(loc, val); } void Shader::set(int loc, glm::vec3 val) { - checkActive(); - glUniform3f(loc, val.x, val.y, val.z); + checkActive(); + glUniform3f(loc, val.x, val.y, val.z); } void Shader::set(int loc, glm::vec4 val) { - checkActive(); - glUniform4f(loc, val.x, val.y, val.z, val.w); + checkActive(); + glUniform4f(loc, val.x, val.y, val.z, val.w); } void Shader::set(int loc, glm::mat4 val) { - checkActive(); - glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val)); + checkActive(); + glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val)); } -void Shader::setArr(int loc, unsigned int count, glm::mat4 &start) { - checkActive(); - glUniformMatrix4fv(loc, count, GL_FALSE, glm::value_ptr(start)); +void Shader::setArr(int loc, unsigned int count, glm::mat4& start) { + checkActive(); + glUniformMatrix4fv(loc, count, GL_FALSE, glm::value_ptr(start)); } -void Shader::compileShader(const std::string& vertexSource, const std::string& fragmentSource, const std::string& geoSource) { - shaderID = glCreateProgram(); - if (!shaderID) throw std::runtime_error("Failed to create shader program."); - - addShader(shaderID, vertexSource, GL_VERTEX_SHADER); - addShader(shaderID, fragmentSource, GL_FRAGMENT_SHADER); - if (geoSource != "") addShader(shaderID, geoSource, GL_GEOMETRY_SHADER); - - GLint result = 0; - GLchar eLog[1024] = { 0 }; - - glLinkProgram(shaderID); - glGetProgramiv(shaderID, GL_LINK_STATUS, &result); - - if (!result) { - glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog); - throw std::runtime_error("Failed to link shader program. Error:\n" + std::string(eLog)); - } - - glValidateProgram(shaderID); - glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result); - - if (!result) { - glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog); - throw std::runtime_error("Failed to validate shader program. Error:\n" + std::string(eLog)); - } +void Shader::compileShader(const std::string& vertexSource, const std::string& fragmentSource, + const std::string& geoSource) { + shaderID = glCreateProgram(); + if (!shaderID) throw std::runtime_error("Failed to create shader program."); + + addShader(shaderID, vertexSource, GL_VERTEX_SHADER); + addShader(shaderID, fragmentSource, GL_FRAGMENT_SHADER); + if (geoSource != "") addShader(shaderID, geoSource, GL_GEOMETRY_SHADER); + + GLint result = 0; + GLchar eLog[1024] = { 0 }; + + glLinkProgram(shaderID); + glGetProgramiv(shaderID, GL_LINK_STATUS, &result); + + if (!result) { + glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog); + throw std::runtime_error("Failed to link shader program. Error:\n" + std::string(eLog)); + } + + glValidateProgram(shaderID); + glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result); + + if (!result) { + glGetProgramInfoLog(shaderID, sizeof(eLog), nullptr, eLog); + throw std::runtime_error("Failed to validate shader program. Error:\n" + std::string(eLog)); + } } void Shader::addShader(GLuint program, const std::string& shaderCode, GLenum shaderType) { - GLuint shader = glCreateShader(shaderType); - - const GLchar* shaderCodeCStr = shaderCode.data(); - int shaderLength = static_cast(shaderCode.length()); - - glShaderSource(shader, 1, &shaderCodeCStr, &shaderLength); - glCompileShader(shader); - - GLint result = 0; - GLchar eLog[1024] = { 0 }; - - glGetShaderiv(shader, GL_COMPILE_STATUS, &result); - - if (!result) { - glGetShaderInfoLog(shader, sizeof(eLog), nullptr, eLog); - std::string shaderTypeName = (shaderType == GL_VERTEX_SHADER) ? "vertex" : (shaderType == GL_FRAGMENT_SHADER) ? "fragment" : "geometry"; - throw std::runtime_error("Failed to compile the " + shaderTypeName + " shader. Error:\n" + eLog); - } - - glAttachShader(program, shader); + GLuint shader = glCreateShader(shaderType); + + const GLchar* shaderCodeCStr = shaderCode.data(); + int shaderLength = static_cast(shaderCode.length()); + + glShaderSource(shader, 1, &shaderCodeCStr, &shaderLength); + glCompileShader(shader); + + GLint result = 0; + GLchar eLog[1024] = { 0 }; + + glGetShaderiv(shader, GL_COMPILE_STATUS, &result); + + if (!result) { + glGetShaderInfoLog(shader, sizeof(eLog), nullptr, eLog); + std::string shaderTypeName = (shaderType == GL_VERTEX_SHADER) ? "vertex" : (shaderType == GL_FRAGMENT_SHADER) + ? "fragment" : "geometry"; + throw std::runtime_error("Failed to compile the " + shaderTypeName + " shader. Error:\n" + eLog); + } + + glAttachShader(program, shader); } Shader::~Shader() { - cleanup(); + cleanup(); } void Shader::cleanup() { - if (shaderID != 0) glDeleteProgram(shaderID); + if (shaderID != 0) glDeleteProgram(shaderID); } void Shader::checkActive() { - int cProgram; - glGetIntegerv(GL_CURRENT_PROGRAM, &cProgram); - if (cProgram != shaderID) throw std::runtime_error("Attempted to set a uniform on an inactive shader!"); + int cProgram; + glGetIntegerv(GL_CURRENT_PROGRAM, &cProgram); + if (cProgram != shaderID) throw std::runtime_error("Attempted to set a uniform on an inactive shader!"); } \ No newline at end of file diff --git a/src/client/graph/shader/Shader.h b/src/client/graph/shader/Shader.h index 028b4002..32629359 100644 --- a/src/client/graph/shader/Shader.h +++ b/src/client/graph/shader/Shader.h @@ -10,38 +10,48 @@ #include class Shader { -public: - void createFromString(std::string& vertexSource, std::string& fragmentSource, const std::string& geoSource = ""); - void createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile = ""); - - virtual void postCreate() {}; - - int get(const std::string &name); - - void use(); - static void clearShader(); - - void set(int loc, unsigned int val); - void set(int loc, int val); - void set(int loc, float val); - void set(int loc, glm::vec3 val); - void set(int loc, glm::vec4 val); - void set(int loc, glm::mat4 val); - - void setArr(int loc, unsigned int count, glm::mat4 &start); - - void cleanup(); - - ~Shader(); - -private: - static std::string readFile(const std::string& fileLocation); - - void compileShader(const std::string& vertexSource, const std::string& fragmentSource, const std::string& geoSource = ""); - static void addShader(unsigned int program, const std::string& shaderCode, GLenum shaderType); - - void checkActive(); - - unsigned int shaderID = 0; + public: + void createFromString(std::string& vertexSource, std::string& fragmentSource, const std::string& geoSource = ""); + + void + createFromFile(const std::string& vertexFile, const std::string& fragmentFile, const std::string& geoFile = ""); + + virtual void postCreate() {}; + + int get(const std::string& name); + + void use(); + + static void clearShader(); + + void set(int loc, unsigned int val); + + void set(int loc, int val); + + void set(int loc, float val); + + void set(int loc, glm::vec3 val); + + void set(int loc, glm::vec4 val); + + void set(int loc, glm::mat4 val); + + void setArr(int loc, unsigned int count, glm::mat4& start); + + void cleanup(); + + ~Shader(); + + private: + static std::string readFile(const std::string& fileLocation); + + void compileShader(const std::string& vertexSource, const std::string& fragmentSource, + const std::string& geoSource = ""); + + static void addShader(unsigned int program, const std::string& shaderCode, GLenum shaderType); + + void checkActive(); + + unsigned int shaderID = 0; }; diff --git a/src/client/graph/shader/WorldGeometryShader.cpp b/src/client/graph/shader/WorldGeometryShader.cpp index 0af04a2a..32b13ba5 100644 --- a/src/client/graph/shader/WorldGeometryShader.cpp +++ b/src/client/graph/shader/WorldGeometryShader.cpp @@ -7,37 +7,42 @@ #include "WorldGeometryShader.h" WorldGeometryShader::WorldGeometryShader(glm::ivec2 windowSize, float bufferScale) : Shader(), - windowSize(windowSize), - bufferScale(bufferScale), - swayData(16 * 4 * 16) { - - swayNoise.SetFrequency(0.20); - swayNoise.SetOctaveCount(2); + windowSize(windowSize), + bufferScale(bufferScale), + swayData(16 * 4 * 16) { + + swayNoise.SetFrequency(0.20); + swayNoise.SetOctaveCount(2); } void WorldGeometryShader::postCreate() { - swayTex.loadFromBytes(&swayData[0], 16, 16, GL_LINEAR, GL_MIRRORED_REPEAT); - - uniforms.proj = get("projection"); - uniforms.model = get("model"); - uniforms.view = get("view"); - - uniforms.swaySampler = get("swayTex"); - uniforms.time = get("time"); - - use(); - set(uniforms.swaySampler, 1); + swayTex.loadFromBytes(&swayData[0], 16, 16, GL_LINEAR, GL_MIRRORED_REPEAT); + + uniforms.proj = get("projection"); + uniforms.model = get("model"); + uniforms.view = get("view"); + + uniforms.swaySampler = get("swayTex"); + uniforms.time = get("time"); + + use(); + set(uniforms.swaySampler, 1); } void WorldGeometryShader::windowResized(glm::ivec2 windowSize) { - this->windowSize = windowSize; + this->windowSize = windowSize; } + void WorldGeometryShader::updateSwayMap(double delta) { - swayOffset += delta * 2.8; - for (int i = 0; i < 16 * 16; i++) { - swayData[i*4] = static_cast((fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset))) + 1) / 2.f * 255.f); - swayData[i*4+1] = static_cast((fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 50))) + 1) / 2.f * 255.f); - swayData[i*4+2] = static_cast((fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 100))) + 1) / 2.f * 255.f); - } - swayTex.updateTexture(0, 0, 16, 16, &swayData[0]); + swayOffset += delta * 2.8; + for (int i = 0; i < 16 * 16; i++) { + swayData[i * 4] = static_cast( + (fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset))) + 1) / 2.f * 255.f); + swayData[i * 4 + 1] = static_cast( + (fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 50))) + 1) / 2.f * 255.f); + swayData[i * 4 + 2] = static_cast( + (fmax(-1, fmin(1, swayNoise.GetValue((i / 16) / 3.f, (i % 16) / 3.f, swayOffset + 100))) + 1) / 2.f * + 255.f); + } + swayTex.updateTexture(0, 0, 16, 16, &swayData[0]); } \ No newline at end of file diff --git a/src/client/graph/shader/WorldGeometryShader.h b/src/client/graph/shader/WorldGeometryShader.h index 24e06024..b09ab88d 100644 --- a/src/client/graph/shader/WorldGeometryShader.h +++ b/src/client/graph/shader/WorldGeometryShader.h @@ -12,30 +12,32 @@ #include "../Texture.h" class WorldGeometryShader : public Shader { -public: - explicit WorldGeometryShader(glm::ivec2 windowSize, float bufferScale); - void postCreate() override; - - void windowResized(glm::ivec2 windowSize); - void updateSwayMap(double delta); - - struct Uniforms { - GLint proj; - GLint model; - GLint view; - - GLint swaySampler; - - GLint time; - }; - - Uniforms uniforms {}; - - Texture swayTex; - double swayOffset = 0; - noise::module::Perlin swayNoise; - std::vector swayData {}; - - glm::ivec2 windowSize {}; - float bufferScale = 1; + public: + explicit WorldGeometryShader(glm::ivec2 windowSize, float bufferScale); + + void postCreate() override; + + void windowResized(glm::ivec2 windowSize); + + void updateSwayMap(double delta); + + struct Uniforms { + GLint proj; + GLint model; + GLint view; + + GLint swaySampler; + + GLint time; + }; + + Uniforms uniforms{}; + + Texture swayTex; + double swayOffset = 0; + noise::module::Perlin swayNoise; + std::vector swayData{}; + + glm::ivec2 windowSize{}; + float bufferScale = 1; }; diff --git a/src/client/gui/DebugGui.cpp b/src/client/gui/DebugGui.cpp index f964ce9e..2202868c 100644 --- a/src/client/gui/DebugGui.cpp +++ b/src/client/gui/DebugGui.cpp @@ -13,164 +13,171 @@ #include "client/gui/compound/GuiLabelledGraph.h" DebugGui::DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world) : - game(game), - world(world) { - - auto fontRef = game.l()->textures["font"]; - auto fpsHistogramRef = game.l()->textures["histogram"]; - auto genericHistogramRef = game.l()->textures["histogram_white"]; - - Font f(game.l()->textures, fontRef); - - auto crosshairText = std::make_shared("crosshairText"); - crosshairText->create({2, 2}, {}, {0.2, 0.2, 0.2, 0.5}, {1, 1, 1, 1}, f); - add(crosshairText); - - auto dataText = std::make_shared("dataText"); - dataText->create({2, 2}, {}, {0.2, 0.2, 0.2, 0.5}, {1, 1, 1, 1}, f); - add(dataText); - - auto interpGraph = std::make_shared("interpGraph"); - interpGraph->create({244, 64}, {}, "Interp", 120, 256, genericHistogramRef, f); - add(interpGraph); - - auto meshGraph = std::make_shared("meshGraph"); - meshGraph->create({244, 64}, {}, "Mesh", 120, 32, genericHistogramRef, f); - add(meshGraph); - - auto genGraph = std::make_shared("genGraph"); - genGraph->create({244, 64}, {}, "Gen", 120, 16, genericHistogramRef, f); - add(genGraph); - - auto packetGraph = std::make_shared("packetGraph"); - packetGraph->create({244, 64}, {}, "Packets", 120, 32, genericHistogramRef, f); - add(packetGraph); - - auto fpsGraph = std::make_shared("fpsGraph"); - fpsGraph->create({244, 64}, {}, "FPS", 120, 60, fpsHistogramRef, f); - add(fpsGraph); - - auto drawsGraph = std::make_shared("drawsGraph"); - drawsGraph->create({244, 64}, {}, "Draw Calls", 120, 0, genericHistogramRef, f); - add(drawsGraph); - - auto gpuGraph = std::make_shared("gpuGraph"); - gpuGraph->create({244, 64}, {}, "GPU", 120, 1, genericHistogramRef, f); - add(gpuGraph); - - positionElements(bufferSize); + game(game), + world(world) { + + auto fontRef = game.l()->textures["font"]; + auto fpsHistogramRef = game.l()->textures["histogram"]; + auto genericHistogramRef = game.l()->textures["histogram_white"]; + + Font f(game.l()->textures, fontRef); + + auto crosshairText = std::make_shared("crosshairText"); + crosshairText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f); + add(crosshairText); + + auto dataText = std::make_shared("dataText"); + dataText->create({ 2, 2 }, {}, { 0.2, 0.2, 0.2, 0.5 }, { 1, 1, 1, 1 }, f); + add(dataText); + + auto interpGraph = std::make_shared("interpGraph"); + interpGraph->create({ 244, 64 }, {}, "Interp", 120, 256, genericHistogramRef, f); + add(interpGraph); + + auto meshGraph = std::make_shared("meshGraph"); + meshGraph->create({ 244, 64 }, {}, "Mesh", 120, 32, genericHistogramRef, f); + add(meshGraph); + + auto genGraph = std::make_shared("genGraph"); + genGraph->create({ 244, 64 }, {}, "Gen", 120, 16, genericHistogramRef, f); + add(genGraph); + + auto packetGraph = std::make_shared("packetGraph"); + packetGraph->create({ 244, 64 }, {}, "Packets", 120, 32, genericHistogramRef, f); + add(packetGraph); + + auto fpsGraph = std::make_shared("fpsGraph"); + fpsGraph->create({ 244, 64 }, {}, "FPS", 120, 60, fpsHistogramRef, f); + add(fpsGraph); + + auto drawsGraph = std::make_shared("drawsGraph"); + drawsGraph->create({ 244, 64 }, {}, "Draw Calls", 120, 0, genericHistogramRef, f); + add(drawsGraph); + + auto gpuGraph = std::make_shared("gpuGraph"); + gpuGraph->create({ 244, 64 }, {}, "GPU", 120, 1, genericHistogramRef, f); + add(gpuGraph); + + positionElements(bufferSize); } void DebugGui::positionElements(glm::vec2 bufferSize) { - auto bufferWidth = static_cast(bufferSize.x); - auto bufferHeight = static_cast(bufferSize.y); - - get("crosshairText")->setPos({bufferWidth / 2 + 22, bufferHeight / 2 - 7}); - get("dataText")->setPos({10, 10}); - - get("genGraph")->setPos({bufferWidth - 254, bufferHeight - 70 - 160}); - get("packetGraph")->setPos({bufferWidth - 254, bufferHeight - 70 - 240}); - get("meshGraph")->setPos({bufferWidth - 254, bufferHeight - 70 - 80}); - get("interpGraph")->setPos({bufferWidth - 254, bufferHeight - 70}); - - get("fpsGraph")->setPos({bufferWidth - 254, 10}); - get("drawsGraph")->setPos({bufferWidth - 254, 90}); - get("gpuGraph")->setPos({bufferWidth - 254, 90 + 80}); + auto bufferWidth = static_cast(bufferSize.x); + auto bufferHeight = static_cast(bufferSize.y); + + get("crosshairText")->setPos({ bufferWidth / 2 + 22, bufferHeight / 2 - 7 }); + get("dataText")->setPos({ 10, 10 }); + + get("genGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 - 160 }); + get("packetGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 - 240 }); + get("meshGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 - 80 }); + get("interpGraph")->setPos({ bufferWidth - 254, bufferHeight - 70 }); + + get("fpsGraph")->setPos({ bufferWidth - 254, 10 }); + get("drawsGraph")->setPos({ bufferWidth - 254, 90 }); + get("gpuGraph")->setPos({ bufferWidth - 254, 90 + 80 }); } -void DebugGui::update(std::shared_ptr player, double fps, int /*chunks*/, int drawCalls, int ssGen, int ssPack) { - Target target = player->getTarget(); - - auto& onBiomeDef = game->getBiomes().biomeFromId(world.l()->getActiveDimension()->getBiome(glm::floor(player->getPos()))); - auto& targetedBlockDef = game->getDefs().blockFromId(world.l()->getActiveDimension()->getBlock(target.pos)); - - /* Top-right Graphs */ { - get("fpsGraph")->pushValue(static_cast(fps)); - get("drawsGraph")->pushValue(drawCalls); - - int videoMemAvail, videoMemTotal; - - glGetIntegerv(0x9048, &videoMemTotal); - glGetIntegerv(0x9049, &videoMemAvail); - - get("gpuGraph")->pushValue(static_cast(std::round( - (videoMemTotal - videoMemAvail) / static_cast(videoMemTotal) * 100.0)) / 100.0f); - } - - /* Bottom-right Graphs */ { - get("meshGraph")->pushValue(world.l()->lastMeshUpdates); - get("interpGraph")->pushValue(world.l()->mapBlocksInterpolated); - get("genGraph")->pushValue(static_cast(ssGen)); - get("packetGraph")->pushValue(static_cast(ssPack)); - } - - /* Top-left Data */ { - glm::vec3 playerPos = glm::floor(player->getPos()); - glm::vec3 chunkPos = Space::Chunk::world::fromBlock(playerPos); - glm::vec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos); - glm::vec3 regionPos = Space::Region::world::fromChunk(chunkPos); - - glm::vec3 posOffsetFromChunk = Space::Block::relative::toChunk(playerPos); - glm::vec3 posOffsetFromBlock = Space::Block::relative::toMapBlock(playerPos); - glm::vec3 posOffsetFromRegion = Space::Block::relative::toRegion(playerPos); - - std::ostringstream str; - - using namespace Util; - - str << "Dimension: " << world.l()->getActiveDimension()->getIdentifier() - << " [" << world.l()->getActiveDimension()->getInd() << "]" << std::endl << std::endl; - - str << "Pos: " << vecToString(playerPos) << " (" << floatVecToString(player->getPos()) << ")" << std::endl; - str << "Vel: " << floatVecToString(player->getVel()) << std::endl; - str << "Yaw: " << floatToString(player->getYaw()) << ", "; - str << "Pitch: " << floatToString(player->getPitch()) << std::endl << std::endl; - - str << "C: " << vecToString(posOffsetFromChunk) << " [" << vecToString(chunkPos) << "]" << std::endl; - str << "M: " << vecToString(posOffsetFromBlock) << " [" << vecToString(mapBlockPos) << "]" << std::endl; - str << "R: " << vecToString(posOffsetFromRegion) << " [" << vecToString(regionPos) << "]" << std::endl << std::endl; - - str << "Texture Slots: " << game.l()->textures.textureSlotsUsed << " / " << game.l()->textures.maxTextureSlots - << " (" << round(game.l()->textures.textureSlotsUsed / static_cast(game.l()->textures.maxTextureSlots) * 100) << "%)" << std::endl << std::endl; - - str << "Biome: " << onBiomeDef.identifier << " [" << onBiomeDef.index << "]" << std::endl << std::endl; - - if (target.type == Target::Type::BLOCK) { - std::string face = - target.face == EVec::TOP ? "TOP" : - target.face == EVec::BOTTOM ? "BOTTOM" : - target.face == EVec::LEFT ? "LEFT" : - target.face == EVec::RIGHT ? "RIGHT" : - target.face == EVec::FRONT ? "FRONT" : - target.face == EVec::BACK ? "BACK" : - "NONE" ; - - str << "Pointing At: " << targetedBlockDef.identifier << " [" << targetedBlockDef.index << "]" << std::endl; - str << "Pointed Position: " << vecToString(target.pos) << std::endl; - str << "Pointed Face: " << face << std::endl; - } - else { - str << "No Target"; - } - - get("dataText")->setText(str.str()); - } - - /* Crosshair Text */ { - if (target.type == Target::Type::BLOCK) get("crosshairText")->setText(targetedBlockDef.name + " (" + - targetedBlockDef.identifier + ") [" + std::to_string(targetedBlockDef.index) + "]"); - else get("crosshairText")->setText(""); - } +void DebugGui::update(std::shared_ptr player, double fps, int /*chunks*/, int drawCalls, int ssGen, + int ssPack) { + Target target = player->getTarget(); + + auto& onBiomeDef = game->getBiomes().biomeFromId( + world.l()->getActiveDimension()->getBiome(glm::floor(player->getPos()))); + auto& targetedBlockDef = game->getDefs().blockFromId(world.l()->getActiveDimension()->getBlock(target.pos)); + + /* Top-right Graphs */ { + get("fpsGraph")->pushValue(static_cast(fps)); + get("drawsGraph")->pushValue(drawCalls); + + int videoMemAvail, videoMemTotal; + + glGetIntegerv(0x9048, &videoMemTotal); + glGetIntegerv(0x9049, &videoMemAvail); + + get("gpuGraph")->pushValue(static_cast(std::round( + (videoMemTotal - videoMemAvail) / static_cast(videoMemTotal) * 100.0)) / 100.0f); + } + + /* Bottom-right Graphs */ { + get("meshGraph")->pushValue(world.l()->lastMeshUpdates); + get("interpGraph")->pushValue(world.l()->mapBlocksInterpolated); + get("genGraph")->pushValue(static_cast(ssGen)); + get("packetGraph")->pushValue(static_cast(ssPack)); + } + + /* Top-left Data */ { + glm::vec3 playerPos = glm::floor(player->getPos()); + glm::vec3 chunkPos = Space::Chunk::world::fromBlock(playerPos); + glm::vec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos); + glm::vec3 regionPos = Space::Region::world::fromChunk(chunkPos); + + glm::vec3 posOffsetFromChunk = Space::Block::relative::toChunk(playerPos); + glm::vec3 posOffsetFromBlock = Space::Block::relative::toMapBlock(playerPos); + glm::vec3 posOffsetFromRegion = Space::Block::relative::toRegion(playerPos); + + std::ostringstream str; + + using namespace Util; + + str << "Dimension: " << world.l()->getActiveDimension()->getIdentifier() + << " [" << world.l()->getActiveDimension()->getInd() << "]" << std::endl << std::endl; + + str << "Pos: " << vecToString(playerPos) << " (" << floatVecToString(player->getPos()) << ")" << std::endl; + str << "Vel: " << floatVecToString(player->getVel()) << std::endl; + str << "Yaw: " << floatToString(player->getYaw()) << ", "; + str << "Pitch: " << floatToString(player->getPitch()) << std::endl << std::endl; + + str << "C: " << vecToString(posOffsetFromChunk) << " [" << vecToString(chunkPos) << "]" << std::endl; + str << "M: " << vecToString(posOffsetFromBlock) << " [" << vecToString(mapBlockPos) << "]" << std::endl; + str << "R: " << vecToString(posOffsetFromRegion) << " [" << vecToString(regionPos) << "]" << std::endl + << std::endl; + + str << "Texture Slots: " << game.l()->textures.textureSlotsUsed << " / " << game.l()->textures.maxTextureSlots + << " (" + << round(game.l()->textures.textureSlotsUsed / static_cast(game.l()->textures.maxTextureSlots) * 100) + << "%)" << std::endl << std::endl; + + str << "Biome: " << onBiomeDef.identifier << " [" << onBiomeDef.index << "]" << std::endl << std::endl; + + if (target.type == Target::Type::BLOCK) { + std::string face = + target.face == EVec::TOP ? "TOP" : + target.face == EVec::BOTTOM ? "BOTTOM" : + target.face == EVec::LEFT ? "LEFT" : + target.face == EVec::RIGHT ? "RIGHT" : + target.face == EVec::FRONT ? "FRONT" : + target.face == EVec::BACK ? "BACK" : + "NONE"; + + str << "Pointing At: " << targetedBlockDef.identifier << " [" << targetedBlockDef.index << "]" << std::endl; + str << "Pointed Position: " << vecToString(target.pos) << std::endl; + str << "Pointed Face: " << face << std::endl; + } + else { + str << "No Target"; + } + + get("dataText")->setText(str.str()); + } + + /* Crosshair Text */ { + if (target.type == Target::Type::BLOCK) + get("crosshairText")->setText(targetedBlockDef.name + " (" + + targetedBlockDef.identifier + ") [" + + std::to_string(targetedBlockDef.index) + "]"); + else get("crosshairText")->setText(""); + } } void DebugGui::bufferResized(glm::vec2 bufferSize) { - positionElements(bufferSize); + positionElements(bufferSize); } // 0 = All, 1 = None, 2 = FPS void DebugGui::changeVisibilityState(int state) { - displayMode = state; - - setVisible(displayMode == 0); - get("fpsGraph")->setVisible(displayMode != 1); + displayMode = state; + + setVisible(displayMode == 0); + get("fpsGraph")->setVisible(displayMode != 1); } diff --git a/src/client/gui/DebugGui.h b/src/client/gui/DebugGui.h index 53902b77..692c5a8f 100644 --- a/src/client/gui/DebugGui.h +++ b/src/client/gui/DebugGui.h @@ -9,21 +9,26 @@ #include "util/CovariantPtr.h" class LocalPlayer; + class LocalSubgame; + class LocalWorld; class DebugGui : public GuiContainer { -public: - DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world); - - void bufferResized(glm::vec2 bufferSize); - void changeVisibilityState(int state); - void positionElements(glm::vec2 bufferSize); - - void update(std::shared_ptr player, double fps, int chunks, int drawCalls, int ssGen, int ssPack); -private: - int displayMode; - - WorldPtr world; - SubgamePtr game; + public: + DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world); + + void bufferResized(glm::vec2 bufferSize); + + void changeVisibilityState(int state); + + void positionElements(glm::vec2 bufferSize); + + void update(std::shared_ptr player, double fps, int chunks, int drawCalls, int ssGen, int ssPack); + + private: + int displayMode; + + WorldPtr world; + SubgamePtr game; }; diff --git a/src/client/gui/GameGui.cpp b/src/client/gui/GameGui.cpp index bfb2e1c7..155d642f 100644 --- a/src/client/gui/GameGui.cpp +++ b/src/client/gui/GameGui.cpp @@ -7,76 +7,76 @@ #include "../graph/Renderer.h" GameGui::GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer) : - refs(refs), - defs(defs), - win(bufferSize), - renderer(renderer), - - hudBuilder(refs, defs, hudLuaRoot), - menuBuilder(refs, defs, menuLuaRoot) { - - hudRoot->add(hudLuaRoot); - menuRoot->add(menuLuaRoot); - - handList->create({3, 3}, {}, {}, refs.l()->getCursorList(), refs.l()->getCursorList(), defs); - menuRoot->add(handList); + refs(refs), + defs(defs), + win(bufferSize), + renderer(renderer), + + hudBuilder(refs, defs, hudLuaRoot), + menuBuilder(refs, defs, menuLuaRoot) { + + hudRoot->add(hudLuaRoot); + menuRoot->add(menuLuaRoot); + + handList->create({ 3, 3 }, {}, {}, refs.l()->getCursorList(), refs.l()->getCursorList(), defs); + menuRoot->add(handList); } void GameGui::update(double delta) { - menuRoot->update(delta); - hudRoot->update(delta); - - hudBuilder.update(); - menuBuilder.update(); - - handList->setPos((renderer.window.input.mousePos() - glm::ivec2(24)) / 3 * 3); - menuRoot->handleMouseInput(renderer.window); + menuRoot->update(delta); + hudRoot->update(delta); + + hudBuilder.update(); + menuBuilder.update(); + + handList->setPos((renderer.window.input.mousePos() - glm::ivec2(24)) / 3 * 3); + menuRoot->handleMouseInput(renderer.window); } void GameGui::winResized(glm::ivec2 win) { - this->win = win; - menuBuilder.build(win); - hudBuilder.build(win); + this->win = win; + menuBuilder.build(win); + hudBuilder.build(win); } void GameGui::showMenu(std::shared_ptr root) { - menuBuilder.setGuiRoot(root); - menuBuilder.build(win); - inMenu = true; + menuBuilder.setGuiRoot(root); + menuBuilder.build(win); + inMenu = true; } void GameGui::closeMenu() { - menuBuilder.clear(); - inMenu = false; + menuBuilder.clear(); + inMenu = false; } const bool GameGui::isInMenu() const { - return inMenu; + return inMenu; } void GameGui::setHud(std::shared_ptr hud) { - this->hudRootElem = hud; - hudBuilder.setGuiRoot(hud); - hudBuilder.build(win); + this->hudRootElem = hud; + hudBuilder.setGuiRoot(hud); + hudBuilder.build(win); } std::shared_ptr GameGui::getHud() { - return hudRootElem; + return hudRootElem; } void GameGui::setVisible(bool visible) { - menuRoot->setVisible(visible); - hudRoot->setVisible(visible); + menuRoot->setVisible(visible); + hudRoot->setVisible(visible); } bool GameGui::isVisible() { - return menuRoot->isVisible(); + return menuRoot->isVisible(); } -void GameGui::drawHud(Renderer &renderer) { - hudRoot->draw(renderer); +void GameGui::drawHud(Renderer& renderer) { + hudRoot->draw(renderer); } -void GameGui::drawMenu(Renderer &renderer) { - menuRoot->draw(renderer); +void GameGui::drawMenu(Renderer& renderer) { + menuRoot->draw(renderer); } \ No newline at end of file diff --git a/src/client/gui/GameGui.h b/src/client/gui/GameGui.h index 2e6c5939..daa46a16 100644 --- a/src/client/gui/GameGui.h +++ b/src/client/gui/GameGui.h @@ -8,41 +8,49 @@ #include "client/gui/compound/GuiInventoryList.h" class GameGui { -public: - explicit GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer); - void winResized(glm::ivec2 win); - void update(double delta); - - void setVisible(bool visible); - bool isVisible(); - - void showMenu(std::shared_ptr root); - void closeMenu(); - const bool isInMenu() const; - - void setHud(std::shared_ptr hud); - std::shared_ptr getHud(); - - void drawHud(Renderer& renderer); - void drawMenu(Renderer& renderer); -private: - SubgamePtr defs; - Renderer& renderer; - - glm::ivec2 win {}; - bool inMenu = false; - - std::shared_ptr hudRootElem = nullptr; - - std::shared_ptr menuRoot = std::make_shared("menuRoot"); - std::shared_ptr menuLuaRoot = std::make_shared("menuLuaRoot"); - GameGuiBuilder menuBuilder; - std::shared_ptr hudRoot = std::make_shared("hudRoot"); - std::shared_ptr hudLuaRoot = std::make_shared("hudLuaRoot"); - GameGuiBuilder hudBuilder; - - std::shared_ptr handList = std::make_shared("hand"); - - InventoryRefsPtr refs; + public: + explicit GameGui(InventoryRefsPtr refs, glm::vec2 bufferSize, SubgamePtr defs, Renderer& renderer); + + void winResized(glm::ivec2 win); + + void update(double delta); + + void setVisible(bool visible); + + bool isVisible(); + + void showMenu(std::shared_ptr root); + + void closeMenu(); + + const bool isInMenu() const; + + void setHud(std::shared_ptr hud); + + std::shared_ptr getHud(); + + void drawHud(Renderer& renderer); + + void drawMenu(Renderer& renderer); + + private: + SubgamePtr defs; + Renderer& renderer; + + glm::ivec2 win{}; + bool inMenu = false; + + std::shared_ptr hudRootElem = nullptr; + + std::shared_ptr menuRoot = std::make_shared("menuRoot"); + std::shared_ptr menuLuaRoot = std::make_shared("menuLuaRoot"); + GameGuiBuilder menuBuilder; + std::shared_ptr hudRoot = std::make_shared("hudRoot"); + std::shared_ptr hudLuaRoot = std::make_shared("hudLuaRoot"); + GameGuiBuilder hudBuilder; + + std::shared_ptr handList = std::make_shared("hand"); + + InventoryRefsPtr refs; }; diff --git a/src/client/gui/GameGuiBuilder.cpp b/src/client/gui/GameGuiBuilder.cpp index f4b0264e..9b4d5f6a 100644 --- a/src/client/gui/GameGuiBuilder.cpp +++ b/src/client/gui/GameGuiBuilder.cpp @@ -8,20 +8,20 @@ #include "client/gui/compound/GuiInventoryList.h" std::shared_ptr GameGuiBuilder::createComponent(LuaGuiElement& elem, glm::ivec2 bounds) { - auto c = GuiBuilder::createComponent(elem, bounds); - if (c != nullptr) return c; - - switch (Util::hash(elem.type.c_str())) { - default: break; - case Util::hash("InventoryList"): { - c = GuiInventoryList::fromSerialized(elem, defs, bounds, refs); - break; - } - } - - if (!c) return nullptr; - - elem.updateFunction = std::bind(&GameGuiBuilder::elementUpdated, this); + auto c = GuiBuilder::createComponent(elem, bounds); + if (c != nullptr) return c; + + switch (Util::hash(elem.type.c_str())) { + default: break; + case Util::hash("InventoryList"): { + c = GuiInventoryList::fromSerialized(elem, defs, bounds, refs); + break; + } + } + + if (!c) return nullptr; + + elem.updateFunction = std::bind(&GameGuiBuilder::elementUpdated, this); // if (elem.callbacks.count("primary")) c->setCallback(GuiComponent::CallbackType::PRIMARY, [=](bool b, glm::vec2 v) { // elem.callbacks.at("primary")(b, LuaParser::luaVec(elem.callbacks.at("primary").lua_state(), {v.x, v.y, 0})); }); @@ -31,6 +31,6 @@ std::shared_ptr GameGuiBuilder::createComponent(LuaGuiElement& ele // // if (elem.callbacks.count("hover")) c->setCallback(GuiComponent::CallbackType::HOVER, [=](bool b, glm::vec2 v) { // elem.callbacks.at("hover")(b, LuaParser::luaVec(elem.callbacks.at("hover").lua_state(), {v.x, v.y, 0})); }); - - return c; + + return c; } diff --git a/src/client/gui/GameGuiBuilder.h b/src/client/gui/GameGuiBuilder.h index 63c9866e..53101323 100644 --- a/src/client/gui/GameGuiBuilder.h +++ b/src/client/gui/GameGuiBuilder.h @@ -10,12 +10,13 @@ #include "world/inv/LocalInventoryRefs.h" class GameGuiBuilder : public GuiBuilder { -public: - GameGuiBuilder(InventoryRefsPtr refs, SubgamePtr defs, std::shared_ptr root) : - defs(defs), refs(refs), GuiBuilder(defs.l()->textures, defs.l()->models, root) {}; - - std::shared_ptr createComponent(LuaGuiElement& elem, glm::ivec2 bounds) override; -private: - InventoryRefsPtr refs; - SubgamePtr defs; + public: + GameGuiBuilder(InventoryRefsPtr refs, SubgamePtr defs, std::shared_ptr root) : + defs(defs), refs(refs), GuiBuilder(defs.l()->textures, defs.l()->models, root) {}; + + std::shared_ptr createComponent(LuaGuiElement& elem, glm::ivec2 bounds) override; + + private: + InventoryRefsPtr refs; + SubgamePtr defs; }; diff --git a/src/client/gui/GuiBuilder.cpp b/src/client/gui/GuiBuilder.cpp index 89965dd9..1d12f24d 100644 --- a/src/client/gui/GuiBuilder.cpp +++ b/src/client/gui/GuiBuilder.cpp @@ -12,68 +12,64 @@ #include "client/gui/compound/GuiImageButton.h" GuiBuilder::GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr root) : - textures(textures), models(models), root(root) {} + textures(textures), models(models), root(root) {} void GuiBuilder::setGuiRoot(std::shared_ptr menu) { - elements = menu; + elements = menu; } void GuiBuilder::update() { - if (dirty) { - build(); - dirty = false; - } + if (dirty) { + build(); + dirty = false; + } } void GuiBuilder::build(glm::ivec2 winBounds) { - clear(false); - if (winBounds != glm::ivec2 {}) this->winBounds = winBounds; - if (elements) create(*elements, root, this->winBounds); + clear(false); + if (winBounds != glm::ivec2{}) this->winBounds = winBounds; + if (elements) create(*elements, root, this->winBounds); } void GuiBuilder::clear(bool deleteRoot) { - clearCallbacks(root); - root->empty(); - if (deleteRoot) elements = nullptr; + clearCallbacks(root); + root->empty(); + if (deleteRoot) elements = nullptr; } void GuiBuilder::create(LuaGuiElement& element, std::shared_ptr parent, glm::ivec2 bounds) { - if (element.get_or("visible", true)) { - auto component = createComponent(element, bounds); - if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key); - parent->add(component); - for (auto &child : element.children) create(*child, component, component->getScale()); - } + if (element.get_or("visible", true)) { + auto component = createComponent(element, bounds); + if (!component) throw std::runtime_error("GuiBuilder failed to create component: " + element.key); + parent->add(component); + for (auto& child : element.children) create(*child, component, component->getScale()); + } } std::shared_ptr GuiBuilder::createComponent(LuaGuiElement& elem, glm::ivec2 bounds) { - std::shared_ptr c = nullptr; - - switch (Util::hash(elem.type.c_str())) { - default: break; - case Util::hash("Body"): { - auto body = GuiRect::fromSerialized(elem, textures, bounds); - body->setScale(bounds); - c = body; - break; - } - case Util::hash("Rect"): - c = GuiRect::fromSerialized(elem, textures, bounds); - break; - case Util::hash("Button"): - c = GuiImageButton::fromSerialized(elem, textures, bounds); - break; - case Util::hash("Text"): - c = GuiText::fromSerialized(elem, textures, bounds); - break; - case Util::hash("Model"): - c = GuiModel::fromSerialized(elem, textures, models, bounds); - break; - } - - if (!c) return nullptr; - - elem.updateFunction = std::bind(&GuiBuilder::elementUpdated, this); + std::shared_ptr c = nullptr; + + switch (Util::hash(elem.type.c_str())) { + default: break; + case Util::hash("Body"): { + auto body = GuiRect::fromSerialized(elem, textures, bounds); + body->setScale(bounds); + c = body; + break; + } + case Util::hash("Rect"):c = GuiRect::fromSerialized(elem, textures, bounds); + break; + case Util::hash("Button"):c = GuiImageButton::fromSerialized(elem, textures, bounds); + break; + case Util::hash("Text"):c = GuiText::fromSerialized(elem, textures, bounds); + break; + case Util::hash("Model"):c = GuiModel::fromSerialized(elem, textures, models, bounds); + break; + } + + if (!c) return nullptr; + + elem.updateFunction = std::bind(&GuiBuilder::elementUpdated, this); // if (elem.callbacks.count("primary")) c->setCallback(GuiComponent::CallbackType::PRIMARY, [=](bool b, glm::vec2 v) { // elem.callbacks.at("primary")(b, LuaParser::luaVec(elem.callbacks.at("primary").lua_state(), {v.x, v.y, 0})); }); @@ -83,22 +79,22 @@ std::shared_ptr GuiBuilder::createComponent(LuaGuiElement& elem, g // // if (elem.callbacks.count("hover")) c->setCallback(GuiComponent::CallbackType::HOVER, [=](bool b, glm::vec2 v) { // elem.callbacks.at("hover")(b, LuaParser::luaVec(elem.callbacks.at("hover").lua_state(), {v.x, v.y, 0})); }); - - return c; + + return c; } void GuiBuilder::clearCallbacks(std::shared_ptr component) { - component->setCallback(GuiComponent::CallbackType::PRIMARY, nullptr); - component->setCallback(GuiComponent::CallbackType::SECONDARY, nullptr); - component->setCallback(GuiComponent::CallbackType::HOVER, nullptr); - - for (auto& child : component->getChildren()) clearCallbacks(child); + component->setCallback(GuiComponent::CallbackType::PRIMARY, nullptr); + component->setCallback(GuiComponent::CallbackType::SECONDARY, nullptr); + component->setCallback(GuiComponent::CallbackType::HOVER, nullptr); + + for (auto& child : component->getChildren()) clearCallbacks(child); } void GuiBuilder::elementUpdated() { - dirty = true; + dirty = true; } GuiBuilder::~GuiBuilder() { - clear(); + clear(); } \ No newline at end of file diff --git a/src/client/gui/GuiBuilder.h b/src/client/gui/GuiBuilder.h index 96df5d32..6a0b783e 100644 --- a/src/client/gui/GuiBuilder.h +++ b/src/client/gui/GuiBuilder.h @@ -12,32 +12,41 @@ class GuiContainer; class GuiBuilder { -public: - struct ComponentCallbacks { GuiComponent::callback left {}, right {}, hover {}; }; - - GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr root); - void setGuiRoot(std::shared_ptr menu); - void update(); - void build(glm::ivec2 winBounds = {}); - void clear(bool deleteRoot = true); - - ~GuiBuilder(); -protected: - void create(LuaGuiElement& element, std::shared_ptr parent, glm::ivec2 bounds); - virtual std::shared_ptr createComponent(LuaGuiElement& elem, glm::ivec2 bounds); - static void clearCallbacks(std::shared_ptr component); - - void elementUpdated(); - - TextureAtlas& textures; - ModelStore& models; - - std::shared_ptr root = nullptr; - - std::shared_ptr elements = nullptr; - unsigned int keyInd = 0; - - bool dirty = false; - - glm::ivec2 winBounds {}; + public: + struct ComponentCallbacks { + GuiComponent::callback left{}, right{}, hover{}; + }; + + GuiBuilder(TextureAtlas& textures, ModelStore& models, std::shared_ptr root); + + void setGuiRoot(std::shared_ptr menu); + + void update(); + + void build(glm::ivec2 winBounds = {}); + + void clear(bool deleteRoot = true); + + ~GuiBuilder(); + + protected: + void create(LuaGuiElement& element, std::shared_ptr parent, glm::ivec2 bounds); + + virtual std::shared_ptr createComponent(LuaGuiElement& elem, glm::ivec2 bounds); + + static void clearCallbacks(std::shared_ptr component); + + void elementUpdated(); + + TextureAtlas& textures; + ModelStore& models; + + std::shared_ptr root = nullptr; + + std::shared_ptr elements = nullptr; + unsigned int keyInd = 0; + + bool dirty = false; + + glm::ivec2 winBounds{}; }; diff --git a/src/client/gui/GuiComponent.cpp b/src/client/gui/GuiComponent.cpp index 359f3d7c..8a34427c 100644 --- a/src/client/gui/GuiComponent.cpp +++ b/src/client/gui/GuiComponent.cpp @@ -9,174 +9,174 @@ #include "client/graph/Renderer.h" GuiComponent::GuiComponent(const std::string& key) : - key(key) {} + key(key) {} void GuiComponent::update(double delta) { - for (const auto& child : children) { - child->update(delta); - } + for (const auto& child : children) { + child->update(delta); + } } const std::string& GuiComponent::getKey() { - return key; + return key; } glm::ivec2 GuiComponent::getPos() { - return pos; + return pos; } void GuiComponent::setPos(glm::ivec2 pos) { - this->pos = pos; - - if (parent != nullptr) { - glm::vec3 parentPos = parent->entity.getPos(); - pos += glm::vec2 {parentPos.x, parentPos.y}; - pos += glm::vec2 {parent->getPadding().w, parent->getPadding().x}; - } - - entity.setPos({pos.x, pos.y, 0}); - - for (const auto& child : children) { - child->updatePos(); - } + this->pos = pos; + + if (parent != nullptr) { + glm::vec3 parentPos = parent->entity.getPos(); + pos += glm::vec2{ parentPos.x, parentPos.y }; + pos += glm::vec2{ parent->getPadding().w, parent->getPadding().x }; + } + + entity.setPos({ pos.x, pos.y, 0 }); + + for (const auto& child : children) { + child->updatePos(); + } } glm::vec2 GuiComponent::getScale() { - return scale; + return scale; } void GuiComponent::setScale(glm::vec2 scale) { - this->scale = scale; - entity.setScale({scale.x, scale.y, scale.x}); + this->scale = scale; + entity.setScale({ scale.x, scale.y, scale.x }); } glm::vec4 GuiComponent::getPadding() { - return padding; + return padding; } void GuiComponent::setPadding(glm::vec4 padding) { - this->padding = padding; + this->padding = padding; } void GuiComponent::setOverflows(bool overflows) { - this->overflows = overflows; + this->overflows = overflows; } void GuiComponent::setVisible(bool visible) { - Drawable::setVisible(visible); - entity.setVisible(visible); - for (const auto& child : children) { - child->setVisible(visible); - } + Drawable::setVisible(visible); + entity.setVisible(visible); + for (const auto& child : children) { + child->setVisible(visible); + } } void GuiComponent::setCallback(GuiComponent::CallbackType type, const callback& cb) { - callbacks[static_cast(type)] = cb; + callbacks[static_cast(type)] = cb; } -void GuiComponent::handleMouseInput(Window &window) { - auto mousePos = window.input.mousePos(); - - window.setCursorHand(mouseActivity(mousePos)); - if (window.input.mousePressed(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, true, mousePos); - if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, false, mousePos); - if (window.input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, true, mousePos); - if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, false, mousePos); +void GuiComponent::handleMouseInput(Window& window) { + auto mousePos = window.input.mousePos(); + + window.setCursorHand(mouseActivity(mousePos)); + if (window.input.mousePressed(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, true, mousePos); + if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_LEFT)) clickEvent(true, false, mousePos); + if (window.input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, true, mousePos); + if (window.input.mouseReleased(GLFW_MOUSE_BUTTON_RIGHT)) clickEvent(false, false, mousePos); } bool GuiComponent::mouseActivity(glm::ivec2 pos) { - bool isHovering = false; - for (auto& child : children) { - glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x); - if (child->mouseActivity(cp)) isHovering = true; - } - - auto& callback = callbacks[static_cast(CallbackType::HOVER)]; - - if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y) { - if (callback) { - callback(true, pos); - hovered = true; - return true; - } - return isHovering; - } - else { - if (callback) { - callback(false, pos); - hovered = false; - } - } - return isHovering; + bool isHovering = false; + for (auto& child : children) { + glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x); + if (child->mouseActivity(cp)) isHovering = true; + } + + auto& callback = callbacks[static_cast(CallbackType::HOVER)]; + + if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y) { + if (callback) { + callback(true, pos); + hovered = true; + return true; + } + return isHovering; + } + else { + if (callback) { + callback(false, pos); + hovered = false; + } + } + return isHovering; } std::shared_ptr GuiComponent::insert(unsigned int index, std::shared_ptr component) { - component->parent = this; - component->updatePos(); - children.insert(std::next(children.begin(), index), std::move(component)); - return component; + component->parent = this; + component->updatePos(); + children.insert(std::next(children.begin(), index), std::move(component)); + return component; } std::shared_ptr GuiComponent::add(std::shared_ptr component) { - component->parent = this; - component->updatePos(); - children.push_back(component); - return component; + component->parent = this; + component->updatePos(); + children.push_back(component); + return component; } void GuiComponent::remove(const std::string& key) { - for (auto it = children.cbegin(); it != children.cend(); it++) { - if (it->get()->key == key) { - children.erase(it); - return; - } - } + for (auto it = children.cbegin(); it != children.cend(); it++) { + if (it->get()->key == key) { + children.erase(it); + return; + } + } } void GuiComponent::empty() { - for (auto it = children.cbegin(); it != children.cend();) { - it = children.erase(it); - } + for (auto it = children.cbegin(); it != children.cend();) { + it = children.erase(it); + } } void GuiComponent::draw(Renderer& renderer) { - entity.draw(renderer); - - for (const auto& child : children) { - renderer.setClipBounds(overflows ? glm::vec4 {} : glm::vec4 {entity.getPos().x, entity.getPos().y, - entity.getPos().x + scale.x, entity.getPos().y + scale.y}); - child->draw(renderer); - } + entity.draw(renderer); + + for (const auto& child : children) { + renderer.setClipBounds(overflows ? glm::vec4{} : glm::vec4{ entity.getPos().x, entity.getPos().y, + entity.getPos().x + scale.x, entity.getPos().y + scale.y }); + child->draw(renderer); + } } bool GuiComponent::clickEvent(bool left, bool state, glm::ivec2 pos) { - for (auto& child : children) { - glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x); - if (child->clickEvent(left, state, cp)) return true; - } - - auto& callback = callbacks[static_cast(left ? CallbackType::PRIMARY : CallbackType::SECONDARY)]; - - if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y && callback) { - callback(state, pos); - return true; - } - return false; + for (auto& child : children) { + glm::ivec2 cp = pos - child->getPos() - glm::ivec2(child->getPadding().y, child->getPadding().x); + if (child->clickEvent(left, state, cp)) return true; + } + + auto& callback = callbacks[static_cast(left ? CallbackType::PRIMARY : CallbackType::SECONDARY)]; + + if (pos.x >= 0 && pos.y >= 0 && pos.x <= hitbox.x && pos.y <= hitbox.y && callback) { + callback(state, pos); + return true; + } + return false; } void GuiComponent::updatePos() { - glm::vec2 realPos(pos); - if (parent != nullptr) { - glm::vec3 parentPos = parent->entity.getPos(); - realPos += glm::vec2 {parentPos.x, parentPos.y}; - realPos += glm::vec2 {parent->getPadding().w, parent->getPadding().x}; - } - entity.setPos({realPos.x, realPos.y, 0}); - for (const auto& child : children) { - child->updatePos(); - } + glm::vec2 realPos(pos); + if (parent != nullptr) { + glm::vec3 parentPos = parent->entity.getPos(); + realPos += glm::vec2{ parentPos.x, parentPos.y }; + realPos += glm::vec2{ parent->getPadding().w, parent->getPadding().x }; + } + entity.setPos({ realPos.x, realPos.y, 0 }); + for (const auto& child : children) { + child->updatePos(); + } } std::list> GuiComponent::getChildren() { - return children; + return children; } diff --git a/src/client/gui/GuiComponent.h b/src/client/gui/GuiComponent.h index e2292a1e..d16b5afb 100644 --- a/src/client/gui/GuiComponent.h +++ b/src/client/gui/GuiComponent.h @@ -14,69 +14,85 @@ class Window; class GuiComponent : public Drawable { -public: - enum class CallbackType { PRIMARY, SECONDARY, HOVER }; - typedef std::function callback; - - GuiComponent() = default; - explicit GuiComponent(const std::string& key); - - virtual void update(double delta) override; - - const std::string& getKey(); - - virtual glm::ivec2 getPos(); - virtual void setPos(glm::ivec2 pos); - virtual glm::vec2 getScale(); - virtual void setScale(glm::vec2 scale); - virtual glm::vec4 getPadding(); - virtual void setPadding(glm::vec4 padding); - void setOverflows(bool overflows); - void setVisible(bool visible) override; - - virtual void setCallback(CallbackType type, const callback& cb); - void handleMouseInput(Window& window); - - template std::shared_ptr get(const std::string &key) { - for (auto &it : children) { - if (it.get()->key == key) { - return std::static_pointer_cast(it); - } - } - return nullptr; - }; - - std::shared_ptr insert(unsigned int index, std::shared_ptr component); - std::shared_ptr add(std::shared_ptr component); - - std::list> getChildren(); - - void remove(const std::string& key); - void empty(); - - void draw(Renderer& renderer) override; -protected: - bool mouseActivity(glm::ivec2 pos); - bool clickEvent(bool left, bool state, glm::ivec2 pos); - - std::string key = ""; - GuiComponent* parent = nullptr; - std::list> children; - - glm::ivec2 pos {}; - glm::vec2 scale {}; - glm::vec4 padding {}; - glm::ivec2 hitbox {}; - - bool visible = true; - bool hovered = false; - bool overflows = false; - - DrawableEntity entity; - std::array callbacks; - -private: - void updatePos(); + public: + enum class CallbackType { + PRIMARY, SECONDARY, HOVER + }; + typedef std::function callback; + + GuiComponent() = default; + + explicit GuiComponent(const std::string& key); + + virtual void update(double delta) override; + + const std::string& getKey(); + + virtual glm::ivec2 getPos(); + + virtual void setPos(glm::ivec2 pos); + + virtual glm::vec2 getScale(); + + virtual void setScale(glm::vec2 scale); + + virtual glm::vec4 getPadding(); + + virtual void setPadding(glm::vec4 padding); + + void setOverflows(bool overflows); + + void setVisible(bool visible) override; + + virtual void setCallback(CallbackType type, const callback& cb); + + void handleMouseInput(Window& window); + + template + std::shared_ptr get(const std::string& key) { + for (auto& it : children) { + if (it.get()->key == key) { + return std::static_pointer_cast(it); + } + } + return nullptr; + }; + + std::shared_ptr insert(unsigned int index, std::shared_ptr component); + + std::shared_ptr add(std::shared_ptr component); + + std::list> getChildren(); + + void remove(const std::string& key); + + void empty(); + + void draw(Renderer& renderer) override; + + protected: + bool mouseActivity(glm::ivec2 pos); + + bool clickEvent(bool left, bool state, glm::ivec2 pos); + + std::string key = ""; + GuiComponent* parent = nullptr; + std::list> children; + + glm::ivec2 pos{}; + glm::vec2 scale{}; + glm::vec4 padding{}; + glm::ivec2 hitbox{}; + + bool visible = true; + bool hovered = false; + bool overflows = false; + + DrawableEntity entity; + std::array callbacks; + + private: + void updatePos(); }; diff --git a/src/client/gui/SerialGui.h b/src/client/gui/SerialGui.h index b45bf3c2..207c53fa 100644 --- a/src/client/gui/SerialGui.h +++ b/src/client/gui/SerialGui.h @@ -20,71 +20,76 @@ #include "../../lua/usertype/LuaGuiElement.h" namespace SerialGui { - const float SCALE_MODIFIER = 3; - const float PERCENT_DIFF = 10000; - - namespace { - static std::vector split(const std::string& value, unsigned int targetCount = 0) { - std::vector vec {}; - - if (value == "") throw std::runtime_error("expected one or more values to split"); - - size_t count = std::count(value.begin(), value.end(), ' '); - if (count + 1 > targetCount) throw std::runtime_error("expected less values"); - - // Split the values into the vector. - size_t begin = 0; - for (int i = 0; i < count; i++) { - size_t end = value.find(' ', begin); - vec.push_back(value.substr(begin, end - begin)); - begin = end + 1; - } - vec.push_back(value.substr(begin)); - - // Duplicate values until we meet or surpass the expected values. - while (vec.size() < targetCount) for (auto& v: vec) vec.push_back(v); - if (vec.size() > targetCount) throw std::runtime_error("values are not a division of expectation"); - - return std::move(vec); - } - - static double toDouble(const std::string& input) { - char* e; - errno = 0; - - if (input.find('%') == input.length() - 1) { - double v = std::strtod(input.substr(0, input.find("%")).c_str(), &e) / 100; - if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string"); - return v - PERCENT_DIFF; // Percentages are going to be stored in negatives. Ew. - } - - double v = round(std::strtod(input.c_str(), &e)); - if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string"); - return v; - } - - static double convertNum(float input, unsigned int multiple) { - if (input >= -PERCENT_DIFF - 100 && input < -PERCENT_DIFF + 100) { - if (!multiple) return input + PERCENT_DIFF; - else return (((input + PERCENT_DIFF) * multiple / SCALE_MODIFIER) * SCALE_MODIFIER); - } - - return input * SCALE_MODIFIER; - } - } - - template static T calcNumbers(const T in, glm::ivec2 multiple = {}) {}; - - template static T get(const LuaGuiElement& elem, const std::string& req, glm::ivec2 multiple = {}) { - if (!elem.has(req)) return T{}; - return calcNumbers(elem.get(req), multiple); - } - - template <> glm::vec2 calcNumbers(const glm::vec2 in, glm::ivec2 multiple) { - return {convertNum(in.x, multiple.x), convertNum(in.y, multiple.y)}; - } - - template <> glm::vec4 calcNumbers(const glm::vec4 in, glm::ivec2 multiple) { - return {convertNum(in.x, multiple.x), convertNum(in.y, multiple.y), convertNum(in.z, multiple.x), convertNum(in.w, multiple.y)}; - } + const float SCALE_MODIFIER = 3; + const float PERCENT_DIFF = 10000; + + namespace { + static std::vector split(const std::string& value, unsigned int targetCount = 0) { + std::vector vec{}; + + if (value == "") throw std::runtime_error("expected one or more values to split"); + + size_t count = std::count(value.begin(), value.end(), ' '); + if (count + 1 > targetCount) throw std::runtime_error("expected less values"); + + // Split the values into the vector. + size_t begin = 0; + for (int i = 0; i < count; i++) { + size_t end = value.find(' ', begin); + vec.push_back(value.substr(begin, end - begin)); + begin = end + 1; + } + vec.push_back(value.substr(begin)); + + // Duplicate values until we meet or surpass the expected values. + while (vec.size() < targetCount) for (auto& v: vec) vec.push_back(v); + if (vec.size() > targetCount) throw std::runtime_error("values are not a division of expectation"); + + return std::move(vec); + } + + static double toDouble(const std::string& input) { + char* e; + errno = 0; + + if (input.find('%') == input.length() - 1) { + double v = std::strtod(input.substr(0, input.find("%")).c_str(), &e) / 100; + if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string"); + return v - PERCENT_DIFF; // Percentages are going to be stored in negatives. Ew. + } + + double v = round(std::strtod(input.c_str(), &e)); + if (*e != '\0' || errno != 0) throw std::runtime_error("error decoding num from string"); + return v; + } + + static double convertNum(float input, unsigned int multiple) { + if (input >= -PERCENT_DIFF - 100 && input < -PERCENT_DIFF + 100) { + if (!multiple) return input + PERCENT_DIFF; + else return (((input + PERCENT_DIFF) * multiple / SCALE_MODIFIER) * SCALE_MODIFIER); + } + + return input * SCALE_MODIFIER; + } + } + + template + static T calcNumbers(const T in, glm::ivec2 multiple = {}) {}; + + template + static T get(const LuaGuiElement& elem, const std::string& req, glm::ivec2 multiple = {}) { + if (!elem.has(req)) return T{}; + return calcNumbers(elem.get(req), multiple); + } + + template<> + glm::vec2 calcNumbers(const glm::vec2 in, glm::ivec2 multiple) { + return { convertNum(in.x, multiple.x), convertNum(in.y, multiple.y) }; + } + + template<> + glm::vec4 calcNumbers(const glm::vec4 in, glm::ivec2 multiple) { + return { convertNum(in.x, multiple.x), convertNum(in.y, multiple.y), convertNum(in.z, multiple.x), + convertNum(in.w, multiple.y) }; + } }; \ No newline at end of file diff --git a/src/client/gui/basic/GuiContainer.cpp b/src/client/gui/basic/GuiContainer.cpp index 5c68729b..4791c2c3 100644 --- a/src/client/gui/basic/GuiContainer.cpp +++ b/src/client/gui/basic/GuiContainer.cpp @@ -4,10 +4,10 @@ #include "GuiContainer.h" -GuiContainer::GuiContainer(const std::string &key) : GuiComponent(key) {} +GuiContainer::GuiContainer(const std::string& key) : GuiComponent(key) {} -void GuiContainer::draw(Renderer &renderer) { - for (const auto& child : children) { - child->draw(renderer); - } +void GuiContainer::draw(Renderer& renderer) { + for (const auto& child : children) { + child->draw(renderer); + } } diff --git a/src/client/gui/basic/GuiContainer.h b/src/client/gui/basic/GuiContainer.h index eb17a537..5c8022eb 100644 --- a/src/client/gui/basic/GuiContainer.h +++ b/src/client/gui/basic/GuiContainer.h @@ -7,10 +7,11 @@ #include "client/gui/GuiComponent.h" class GuiContainer : public GuiComponent { -public: - GuiContainer() = default; - explicit GuiContainer(const std::string& key); - - void draw(Renderer& renderer) override; + public: + GuiContainer() = default; + + explicit GuiContainer(const std::string& key); + + void draw(Renderer& renderer) override; }; diff --git a/src/client/gui/basic/GuiGraph.cpp b/src/client/gui/basic/GuiGraph.cpp index cddbba33..1ec41c4a 100644 --- a/src/client/gui/basic/GuiGraph.cpp +++ b/src/client/gui/basic/GuiGraph.cpp @@ -8,99 +8,103 @@ #include "client/graph/Model.h" #include "game/atlas/asset/AtlasRef.h" -GuiGraph::GuiGraph(const std::string &key) : GuiComponent(key) {} +GuiGraph::GuiGraph(const std::string& key) : GuiComponent(key) {} -void GuiGraph::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, - unsigned int length, float maxValue, bool editInPlace) { - - this->scale = scale; - this->padding = padding; - - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); - - this->length = length; - this->maxVal = maxValue; - this->dynamicMax = maxValue <= 0; - this->editInPlace = editInPlace; - this->texture = std::move(texture); - - history = std::vector(static_cast(length)); - - entity.setModel(std::make_shared()); +void GuiGraph::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, + unsigned int length, float maxValue, bool editInPlace) { + + this->scale = scale; + this->padding = padding; + + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); + + this->length = length; + this->maxVal = maxValue; + this->dynamicMax = maxValue <= 0; + this->editInPlace = editInPlace; + this->texture = std::move(texture); + + history = std::vector(static_cast(length)); + + entity.setModel(std::make_shared()); } void GuiGraph::pushValue(float value) { - if (editInPlace) { - insertionPoint++; - if (insertionPoint >= length) insertionPoint = 0; - history[insertionPoint] = value; - } - else { - if (insertionPoint < length - 1) insertionPoint++; - else { - for (int i = 0; i < length; i++) { - history[i] = history[i + 1]; - } - } - history[insertionPoint] = value; - } - if (dynamicMax) { - maxVal = 0; - for (float i : history) { - if (i > maxVal) maxVal = i; - } - } - - buildHistogramMesh(); + if (editInPlace) { + insertionPoint++; + if (insertionPoint >= length) insertionPoint = 0; + history[insertionPoint] = value; + } + else { + if (insertionPoint < length - 1) insertionPoint++; + else { + for (int i = 0; i < length; i++) { + history[i] = history[i + 1]; + } + } + history[insertionPoint] = value; + } + if (dynamicMax) { + maxVal = 0; + for (float i : history) { + if (i > maxVal) maxVal = i; + } + } + + buildHistogramMesh(); } void GuiGraph::setMax(float max) { - maxVal = max; + maxVal = max; } void GuiGraph::buildHistogramMesh() { - std::vector vertices {}; - std::vector indices {}; - - auto uv = texture->uv; - uv.z -= uv.x; - uv.w -= uv.y; - - unsigned int indOffset = 0; - float xOffset = 0; - - for (float num : history) { - float distFromPointer = (xOffset <= insertionPoint) ? insertionPoint - xOffset : insertionPoint + length - xOffset; - float age = std::round((90 - (distFromPointer / length)*90)) / 100.0f; - - float h = num / maxVal; - float sec = (float)std::round(9 - fmin(h, 1)*9) * 0.1f; - - auto columnVerts = std::vector { - {{xOffset, -h, 0}, {uv.x + age * uv.z, uv.y + sec * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{xOffset + 1,-h, 0}, {uv.x + (age+0.01f) * uv.z, uv.y + sec * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{xOffset + 1, 0, 0}, {uv.x + (age+0.01f) * uv.z, uv.y + (sec+0.10f) * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{xOffset, 0, 0}, {uv.x + age * uv.z, uv.y + (sec+0.10f) * uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - }; - - vertices.insert(vertices.end(), columnVerts.begin(), columnVerts.end()); - - indices.push_back( indOffset); - indices.push_back(3 + indOffset); - indices.push_back(1 + indOffset); - indices.push_back(3 + indOffset); - indices.push_back(2 + indOffset); - indices.push_back(1 + indOffset); - - xOffset ++; - indOffset += 4; - } - - auto m = std::make_unique(); - m->create(vertices, indices); - - auto model = std::make_shared(); - model->fromMesh(std::move(m)); - - entity.setModel(model); + std::vector vertices{}; + std::vector indices{}; + + auto uv = texture->uv; + uv.z -= uv.x; + uv.w -= uv.y; + + unsigned int indOffset = 0; + float xOffset = 0; + + for (float num : history) { + float distFromPointer = (xOffset <= insertionPoint) ? insertionPoint - xOffset : insertionPoint + length - + xOffset; + float age = std::round((90 - (distFromPointer / length) * 90)) / 100.0f; + + float h = num / maxVal; + float sec = (float) std::round(9 - fmin(h, 1) * 9) * 0.1f; + + auto columnVerts = std::vector{ + {{ xOffset, -h, 0 }, { uv.x + age * uv.z, uv.y + sec * uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ xOffset + 1, -h, 0 }, { uv.x + (age + 0.01f) * uv.z, uv.y + sec * uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, + {}, {}}, + {{ xOffset + 1, 0, 0 }, { uv.x + (age + 0.01f) * uv.z, uv.y + (sec + 0.10f) * uv.w, 0, 1 }, { 1, 1, 1 }, + true, {}, {}, {}}, + {{ xOffset, 0, 0 }, { uv.x + age * uv.z, uv.y + (sec + 0.10f) * uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, + {}}, + }; + + vertices.insert(vertices.end(), columnVerts.begin(), columnVerts.end()); + + indices.push_back(indOffset); + indices.push_back(3 + indOffset); + indices.push_back(1 + indOffset); + indices.push_back(3 + indOffset); + indices.push_back(2 + indOffset); + indices.push_back(1 + indOffset); + + xOffset++; + indOffset += 4; + } + + auto m = std::make_unique(); + m->create(vertices, indices); + + auto model = std::make_shared(); + model->fromMesh(std::move(m)); + + entity.setModel(model); } diff --git a/src/client/gui/basic/GuiGraph.h b/src/client/gui/basic/GuiGraph.h index 13568123..845f9c6e 100644 --- a/src/client/gui/basic/GuiGraph.h +++ b/src/client/gui/basic/GuiGraph.h @@ -9,26 +9,31 @@ class AtlasRef; class GuiGraph : public GuiComponent { -public: - GuiGraph() = default; - GuiGraph(const std::string& key); - - void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, unsigned int length, float maxValue, bool editInPlace); - - void setMax(float max); - void pushValue(float value); -private: - void buildHistogramMesh(); - - bool editInPlace = false; - - unsigned int insertionPoint = 0; - unsigned int length = 60; - - bool dynamicMax = true; - float maxVal = 0; - - std::shared_ptr texture; - std::vector history; + public: + GuiGraph() = default; + + GuiGraph(const std::string& key); + + void + create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, unsigned int length, float maxValue, + bool editInPlace); + + void setMax(float max); + + void pushValue(float value); + + private: + void buildHistogramMesh(); + + bool editInPlace = false; + + unsigned int insertionPoint = 0; + unsigned int length = 60; + + bool dynamicMax = true; + float maxVal = 0; + + std::shared_ptr texture; + std::vector history; }; diff --git a/src/client/gui/basic/GuiInventoryItem.cpp b/src/client/gui/basic/GuiInventoryItem.cpp index 14a5b3ef..a396a5e6 100644 --- a/src/client/gui/basic/GuiInventoryItem.cpp +++ b/src/client/gui/basic/GuiInventoryItem.cpp @@ -11,41 +11,41 @@ #include "game/def/BlockDef.h" #include "game/def/CraftItemDef.h" -GuiInventoryItem::GuiInventoryItem(const std::string &key) : GuiContainer(key) {} +GuiInventoryItem::GuiInventoryItem(const std::string& key) : GuiContainer(key) {} void GuiInventoryItem::create(glm::vec2 scale, unsigned short count, ItemDef& def, Font f) { - - if (def.type == ItemDef::Type::CRAFTITEM) { - auto texture = static_cast(def).textureRefs[0]; - - auto shadow = std::make_shared("shadow"); - shadow->create(scale * 16.f, {}, texture, {0, 0, 0, 0.2}); - add(shadow); - shadow->setPos(scale); - - auto item = std::make_shared("mesh"); - item->create(scale * 16.f, {}, texture); - add(item); - } - else { - auto& model = static_cast(def).entityModel; - - auto item = std::make_shared("mesh"); - item->create(scale * 10.5f, model); - item->setPos(glm::vec2{8, 8} * scale); - - item->setRotationX(180.f - 30.f); - item->setRotationY(45.f); - item->setRotationZ(0.f); - - add(item); - } - - if (count > 1) { - auto text = std::make_shared("count"); - text->create(scale, {}, {}, {1, 1, 1, 1}, f); - text->setText(std::to_string(count)); - add(text); - text->setPos({(19 - text->getWidth()) * scale.x, 9 * scale.y}); - } + + if (def.type == ItemDef::Type::CRAFTITEM) { + auto texture = static_cast(def).textureRefs[0]; + + auto shadow = std::make_shared("shadow"); + shadow->create(scale * 16.f, {}, texture, { 0, 0, 0, 0.2 }); + add(shadow); + shadow->setPos(scale); + + auto item = std::make_shared("mesh"); + item->create(scale * 16.f, {}, texture); + add(item); + } + else { + auto& model = static_cast(def).entityModel; + + auto item = std::make_shared("mesh"); + item->create(scale * 10.5f, model); + item->setPos(glm::vec2{ 8, 8 } * scale); + + item->setRotationX(180.f - 30.f); + item->setRotationY(45.f); + item->setRotationZ(0.f); + + add(item); + } + + if (count > 1) { + auto text = std::make_shared("count"); + text->create(scale, {}, {}, { 1, 1, 1, 1 }, f); + text->setText(std::to_string(count)); + add(text); + text->setPos({ (19 - text->getWidth()) * scale.x, 9 * scale.y }); + } } diff --git a/src/client/gui/basic/GuiInventoryItem.h b/src/client/gui/basic/GuiInventoryItem.h index e9135a61..f9cf2935 100644 --- a/src/client/gui/basic/GuiInventoryItem.h +++ b/src/client/gui/basic/GuiInventoryItem.h @@ -7,12 +7,14 @@ #include "GuiContainer.h" class ItemDef; + class Font; class GuiInventoryItem : public GuiContainer { -public: - GuiInventoryItem() = default; - GuiInventoryItem(const std::string& key); - - void create(glm::vec2 scale, unsigned short itemCount, ItemDef& def, Font font); + public: + GuiInventoryItem() = default; + + GuiInventoryItem(const std::string& key); + + void create(glm::vec2 scale, unsigned short itemCount, ItemDef& def, Font font); }; diff --git a/src/client/gui/basic/GuiModel.cpp b/src/client/gui/basic/GuiModel.cpp index a1e8eda1..94a75ed3 100644 --- a/src/client/gui/basic/GuiModel.cpp +++ b/src/client/gui/basic/GuiModel.cpp @@ -11,61 +11,62 @@ #include "game/atlas/asset/ModelStore.h" #include "game/atlas/TextureAtlas.h" -GuiModel::GuiModel(const std::string &key) : GuiComponent(key) {} +GuiModel::GuiModel(const std::string& key) : GuiComponent(key) {} -std::shared_ptr GuiModel::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) { - glm::vec2 pos = SerialGui::get(elem, "position", bounds); - glm::vec2 scale = SerialGui::get(elem, "scale"); - glm::vec2 anim_range = SerialGui::get(elem, "anim_range"); - if (scale == glm::vec2{0, 0}) scale = {1, 1}; - - std::string type = elem.get_or("type", "model"); - std::string source = elem.get_or("source", ""); - std::string texture = elem.get_or("texture", ""); - - auto m = std::make_shared(); - if (type == "model") m->fromSerialized(models.models[source], {textures[texture]}); - - auto model = std::make_shared(elem.key); - model->create(scale, m); - model->setPos(pos); - - if (anim_range.y != 0) model->animate(anim_range); - - return model; +std::shared_ptr +GuiModel::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds) { + glm::vec2 pos = SerialGui::get(elem, "position", bounds); + glm::vec2 scale = SerialGui::get(elem, "scale"); + glm::vec2 anim_range = SerialGui::get(elem, "anim_range"); + if (scale == glm::vec2{ 0, 0 }) scale = { 1, 1 }; + + std::string type = elem.get_or("type", "model"); + std::string source = elem.get_or("source", ""); + std::string texture = elem.get_or("texture", ""); + + auto m = std::make_shared(); + if (type == "model") m->fromSerialized(models.models[source], { textures[texture] }); + + auto model = std::make_shared(elem.key); + model->create(scale, m); + model->setPos(pos); + + if (anim_range.y != 0) model->animate(anim_range); + + return model; } void GuiModel::create(glm::vec2 scale, std::shared_ptr model) { - entity.setModel(model); - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); - - setRotationX(180); - setRotationY(215); + entity.setModel(model); + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); + + setRotationX(180); + setRotationY(215); } void GuiModel::update(double delta) { - entity.update(delta); + entity.update(delta); } void GuiModel::animate(glm::vec2 range) { - entity.animation.setAnim(range, 0, true); + entity.animation.setAnim(range, 0, true); } void GuiModel::setRotationX(float x) { - entity.setRotateX(x); + entity.setRotateX(x); } void GuiModel::setRotationY(float y) { - entity.setRotateY(y); + entity.setRotateY(y); } void GuiModel::setRotationZ(float z) { - entity.setRotateZ(z); + entity.setRotateZ(z); } -void GuiModel::draw(Renderer &renderer) { - renderer.toggleDepthTest(true); - renderer.clearDepthBuffer(); - GuiComponent::draw(renderer); - renderer.toggleDepthTest(false); +void GuiModel::draw(Renderer& renderer) { + renderer.toggleDepthTest(true); + renderer.clearDepthBuffer(); + GuiComponent::draw(renderer); + renderer.toggleDepthTest(false); } diff --git a/src/client/gui/basic/GuiModel.h b/src/client/gui/basic/GuiModel.h index 6ac51e6a..734982e0 100644 --- a/src/client/gui/basic/GuiModel.h +++ b/src/client/gui/basic/GuiModel.h @@ -9,27 +9,36 @@ #include "GuiContainer.h" class LocalSubgame; + class ModelStore; + class TextureAtlas; + class LuaGuiElement; class GuiModel : public GuiComponent { -public: - GuiModel() = default; - GuiModel(const std::string& key); - - static std::shared_ptr fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds); - - void create(glm::vec2 scale, std::shared_ptr model); - void update(double delta) override; - - void animate(glm::vec2 range); - - void setRotationX(float x); - void setRotationY(float x); - void setRotationZ(float x); - - void draw(Renderer& renderer) override; -protected: - float depth = 300; + public: + GuiModel() = default; + + GuiModel(const std::string& key); + + static std::shared_ptr + fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, ModelStore& models, glm::ivec2 bounds); + + void create(glm::vec2 scale, std::shared_ptr model); + + void update(double delta) override; + + void animate(glm::vec2 range); + + void setRotationX(float x); + + void setRotationY(float x); + + void setRotationZ(float x); + + void draw(Renderer& renderer) override; + + protected: + float depth = 300; }; diff --git a/src/client/gui/basic/GuiRect.cpp b/src/client/gui/basic/GuiRect.cpp index fc32ed1a..97ff2621 100644 --- a/src/client/gui/basic/GuiRect.cpp +++ b/src/client/gui/basic/GuiRect.cpp @@ -10,111 +10,111 @@ #include "game/atlas/TextureAtlas.h" #include "game/atlas/asset/AtlasRef.h" -GuiRect::GuiRect(const std::string &key) : GuiComponent(key) {} +GuiRect::GuiRect(const std::string& key) : GuiComponent(key) {} std::shared_ptr GuiRect::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) { - glm::vec2 pos = SerialGui::get(elem, "position", bounds); - glm::vec2 offset = SerialGui::get(elem, "position_anchor"); - glm::vec2 size = SerialGui::get(elem, "size", bounds); - glm::vec4 padding = SerialGui::get(elem, "padding", bounds); - - pos -= offset * size; - size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z}; - - std::string background = elem.get_or("background", ""); - bool hideOverflow = elem.get_or("overflow", "visible") == "hidden"; - - auto rect = std::make_shared(elem.key); - if (background[0] == '#') rect->create(size, padding, Util::hexToColorVec(background)); - else if (background.size() > 0) rect->create(size, padding, textures[background]); - else rect->create(size, padding, glm::vec4 {}); - rect->setOverflows(!hideOverflow); - rect->setPos(pos); - return rect; + glm::vec2 pos = SerialGui::get(elem, "position", bounds); + glm::vec2 offset = SerialGui::get(elem, "position_anchor"); + glm::vec2 size = SerialGui::get(elem, "size", bounds); + glm::vec4 padding = SerialGui::get(elem, "padding", bounds); + + pos -= offset * size; + size -= glm::vec2{ padding.y + padding.w, padding.x + padding.z }; + + std::string background = elem.get_or("background", ""); + bool hideOverflow = elem.get_or("overflow", "visible") == "hidden"; + + auto rect = std::make_shared(elem.key); + if (background[0] == '#') rect->create(size, padding, Util::hexToColorVec(background)); + else if (background.size() > 0) rect->create(size, padding, textures[background]); + else rect->create(size, padding, glm::vec4{}); + rect->setOverflows(!hideOverflow); + rect->setPos(pos); + return rect; } // Single Color Constructor // Creates a GuiRect object whose background // is a flat color defined by 'color'. void GuiRect::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color) { - this->scale = scale; - this->padding = padding; - - auto mesh = std::make_unique(); - mesh->create({{{0, 0, 0}, color, {1, 1, 1}, false, {}, {}, {}}, - {{0, 1, 0}, color, {1, 1, 1}, false, {}, {}, {}}, - {{1, 1, 0}, color, {1, 1, 1}, false, {}, {}, {}}, - {{1, 0, 0}, color, {1, 1, 1}, false, {}, {}, {}} - }, {0, 1, 2, 2, 3, 0}); - auto model = std::make_shared(); - model->fromMesh(std::move(mesh)); - - entity.setModel(model); - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); + this->scale = scale; + this->padding = padding; + + auto mesh = std::make_unique(); + mesh->create({{{ 0, 0, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}}, + {{ 0, 1, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}}, + {{ 1, 1, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}}, + {{ 1, 0, 0 }, color, { 1, 1, 1 }, false, {}, {}, {}} + }, { 0, 1, 2, 2, 3, 0 }); + auto model = std::make_shared(); + model->fromMesh(std::move(mesh)); + + entity.setModel(model); + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); } // Multiple Color Constructor // Creates a GuiRect object with a gradient background // defined by 'tl', 'tr', 'bl', and 'br'. void GuiRect::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br) { - this->scale = scale; - this->padding = padding; - - auto mesh = std::make_unique(); - mesh->create({ - {{0, 0, 0}, tl, {1, 1, 1}, false, {}, {}, {}}, - {{0, 1, 0}, bl, {1, 1, 1}, false, {}, {}, {}}, - {{1, 1, 0}, br, {1, 1, 1}, false, {}, {}, {}}, - {{1, 0, 0}, tr, {1, 1, 1}, false, {}, {}, {}} - }, {0, 1, 2, 2, 3, 0}); - auto model = std::make_shared(); - model->fromMesh(std::move(mesh)); - - entity.setModel(model); - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); + this->scale = scale; + this->padding = padding; + + auto mesh = std::make_unique(); + mesh->create({ + {{ 0, 0, 0 }, tl, { 1, 1, 1 }, false, {}, {}, {}}, + {{ 0, 1, 0 }, bl, { 1, 1, 1 }, false, {}, {}, {}}, + {{ 1, 1, 0 }, br, { 1, 1, 1 }, false, {}, {}, {}}, + {{ 1, 0, 0 }, tr, { 1, 1, 1 }, false, {}, {}, {}} + }, { 0, 1, 2, 2, 3, 0 }); + auto model = std::make_shared(); + model->fromMesh(std::move(mesh)); + + entity.setModel(model); + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); } // Texture Constructor // Creates a GuiRect object with a textured background // defined by the 'texture' reference. void GuiRect::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture) { - this->scale = scale; - this->padding = padding; - this->texture = texture; - this->hitbox = scale + glm::vec2{padding.y + padding.w, padding.x + padding.z}; - - auto mesh = std::make_unique(); - mesh->create({ - {{0, 0, 0}, {this->texture->uv.x, this->texture->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{0, 1, 0}, {this->texture->uv.x, this->texture->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{1, 1, 0}, {this->texture->uv.z, this->texture->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{1, 0, 0}, {this->texture->uv.z, this->texture->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}} - }, {0, 1, 2, 2, 3, 0}); - auto model = std::make_shared(); - model->fromMesh(std::move(mesh)); - - entity.setModel(model); - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); + this->scale = scale; + this->padding = padding; + this->texture = texture; + this->hitbox = scale + glm::vec2{ padding.y + padding.w, padding.x + padding.z }; + + auto mesh = std::make_unique(); + mesh->create({ + {{ 0, 0, 0 }, { this->texture->uv.x, this->texture->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ 0, 1, 0 }, { this->texture->uv.x, this->texture->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ 1, 1, 0 }, { this->texture->uv.z, this->texture->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ 1, 0, 0 }, { this->texture->uv.z, this->texture->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}} + }, { 0, 1, 2, 2, 3, 0 }); + auto model = std::make_shared(); + model->fromMesh(std::move(mesh)); + + entity.setModel(model); + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); } // Texture Constructor // Creates a GuiRect object with a textured background // defined by the 'texture' reference. void GuiRect::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, glm::vec4 tint) { - this->scale = scale; - this->padding = padding; - this->texture = std::move(texture); - - auto mesh = std::make_unique(); - mesh->create({ - {{0, 0, 0}, {this->texture->uv.x, this->texture->uv.y, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}}, - {{0, 1, 0}, {this->texture->uv.x, this->texture->uv.w, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}}, - {{1, 1, 0}, {this->texture->uv.z, this->texture->uv.w, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}}, - {{1, 0, 0}, {this->texture->uv.z, this->texture->uv.y, 0, tint.w}, glm::vec3{tint}, true, {}, {}, {}} - }, {0, 1, 2, 2, 3, 0}); - auto model = std::make_shared(); - model->fromMesh(std::move(mesh)); - - entity.setModel(model); - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); + this->scale = scale; + this->padding = padding; + this->texture = std::move(texture); + + auto mesh = std::make_unique(); + mesh->create({ + {{ 0, 0, 0 }, { this->texture->uv.x, this->texture->uv.y, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}}, + {{ 0, 1, 0 }, { this->texture->uv.x, this->texture->uv.w, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}}, + {{ 1, 1, 0 }, { this->texture->uv.z, this->texture->uv.w, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}}, + {{ 1, 0, 0 }, { this->texture->uv.z, this->texture->uv.y, 0, tint.w }, glm::vec3{ tint }, true, {}, {}, {}} + }, { 0, 1, 2, 2, 3, 0 }); + auto model = std::make_shared(); + model->fromMesh(std::move(mesh)); + + entity.setModel(model); + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); } diff --git a/src/client/gui/basic/GuiRect.h b/src/client/gui/basic/GuiRect.h index 03edc94a..43f8e327 100644 --- a/src/client/gui/basic/GuiRect.h +++ b/src/client/gui/basic/GuiRect.h @@ -7,23 +7,31 @@ #include "client/gui/GuiComponent.h" class AtlasRef; + class LocalSubgame; + class TextureAtlas; + class LuaGuiElement; class GuiRect : public GuiComponent { -public: - GuiRect() = default; - GuiRect(const std::string& key); - - static std::shared_ptr fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds); - - void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color); - void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br); - void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture); - void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, glm::vec4 tint); - -protected: - std::shared_ptr texture = nullptr; + public: + GuiRect() = default; + + GuiRect(const std::string& key); + + static std::shared_ptr + fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds); + + void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 color); + + void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 tl, glm::vec4 tr, glm::vec4 bl, glm::vec4 br); + + void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture); + + void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, glm::vec4 tint); + + protected: + std::shared_ptr texture = nullptr; }; diff --git a/src/client/gui/basic/GuiText.cpp b/src/client/gui/basic/GuiText.cpp index 206b28ac..a98f7702 100644 --- a/src/client/gui/basic/GuiText.cpp +++ b/src/client/gui/basic/GuiText.cpp @@ -12,170 +12,178 @@ #include "game/atlas/asset/AtlasRef.h" #include "world/dim/ent/AnimationSegment.h" -GuiText::GuiText(const std::string &key) : GuiComponent(key) {} +GuiText::GuiText(const std::string& key) : GuiComponent(key) {} void GuiText::create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font) { - // Text Constructor - // Creates a GuiText object. - - this->scale = scale; - this->padding = padding; - this->font = std::move(font); - - this->bgcolor = bgcolor; - this->color = color; - - setScale(scale); - setText(""); + // Text Constructor + // Creates a GuiText object. + + this->scale = scale; + this->padding = padding; + this->font = std::move(font); + + this->bgcolor = bgcolor; + this->color = color; + + setScale(scale); + setText(""); } std::shared_ptr GuiText::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) { - glm::vec2 pos = SerialGui::get(elem, "position", bounds); - glm::vec2 offset = SerialGui::get(elem, "position_anchor"); - glm::vec2 size = SerialGui::get(elem, "size", bounds); - glm::vec4 padding = SerialGui::get(elem, "padding", bounds); - glm::vec2 scale = SerialGui::get(elem, "scale"); - if (scale == glm::vec2{0, 0}) scale = {1, 1}; - - pos -= offset * size; - - glm::vec4 background_color = Util::hexToColorVec(elem.get_or("background", "#0000")); - glm::vec4 color = Util::hexToColorVec(elem.get_or("color", "#fff")); - std::string content = elem.get_or("content", ""); - - auto text = std::make_shared(elem.key); - text->create(scale * SerialGui::SCALE_MODIFIER, padding, background_color, color, {textures, textures["font"]}); - text->setText(content); - text->setPos(pos); - - return text; + glm::vec2 pos = SerialGui::get(elem, "position", bounds); + glm::vec2 offset = SerialGui::get(elem, "position_anchor"); + glm::vec2 size = SerialGui::get(elem, "size", bounds); + glm::vec4 padding = SerialGui::get(elem, "padding", bounds); + glm::vec2 scale = SerialGui::get(elem, "scale"); + if (scale == glm::vec2{ 0, 0 }) scale = { 1, 1 }; + + pos -= offset * size; + + glm::vec4 background_color = Util::hexToColorVec(elem.get_or("background", "#0000")); + glm::vec4 color = Util::hexToColorVec(elem.get_or("color", "#fff")); + std::string content = elem.get_or("content", ""); + + auto text = std::make_shared(elem.key); + text->create(scale * SerialGui::SCALE_MODIFIER, padding, background_color, color, { textures, textures["font"] }); + text->setText(content); + text->setPos(pos); + + return text; } void GuiText::setText(std::string text) { - this->text = std::move(text); - unsigned int indOffset = 0; - - maxLineWidth = 0; - - std::vector textVertices; - textVertices.reserve(text.length()*8 + 200); - std::vector textIndices; - textIndices.reserve(text.length()*12 + 240); - - //Draw background & Measure Line Width - int lineWidth = 0; - int xOffset = 0, yOffset = 0; - int h = Font::charHeight; - - for (unsigned int i = 0; i < this->text.length() + 1; i++) { - char c = this->text[i]; - - //TODO: Proper font handling. - if (c == '\t') c = ' '; - - if (c == '\n' || i == this->text.length()) { - if (lineWidth > 0) { - lineWidth += 2; - - if (lineWidth > maxLineWidth) maxLineWidth = lineWidth; - - if (bgcolor.w != 0) { - textVertices.emplace_back(glm::vec3 {-1, yOffset - 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - textVertices.emplace_back(glm::vec3 {-1, yOffset + h + 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - textVertices.emplace_back(glm::vec3 {lineWidth + 1, yOffset + h + 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - textVertices.emplace_back(glm::vec3 {lineWidth + 1, yOffset - 1, 0}, bgcolor, glm::vec3(1), 0.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - - textIndices.emplace_back(indOffset); - textIndices.emplace_back(indOffset + 1); - textIndices.emplace_back(indOffset + 2); - textIndices.emplace_back(indOffset + 2); - textIndices.emplace_back(indOffset + 3); - textIndices.emplace_back(indOffset); - - indOffset += 4; - } - yOffset += h + 2; - } - else { - yOffset += h / 2; //Pad out the height if using just newlines. - } - - lineWidth = 0; - } - else lineWidth += font.getCharWidth(c) + 1; - } - - //Draw Characters - - bool emptyLine = true; - xOffset = 0; - yOffset = 0; - - for (unsigned int i = 0; i < this->text.length() + 1; i++) { - char c = this->text[i]; - - //TODO: Proper font handling. - if (c == '\t') c = ' '; - - unsigned int h = Font::charHeight; - - if (c == '\n' || i == this->text.length()) { - yOffset += (emptyLine) ? h / 2 : h + 2; - xOffset = 0; - emptyLine = true; - continue; - } - else { - emptyLine = false; - } - - auto charWidth = font.getCharWidth(c) + 1; - auto charUVs = font.getCharUVs(c); - - for (unsigned int j = 0; j <= 1; j++) { - glm::vec3 c = {this->color.x, this->color.y, this->color.z}; - - if (j == 0) { - c *= glm::vec3 {0.4, 0.4, 0.45}; - xOffset += 1; - yOffset += 1; - } - else { - xOffset -= 1; - yOffset -= 1; - } - - textVertices.emplace_back(glm::vec3 {xOffset, yOffset, 0}, glm::vec4 {charUVs.x, charUVs.y, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - textVertices.emplace_back(glm::vec3 {xOffset, yOffset + h, 0}, glm::vec4 {charUVs.x, charUVs.w, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - textVertices.emplace_back(glm::vec3 {xOffset + charWidth, yOffset + h, 0}, glm::vec4 {charUVs.z, charUVs.w, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - textVertices.emplace_back(glm::vec3 {xOffset + charWidth, yOffset, 0}, glm::vec4 {charUVs.z, charUVs.y, 0, color.w}, c, 1.f, glm::vec3 {}, glm::ivec4 {}, glm::vec4 {}); - - textIndices.emplace_back(indOffset); - textIndices.emplace_back(indOffset + 1); - textIndices.emplace_back(indOffset + 2); - textIndices.emplace_back(indOffset + 2); - textIndices.emplace_back(indOffset + 3); - textIndices.emplace_back(indOffset); - - indOffset += 4; - } - - xOffset += charWidth; - } - - auto m = std::make_unique(); - m->create(textVertices, textIndices); - - auto model = std::make_shared(); - model->fromMesh(std::move(m)); - - entity.setModel(model); + this->text = std::move(text); + unsigned int indOffset = 0; + + maxLineWidth = 0; + + std::vector textVertices; + textVertices.reserve(text.length() * 8 + 200); + std::vector textIndices; + textIndices.reserve(text.length() * 12 + 240); + + //Draw background & Measure Line Width + int lineWidth = 0; + int xOffset = 0, yOffset = 0; + int h = Font::charHeight; + + for (unsigned int i = 0; i < this->text.length() + 1; i++) { + char c = this->text[i]; + + //TODO: Proper font handling. + if (c == '\t') c = ' '; + + if (c == '\n' || i == this->text.length()) { + if (lineWidth > 0) { + lineWidth += 2; + + if (lineWidth > maxLineWidth) maxLineWidth = lineWidth; + + if (bgcolor.w != 0) { + textVertices.emplace_back(glm::vec3{ -1, yOffset - 1, 0 }, bgcolor, glm::vec3(1), 0.f, glm::vec3{}, + glm::ivec4{}, glm::vec4{}); + textVertices.emplace_back(glm::vec3{ -1, yOffset + h + 1, 0 }, bgcolor, glm::vec3(1), 0.f, + glm::vec3{}, glm::ivec4{}, glm::vec4{}); + textVertices.emplace_back(glm::vec3{ lineWidth + 1, yOffset + h + 1, 0 }, bgcolor, glm::vec3(1), + 0.f, glm::vec3{}, glm::ivec4{}, glm::vec4{}); + textVertices.emplace_back(glm::vec3{ lineWidth + 1, yOffset - 1, 0 }, bgcolor, glm::vec3(1), 0.f, + glm::vec3{}, glm::ivec4{}, glm::vec4{}); + + textIndices.emplace_back(indOffset); + textIndices.emplace_back(indOffset + 1); + textIndices.emplace_back(indOffset + 2); + textIndices.emplace_back(indOffset + 2); + textIndices.emplace_back(indOffset + 3); + textIndices.emplace_back(indOffset); + + indOffset += 4; + } + yOffset += h + 2; + } + else { + yOffset += h / 2; //Pad out the height if using just newlines. + } + + lineWidth = 0; + } + else lineWidth += font.getCharWidth(c) + 1; + } + + //Draw Characters + + bool emptyLine = true; + xOffset = 0; + yOffset = 0; + + for (unsigned int i = 0; i < this->text.length() + 1; i++) { + char c = this->text[i]; + + //TODO: Proper font handling. + if (c == '\t') c = ' '; + + unsigned int h = Font::charHeight; + + if (c == '\n' || i == this->text.length()) { + yOffset += (emptyLine) ? h / 2 : h + 2; + xOffset = 0; + emptyLine = true; + continue; + } + else { + emptyLine = false; + } + + auto charWidth = font.getCharWidth(c) + 1; + auto charUVs = font.getCharUVs(c); + + for (unsigned int j = 0; j <= 1; j++) { + glm::vec3 c = { this->color.x, this->color.y, this->color.z }; + + if (j == 0) { + c *= glm::vec3{ 0.4, 0.4, 0.45 }; + xOffset += 1; + yOffset += 1; + } + else { + xOffset -= 1; + yOffset -= 1; + } + + textVertices.emplace_back(glm::vec3{ xOffset, yOffset, 0 }, glm::vec4{ charUVs.x, charUVs.y, 0, color.w }, + c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{}); + textVertices.emplace_back(glm::vec3{ xOffset, yOffset + h, 0 }, + glm::vec4{ charUVs.x, charUVs.w, 0, color.w }, c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{}); + textVertices.emplace_back(glm::vec3{ xOffset + charWidth, yOffset + h, 0 }, + glm::vec4{ charUVs.z, charUVs.w, 0, color.w }, c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{}); + textVertices.emplace_back(glm::vec3{ xOffset + charWidth, yOffset, 0 }, + glm::vec4{ charUVs.z, charUVs.y, 0, color.w }, c, 1.f, glm::vec3{}, glm::ivec4{}, glm::vec4{}); + + textIndices.emplace_back(indOffset); + textIndices.emplace_back(indOffset + 1); + textIndices.emplace_back(indOffset + 2); + textIndices.emplace_back(indOffset + 2); + textIndices.emplace_back(indOffset + 3); + textIndices.emplace_back(indOffset); + + indOffset += 4; + } + + xOffset += charWidth; + } + + auto m = std::make_unique(); + m->create(textVertices, textIndices); + + auto model = std::make_shared(); + model->fromMesh(std::move(m)); + + entity.setModel(model); } std::string GuiText::getText() { - return text; + return text; } unsigned int GuiText::getWidth() { - return maxLineWidth; + return maxLineWidth; } diff --git a/src/client/gui/basic/GuiText.h b/src/client/gui/basic/GuiText.h index 6c7bd55d..46b6dbcd 100644 --- a/src/client/gui/basic/GuiText.h +++ b/src/client/gui/basic/GuiText.h @@ -9,27 +9,32 @@ #include "client/graph/Font.h" class TextureAtlas; + class LuaGuiElement; class GuiText : public GuiComponent { -public: - GuiText() = default; - explicit GuiText(const std::string& key); - - static std::shared_ptr fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds); - - void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font); - - unsigned int getWidth(); - - void setText(std::string text); - std::string getText(); -private: - Font font; - glm::vec4 bgcolor {}; - glm::vec4 color {}; - std::string text; - - unsigned int maxLineWidth = 0; + public: + GuiText() = default; + + explicit GuiText(const std::string& key); + + static std::shared_ptr + fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds); + + void create(glm::vec2 scale, glm::vec4 padding, glm::vec4 bgcolor, glm::vec4 color, Font font); + + unsigned int getWidth(); + + void setText(std::string text); + + std::string getText(); + + private: + Font font; + glm::vec4 bgcolor{}; + glm::vec4 color{}; + std::string text; + + unsigned int maxLineWidth = 0; }; diff --git a/src/client/gui/compound/GuiImageButton.cpp b/src/client/gui/compound/GuiImageButton.cpp index 18a3a83b..fb704d3c 100644 --- a/src/client/gui/compound/GuiImageButton.cpp +++ b/src/client/gui/compound/GuiImageButton.cpp @@ -9,73 +9,75 @@ #include "client/gui/basic/GuiText.h" #include "game/atlas/asset/AtlasRef.h" -GuiImageButton::GuiImageButton(const std::string &key) : GuiRect(key) {} +GuiImageButton::GuiImageButton(const std::string& key) : GuiRect(key) {} -std::shared_ptr GuiImageButton::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) { - glm::vec2 pos = SerialGui::get(elem, "position", bounds); - glm::vec2 offset = SerialGui::get(elem, "position_anchor"); - glm::vec2 size = SerialGui::get(elem, "size", bounds); - glm::vec4 padding = SerialGui::get(elem, "padding", bounds); - - pos -= offset * size; - size -= glm::vec2 {padding.y + padding.w, padding.x + padding.z}; - - std::string background = elem.get_or("background", ""); - std::string background_hover = elem.get_or("background_hover", background); - - bool hideOverflow = elem.get_or("overflow", "visible") == "hidden"; - std::string content = elem.get_or("content", ""); - - auto button = std::make_shared(elem.key); - button->create(size, padding, textures[background], textures[background_hover]); - button->setOverflows(!hideOverflow); - button->setPos(pos); - - if (content != "") { - auto text = std::make_shared(elem.key + "__TEXT"); - text->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding, {}, {1, 1, 1, 1}, {textures, textures["font"]}); - text->setPos({6 * SerialGui::SCALE_MODIFIER, size.y / 2 - 4.5 * SerialGui::SCALE_MODIFIER}); - text->setText(content); - button->add(text); - } - - return button; +std::shared_ptr +GuiImageButton::fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds) { + glm::vec2 pos = SerialGui::get(elem, "position", bounds); + glm::vec2 offset = SerialGui::get(elem, "position_anchor"); + glm::vec2 size = SerialGui::get(elem, "size", bounds); + glm::vec4 padding = SerialGui::get(elem, "padding", bounds); + + pos -= offset * size; + size -= glm::vec2{ padding.y + padding.w, padding.x + padding.z }; + + std::string background = elem.get_or("background", ""); + std::string background_hover = elem.get_or("background_hover", background); + + bool hideOverflow = elem.get_or("overflow", "visible") == "hidden"; + std::string content = elem.get_or("content", ""); + + auto button = std::make_shared(elem.key); + button->create(size, padding, textures[background], textures[background_hover]); + button->setOverflows(!hideOverflow); + button->setPos(pos); + + if (content != "") { + auto text = std::make_shared(elem.key + "__TEXT"); + text->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding, {}, { 1, 1, 1, 1 }, { textures, textures["font"] }); + text->setPos({ 6 * SerialGui::SCALE_MODIFIER, size.y / 2 - 4.5 * SerialGui::SCALE_MODIFIER }); + text->setText(content); + button->add(text); + } + + return button; } // Texture Constructor // Creates a GuiImageButton object with two textures // defined by the 'texture' & 'hoverTexture' reference. -void GuiImageButton::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, std::shared_ptr hoverTexture) { - this->hoverTexture = hoverTexture; - GuiRect::create(scale, padding, texture); - - setCallback(GuiComponent::CallbackType::HOVER, nullptr); +void GuiImageButton::create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, + std::shared_ptr hoverTexture) { + this->hoverTexture = hoverTexture; + GuiRect::create(scale, padding, texture); + + setCallback(GuiComponent::CallbackType::HOVER, nullptr); } -void GuiImageButton::setCallback(GuiComponent::CallbackType type, const GuiComponent::callback &cb) { - if (type == CallbackType::HOVER) { - GuiComponent::setCallback(type, [&, cb](bool nowHovered, glm::ivec2 pos) { - if (cb) cb(nowHovered, pos); - if (nowHovered != hovered) this->rebuild(nowHovered); - }); - } - else GuiComponent::setCallback(type, cb); +void GuiImageButton::setCallback(GuiComponent::CallbackType type, const GuiComponent::callback& cb) { + if (type == CallbackType::HOVER) { + GuiComponent::setCallback(type, [&, cb](bool nowHovered, glm::ivec2 pos) { + if (cb) cb(nowHovered, pos); + if (nowHovered != hovered) this->rebuild(nowHovered); + }); + } + else GuiComponent::setCallback(type, cb); } void GuiImageButton::rebuild(bool hover) { - auto tex = (hover) ? (hoverTexture != nullptr) ? hoverTexture : texture : texture; - - auto mesh = std::make_unique(); - mesh->create({ - {{0, 0, 0}, {tex->uv.x, tex->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{0, 1, 0}, {tex->uv.x, tex->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{1, 1, 0}, {tex->uv.z, tex->uv.w, 0, 1}, {1, 1, 1}, true, {}, {}, {}}, - {{1, 0, 0}, {tex->uv.z, tex->uv.y, 0, 1}, {1, 1, 1}, true, {}, {}, {}} - }, {0, 1, 2, 2, 3, 0}); - - auto model = std::make_shared(); - model->fromMesh(std::move(mesh)); - - entity.setModel(model); - setScale({scale.x + padding.w + padding.y, scale.y + padding.x + padding.z}); + auto tex = (hover) ? (hoverTexture != nullptr) ? hoverTexture : texture : texture; + + auto mesh = std::make_unique(); + mesh->create({ + {{ 0, 0, 0 }, { tex->uv.x, tex->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ 0, 1, 0 }, { tex->uv.x, tex->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ 1, 1, 0 }, { tex->uv.z, tex->uv.w, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}}, + {{ 1, 0, 0 }, { tex->uv.z, tex->uv.y, 0, 1 }, { 1, 1, 1 }, true, {}, {}, {}} + }, { 0, 1, 2, 2, 3, 0 }); + + auto model = std::make_shared(); + model->fromMesh(std::move(mesh)); + + entity.setModel(model); + setScale({ scale.x + padding.w + padding.y, scale.y + padding.x + padding.z }); } \ No newline at end of file diff --git a/src/client/gui/compound/GuiImageButton.h b/src/client/gui/compound/GuiImageButton.h index 0bed59fc..845d4033 100644 --- a/src/client/gui/compound/GuiImageButton.h +++ b/src/client/gui/compound/GuiImageButton.h @@ -7,16 +7,21 @@ #include "../basic/GuiRect.h" class GuiImageButton : public GuiRect { -public: - GuiImageButton() = default; - GuiImageButton(const std::string& key); - - static std::shared_ptr fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds); - - void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, std::shared_ptr hoverTexture); - - void setCallback(CallbackType type, const callback& cb) override; -private: - void rebuild(bool hover); - std::shared_ptr hoverTexture = nullptr; + public: + GuiImageButton() = default; + + GuiImageButton(const std::string& key); + + static std::shared_ptr + fromSerialized(const LuaGuiElement& elem, TextureAtlas& textures, glm::ivec2 bounds); + + void create(glm::vec2 scale, glm::vec4 padding, std::shared_ptr texture, + std::shared_ptr hoverTexture); + + void setCallback(CallbackType type, const callback& cb) override; + + private: + void rebuild(bool hover); + + std::shared_ptr hoverTexture = nullptr; }; diff --git a/src/client/gui/compound/GuiInventoryList.cpp b/src/client/gui/compound/GuiInventoryList.cpp index f2d46813..3f7e1332 100644 --- a/src/client/gui/compound/GuiInventoryList.cpp +++ b/src/client/gui/compound/GuiInventoryList.cpp @@ -12,138 +12,139 @@ #include "game/atlas/LocalDefinitionAtlas.h" #include "client/gui/basic/GuiInventoryItem.h" -GuiInventoryList::GuiInventoryList(const std::string &key) : GuiContainer(key) {} +GuiInventoryList::GuiInventoryList(const std::string& key) : GuiContainer(key) {} std::shared_ptr GuiInventoryList::fromSerialized(const LuaGuiElement& elem, - SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs) { - - glm::vec2 pos = SerialGui::get(elem, "position", bounds); + SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs) { + + glm::vec2 pos = SerialGui::get(elem, "position", bounds); // glm::vec2 offset = SerialGui::get(elem, "position_anchor"); // glm::vec2 size = SerialGui::deserializeToken(s.tokens, "size", bounds); - glm::vec4 padding = SerialGui::get(elem, "padding", bounds); - glm::vec2 slotspc = SerialGui::get(elem, "slot_spacing", bounds); - - std::string source = elem.get_or("source", ""); - std::string list = elem.get_or("list", ""); - unsigned short start = static_cast(elem.get_or("start", 1) - 1); - unsigned short length = static_cast(elem.get_or("length", 0)); - - auto invList = refs->getInventory(source)->getList(list).l(); - auto inv = std::make_shared(elem.key); - - inv->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding * SerialGui::SCALE_MODIFIER, - slotspc * SerialGui::SCALE_MODIFIER, invList, refs.l()->getCursorList(), game, start, length); - inv->setPos(pos); - - return inv; + glm::vec4 padding = SerialGui::get(elem, "padding", bounds); + glm::vec2 slotspc = SerialGui::get(elem, "slot_spacing", bounds); + + std::string source = elem.get_or("source", ""); + std::string list = elem.get_or("list", ""); + unsigned short start = static_cast(elem.get_or("start", 1) - 1); + unsigned short length = static_cast(elem.get_or("length", 0)); + + auto invList = refs->getInventory(source)->getList(list).l(); + auto inv = std::make_shared(elem.key); + + inv->create(glm::vec2(SerialGui::SCALE_MODIFIER), padding * SerialGui::SCALE_MODIFIER, + slotspc * SerialGui::SCALE_MODIFIER, invList, refs.l()->getCursorList(), game, start, length); + inv->setPos(pos); + + return inv; } void GuiInventoryList::create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding, - InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs, - unsigned short start, unsigned short length) { - - this->list = list; - this->cursor = cursor; - this->defs = defs; - - this->start = start; - this->length = length; - - this->scale = scale; - this->padding = padding; - this->innerPadding = innerPadding; - this->hitbox = (list->getWidth() == 0 ? glm::ivec2 {} : glm::ivec2 { - padding.x + list->getWidth() * (innerPadding.x*scale.x), - padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y*scale.y) }); - - drawContents(); - myCallback = std::make_shared>(std::bind(&GuiInventoryList::drawContents, this)); - list.l()->addGuiCallback(myCallback); - - setCallback(CallbackType::PRIMARY, nullptr); - setCallback(CallbackType::SECONDARY, nullptr); - setCallback(CallbackType::HOVER, nullptr); - - hoverRect->create({}, {}, {1, 1, 1, 0.1}); + InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs, + unsigned short start, unsigned short length) { + + this->list = list; + this->cursor = cursor; + this->defs = defs; + + this->start = start; + this->length = length; + + this->scale = scale; + this->padding = padding; + this->innerPadding = innerPadding; + this->hitbox = (list->getWidth() == 0 ? glm::ivec2{} : glm::ivec2{ + padding.x + list->getWidth() * (innerPadding.x * scale.x), + padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y * scale.y) }); + + drawContents(); + myCallback = std::make_shared>(std::bind(&GuiInventoryList::drawContents, this)); + list.l()->addGuiCallback(myCallback); + + setCallback(CallbackType::PRIMARY, nullptr); + setCallback(CallbackType::SECONDARY, nullptr); + setCallback(CallbackType::HOVER, nullptr); + + hoverRect->create({}, {}, { 1, 1, 1, 0.1 }); } void GuiInventoryList::setCallback(CallbackType type, const callback& cb) { - GuiComponent::setCallback(type, [&, cb, type](bool down, glm::ivec2 pos) { - if (cb) cb(down, pos); - - if (type == GuiComponent::CallbackType::HOVER) this->hoverEvent(down, pos); - else if (down) this->interactEvent(pos, type == GuiComponent::CallbackType::PRIMARY); - }); + GuiComponent::setCallback(type, [&, cb, type](bool down, glm::ivec2 pos) { + if (cb) cb(down, pos); + + if (type == GuiComponent::CallbackType::HOVER) this->hoverEvent(down, pos); + else if (down) this->interactEvent(pos, type == GuiComponent::CallbackType::PRIMARY); + }); } void GuiInventoryList::hoverEvent(bool hovered, glm::ivec2 pos) { - pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale); - - if (hovered) { - if (!this->hovered) hoverRect->setScale({16*scale.x, 16*scale.y}); - - glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding); - slot.x = std::min(slot.x, static_cast(list->getWidth() - 1)); - slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1); - glm::ivec2 highlightPos = slot * glm::ivec2(this->scale) * this->innerPadding; - - hoverRect->setPos(highlightPos); - } - else if (this->hovered) hoverRect->setScale({}); + pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale); + + if (hovered) { + if (!this->hovered) hoverRect->setScale({ 16 * scale.x, 16 * scale.y }); + + glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding); + slot.x = std::min(slot.x, static_cast(list->getWidth() - 1)); + slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1); + glm::ivec2 highlightPos = slot * glm::ivec2(this->scale) * this->innerPadding; + + hoverRect->setPos(highlightPos); + } + else if (this->hovered) hoverRect->setScale({}); } void GuiInventoryList::interactEvent(glm::ivec2 pos, bool primary) { - if (list->getWidth() == 0) return; - - pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale); - - glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding); - slot.x = std::min(slot.x, static_cast(list->getWidth() - 1)); - slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1); - - unsigned short index = slot.x + slot.y * list->getWidth(); - - if (index >= list->getLength()) return; - - list->interact(cursor, primary, index); + if (list->getWidth() == 0) return; + + pos += glm::ivec2(glm::vec2(this->padding.x, this->padding.y) * this->scale); + + glm::ivec2 slot = pos / (glm::ivec2(this->scale) * this->innerPadding); + slot.x = std::min(slot.x, static_cast(list->getWidth() - 1)); + slot.y = std::min(slot.y, list->getLength() / list->getWidth() - 1); + + unsigned short index = slot.x + slot.y * list->getWidth(); + + if (index >= list->getLength()) return; + + list->interact(cursor, primary, index); } void GuiInventoryList::drawContents() { - if (list->getWidth() == 0) return; - unsigned short length = this->length == 0 ? list->getLength() : this->length; - - this->hitbox = glm::ivec2 { - padding.x + list->getWidth() * (innerPadding.x*scale.x), - padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y*scale.y) - }; - - empty(); - - auto fontRef = defs.l()->textures["font"]; - Font f(defs.l()->textures, fontRef); - - for (unsigned short i = 0; i < list->getLength() / list->getWidth(); i++) { - for (unsigned short j = 0; j < list->getWidth(); j++) { - unsigned short stackInd = j + i * list->getWidth(); - if (stackInd >= length) break; + if (list->getWidth() == 0) return; + unsigned short length = this->length == 0 ? list->getLength() : this->length; + + this->hitbox = glm::ivec2{ + padding.x + list->getWidth() * (innerPadding.x * scale.x), + padding.y + (list->getLength() / list->getWidth()) * (innerPadding.y * scale.y) + }; + + empty(); + + auto fontRef = defs.l()->textures["font"]; + Font f(defs.l()->textures, fontRef); + + for (unsigned short i = 0; i < list->getLength() / list->getWidth(); i++) { + for (unsigned short j = 0; j < list->getWidth(); j++) { + unsigned short stackInd = j + i * list->getWidth(); + if (stackInd >= length) break; // auto bg = std::make_shared("background_" + to_string(i) + "_" + to_string(j)); // bg->create(scale * 16.f, {}, {1, 0, 0, 0.3}); // add(bg); // bg->setPos({padding.x + j * (16*scale.x+innerPadding.x/scale.x), padding.y + i * (16*scale.y+innerPadding.y/scale.y)}); - - auto stack = list->getStack(stackInd); - if (stack.id == 0) continue; - - auto item = std::make_shared("item_" + std::to_string(i) + "_" + std::to_string(j)); - item->create(scale, stack.count, defs->getDefs().fromId(stack.id), f); - add(item); - item->setPos({padding.x + j * (16*scale.x+innerPadding.x/scale.x), padding.y + i * (16*scale.y+innerPadding.y/scale.y)}); - } - } - - add(hoverRect); + + auto stack = list->getStack(stackInd); + if (stack.id == 0) continue; + + auto item = std::make_shared("item_" + std::to_string(i) + "_" + std::to_string(j)); + item->create(scale, stack.count, defs->getDefs().fromId(stack.id), f); + add(item); + item->setPos({ padding.x + j * (16 * scale.x + innerPadding.x / scale.x), + padding.y + i * (16 * scale.y + innerPadding.y / scale.y) }); + } + } + + add(hoverRect); } GuiInventoryList::~GuiInventoryList() { - if (list) list.l()->removeGuiCallback(myCallback); + if (list) list.l()->removeGuiCallback(myCallback); } \ No newline at end of file diff --git a/src/client/gui/compound/GuiInventoryList.h b/src/client/gui/compound/GuiInventoryList.h index 0f56ab80..f65b757c 100644 --- a/src/client/gui/compound/GuiInventoryList.h +++ b/src/client/gui/compound/GuiInventoryList.h @@ -9,39 +9,47 @@ #include "util/CovariantPtr.h" class LocalSubgame; + class LuaGuiElement; + class LocalInventoryRefs; + class LocalInventoryList; class GuiInventoryList : public GuiContainer { -public: - GuiInventoryList() = default; - GuiInventoryList(const std::string& key); - ~GuiInventoryList() override; - - static std::shared_ptr fromSerialized(const LuaGuiElement& elem, - SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs); - - void create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding, - InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs, - unsigned short start = 0, unsigned short length = 0); - - void setCallback(CallbackType type, const callback& cb) override; - - void hoverEvent(bool hovered, glm::ivec2 pos); - void interactEvent(glm::ivec2 pos, bool primary); - void drawContents(); -private: - std::shared_ptr hoverRect = std::make_shared("hover_rect"); - std::shared_ptr> myCallback = nullptr; - - InventoryListPtr list; - InventoryListPtr cursor; - - unsigned short start = 0; - unsigned short length = 0; - - glm::ivec2 innerPadding; - - SubgamePtr defs = SubgamePtr(); + public: + GuiInventoryList() = default; + + GuiInventoryList(const std::string& key); + + ~GuiInventoryList() override; + + static std::shared_ptr fromSerialized(const LuaGuiElement& elem, + SubgamePtr game, glm::ivec2 bounds, InventoryRefsPtr refs); + + void create(glm::vec2 scale, glm::vec4 padding, glm::ivec2 innerPadding, + InventoryListPtr list, InventoryListPtr cursor, SubgamePtr defs, + unsigned short start = 0, unsigned short length = 0); + + void setCallback(CallbackType type, const callback& cb) override; + + void hoverEvent(bool hovered, glm::ivec2 pos); + + void interactEvent(glm::ivec2 pos, bool primary); + + void drawContents(); + + private: + std::shared_ptr hoverRect = std::make_shared("hover_rect"); + std::shared_ptr> myCallback = nullptr; + + InventoryListPtr list; + InventoryListPtr cursor; + + unsigned short start = 0; + unsigned short length = 0; + + glm::ivec2 innerPadding; + + SubgamePtr defs = SubgamePtr(); }; diff --git a/src/client/gui/compound/GuiLabelledGraph.cpp b/src/client/gui/compound/GuiLabelledGraph.cpp index 9fa0b15a..3fcbb701 100644 --- a/src/client/gui/compound/GuiLabelledGraph.cpp +++ b/src/client/gui/compound/GuiLabelledGraph.cpp @@ -4,52 +4,54 @@ #include "GuiLabelledGraph.h" -GuiLabelledGraph::GuiLabelledGraph(const std::string &key) : GuiContainer(key) {} +GuiLabelledGraph::GuiLabelledGraph(const std::string& key) : GuiContainer(key) {} -void GuiLabelledGraph::create(glm::vec2 scale, glm::vec4 padding, const std::string &title, - unsigned int graphLength, unsigned int graphScale, - std::shared_ptr graphTextureRef, Font font) { - - const static int GRAPH_PAD_X = 2; - const static int GRAPH_PAD_Y = 62; - const static int TEXT_PAD_X = 4; - const static int TEXT_PAD_Y = 8; - - this->scale = scale; - this->padding = padding; - this->title = title; - this->font = std::move(font); - this->graphTextureRef = std::move(graphTextureRef); - - auto background = std::make_shared("background"); - background->create(scale, {}, {0.1, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.1, 0.7}, {0.1, 0.1, 0.1, 0.7}); - add(background); - background->setPos({0, 0}); - - auto graph = std::make_shared("graph"); - graph->create({scale.x / (graphLength + GRAPH_PAD_X), scale.y * 0.4}, {}, this->graphTextureRef, graphLength, graphScale, true); - add(graph); - graph->setPos({GRAPH_PAD_X, GRAPH_PAD_Y}); - - auto label = std::make_shared("label"); - label->create({2, 2}, {}, {}, {1, 1, 1, 1}, this->font); - add(label); - label->setPos({TEXT_PAD_X, TEXT_PAD_Y}); - - for (float &i : history) i = 0; +void GuiLabelledGraph::create(glm::vec2 scale, glm::vec4 padding, const std::string& title, + unsigned int graphLength, unsigned int graphScale, + std::shared_ptr graphTextureRef, Font font) { + + const static int GRAPH_PAD_X = 2; + const static int GRAPH_PAD_Y = 62; + const static int TEXT_PAD_X = 4; + const static int TEXT_PAD_Y = 8; + + this->scale = scale; + this->padding = padding; + this->title = title; + this->font = std::move(font); + this->graphTextureRef = std::move(graphTextureRef); + + auto background = std::make_shared("background"); + background->create(scale, {}, { 0.1, 0.1, 0.1, 0.2 }, { 0.1, 0.1, 0.1, 0.2 }, { 0.1, 0.1, 0.1, 0.7 }, + { 0.1, 0.1, 0.1, 0.7 }); + add(background); + background->setPos({ 0, 0 }); + + auto graph = std::make_shared("graph"); + graph->create({ scale.x / (graphLength + GRAPH_PAD_X), scale.y * 0.4 }, {}, this->graphTextureRef, graphLength, + graphScale, true); + add(graph); + graph->setPos({ GRAPH_PAD_X, GRAPH_PAD_Y }); + + auto label = std::make_shared("label"); + label->create({ 2, 2 }, {}, {}, { 1, 1, 1, 1 }, this->font); + add(label); + label->setPos({ TEXT_PAD_X, TEXT_PAD_Y }); + + for (float& i : history) i = 0; } void GuiLabelledGraph::pushValue(float value) { - get("graph")->pushValue(value); - - history[ind] = value; - if (++ind >= 5) { - ind = 0; - - std::string stringVal = (value == static_cast(value)) - ? std::to_string(static_cast(value)) - : Util::floatToString(value); - - get("label")->setText(title + ": " + stringVal); - } + get("graph")->pushValue(value); + + history[ind] = value; + if (++ind >= 5) { + ind = 0; + + std::string stringVal = (value == static_cast(value)) + ? std::to_string(static_cast(value)) + : Util::floatToString(value); + + get("label")->setText(title + ": " + stringVal); + } } \ No newline at end of file diff --git a/src/client/gui/compound/GuiLabelledGraph.h b/src/client/gui/compound/GuiLabelledGraph.h index 1f6fc51a..1a3e54fe 100644 --- a/src/client/gui/compound/GuiLabelledGraph.h +++ b/src/client/gui/compound/GuiLabelledGraph.h @@ -12,22 +12,24 @@ #include "world/dim/ent/DrawableEntity.h" class GuiLabelledGraph : public GuiContainer { -public: - GuiLabelledGraph() = default; - GuiLabelledGraph(const std::string& key); - - void create(glm::vec2 scale, glm::vec4 padding, const std::string& title, - unsigned int graphLength, unsigned int graphScale, - std::shared_ptr graphTextureRef, Font font); - - void pushValue(float value); -private: - std::string title; - - std::shared_ptr graphTextureRef; - Font font; - - int ind = 0; - float history[5] {}; + public: + GuiLabelledGraph() = default; + + GuiLabelledGraph(const std::string& key); + + void create(glm::vec2 scale, glm::vec4 padding, const std::string& title, + unsigned int graphLength, unsigned int graphScale, + std::shared_ptr graphTextureRef, Font font); + + void pushValue(float value); + + private: + std::string title; + + std::shared_ptr graphTextureRef; + Font font; + + int ind = 0; + float history[5]{}; }; diff --git a/src/client/menu/MenuSandbox.cpp b/src/client/menu/MenuSandbox.cpp index 35efd52c..af25cd4f 100644 --- a/src/client/menu/MenuSandbox.cpp +++ b/src/client/menu/MenuSandbox.cpp @@ -17,189 +17,190 @@ #include "lua/modules/mSetGui.h" #include "lua/modules/mStartGame.h" -MenuSandbox::MenuSandbox(glm::ivec2 &win, Client& client, std::shared_ptr container) : - LuaParser(*client.game), - win(win), - client(client), - container(container), - luaContainer(std::dynamic_pointer_cast(container->add(std::make_shared("__lua")))), - builder(client.game->textures, client.game->models, luaContainer) {} +MenuSandbox::MenuSandbox(glm::ivec2& win, Client& client, std::shared_ptr container) : + LuaParser(*client.game), + win(win), + client(client), + container(container), + luaContainer(std::dynamic_pointer_cast(container->add(std::make_shared("__lua")))), + builder(client.game->textures, client.game->models, luaContainer) {} void MenuSandbox::reset() { - container->remove("error"); - builder.clear(true); - core = {}; - mod = {}; - lua = sol::state {}; - lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug); - - loadApi(); + container->remove("error"); + builder.clear(true); + core = {}; + mod = {}; + lua = sol::state{}; + lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug); + + loadApi(); } void MenuSandbox::loadApi() { - //Create Zepha Table - core = lua.create_table(); - lua["zepha"] = core; - core["__builtin"] = lua.create_table(); - - - modules.emplace_back(std::make_unique(Api::State::CLIENT, lua, core)); - - ClientApi::gui_element(lua); - - MenuApi::set_gui (builder, win, lua, core); - MenuApi::start_game (client, core); - - bindModules(); - - // Create sandboxed runfile() - lua["dofile"] = lua["loadfile"] = sol::nil; - lua.set_function("runfile", &MenuSandbox::runFileSandboxed, this); + //Create Zepha Table + core = lua.create_table(); + lua["zepha"] = core; + core["__builtin"] = lua.create_table(); + + + modules.emplace_back(std::make_unique(Api::State::CLIENT, lua, core)); + + ClientApi::gui_element(lua); + + MenuApi::set_gui(builder, win, lua, core); + MenuApi::start_game(client, core); + + bindModules(); + + // Create sandboxed runfile() + lua["dofile"] = lua["loadfile"] = sol::nil; + lua.set_function("runfile", &MenuSandbox::runFileSandboxed, this); } void MenuSandbox::load(const SubgameDef& subgame) { - reset(); - - try { - loadAndRunMod(subgame.subgamePath + "/../../assets/base"); - loadAndRunMod(subgame.subgamePath + "/menu"); - } - catch (const std::runtime_error& e) { - showError(e.what(), subgame.config.name); - } + reset(); + + try { + loadAndRunMod(subgame.subgamePath + "/../../assets/base"); + loadAndRunMod(subgame.subgamePath + "/menu"); + } + catch (const std::runtime_error& e) { + showError(e.what(), subgame.config.name); + } } void MenuSandbox::windowResized() { - builder.build(win); + builder.build(win); } void MenuSandbox::update(double delta) { - builder.update(); - core["__builtin"]["update_delayed_functions"](); + builder.update(); + core["__builtin"]["update_delayed_functions"](); } sol::protected_function_result MenuSandbox::runFileSandboxed(const std::string& file) { - for (LuaMod::File& f : mod.files) { - if (f.path != file) continue; - - sol::environment env(lua, sol::create, lua.globals()); - env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1); - env["_FILE"] = f.path; - env["_MODNAME"] = mod.config.name; - - return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback, - this, std::placeholders::_2), "@" + f.path, sol::load_mode::text); - } - throw std::runtime_error("Error opening '" + file + "', file not found."); + for (LuaMod::File& f : mod.files) { + if (f.path != file) continue; + + sol::environment env(lua, sol::create, lua.globals()); + env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1); + env["_FILE"] = f.path; + env["_MODNAME"] = mod.config.name; + + return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback, + this, std::placeholders::_2), "@" + f.path, sol::load_mode::text); + } + throw std::runtime_error("Error opening '" + file + "', file not found."); } -void MenuSandbox::loadAndRunMod(const std::string &modPath) { - if (!cf_file_exists(modPath.data())) throw std::runtime_error("Directory not found."); - - LuaMod mod; - std::string root = modPath + "/script"; - - std::list dirsToScan {root}; - std::list luaFiles {}; - - cf_dir_t dir; - while (!dirsToScan.empty()) { - std::string dirStr = *dirsToScan.begin(); - dirsToScan.erase(dirsToScan.begin()); - - if (!cf_file_exists(dirStr.data())) throw std::runtime_error("Missing 'script' directory."); - cf_dir_open(&dir, dirStr.data()); - - while (dir.has_next) { - // Read through files in the directory - cf_file_t scannedFile; - cf_read_file(&dir, &scannedFile); - - if (strncmp(scannedFile.name, ".", 1) != 0) { - if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); - else { - auto path = std::string_view(scannedFile.path); - if (path.rfind('.') != std::string::npos && path.rfind('.') == path.rfind(".lua")) - luaFiles.emplace_back(scannedFile.path); - } - } - cf_dir_next(&dir); - } - cf_dir_close(&dir); - } - - mod.modPath = modPath; - - for (std::string& file : luaFiles) { - size_t rootPos = file.find(root); - std::string modPath = file; - - if (rootPos == std::string::npos) - throw std::runtime_error("Attempted to access file \"" + file + "\", which is outside of the mod root."); - - modPath.erase(rootPos, root.length() + 1); - modPath.resize(modPath.size() - 4); - - std::ifstream t(file); - std::string fileStr((std::istreambuf_iterator(t)), std::istreambuf_iterator()); - - LuaMod::File f {modPath, fileStr}; - mod.files.push_back(f); - } - - std::string texPath = modPath + "/textures"; - if (cf_file_exists(texPath.data())) { - this->modAssets = client.game->textures.loadDirectory(texPath, false, true); - } - - this->mod = mod; - runFileSandboxed("init"); +void MenuSandbox::loadAndRunMod(const std::string& modPath) { + if (!cf_file_exists(modPath.data())) throw std::runtime_error("Directory not found."); + + LuaMod mod; + std::string root = modPath + "/script"; + + std::list dirsToScan{ root }; + std::list luaFiles{}; + + cf_dir_t dir; + while (!dirsToScan.empty()) { + std::string dirStr = *dirsToScan.begin(); + dirsToScan.erase(dirsToScan.begin()); + + if (!cf_file_exists(dirStr.data())) throw std::runtime_error("Missing 'script' directory."); + cf_dir_open(&dir, dirStr.data()); + + while (dir.has_next) { + // Read through files in the directory + cf_file_t scannedFile; + cf_read_file(&dir, &scannedFile); + + if (strncmp(scannedFile.name, ".", 1) != 0) { + if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); + else { + auto path = std::string_view(scannedFile.path); + if (path.rfind('.') != std::string::npos && path.rfind('.') == path.rfind(".lua")) + luaFiles.emplace_back(scannedFile.path); + } + } + cf_dir_next(&dir); + } + cf_dir_close(&dir); + } + + mod.modPath = modPath; + + for (std::string& file : luaFiles) { + size_t rootPos = file.find(root); + std::string modPath = file; + + if (rootPos == std::string::npos) + throw std::runtime_error("Attempted to access file \"" + file + "\", which is outside of the mod root."); + + modPath.erase(rootPos, root.length() + 1); + modPath.resize(modPath.size() - 4); + + std::ifstream t(file); + std::string fileStr((std::istreambuf_iterator(t)), std::istreambuf_iterator()); + + LuaMod::File f{ modPath, fileStr }; + mod.files.push_back(f); + } + + std::string texPath = modPath + "/textures"; + if (cf_file_exists(texPath.data())) { + this->modAssets = client.game->textures.loadDirectory(texPath, false, true); + } + + this->mod = mod; + runFileSandboxed("init"); } void MenuSandbox::showError(const std::string& what, const std::string& subgame) { - const std::string errPrefixText = "Encountered an error while loading the menu for " + subgame + " ;-;"; - Font f(client.game->textures, client.game->textures["font"]); - - auto errWrap = std::make_shared("error"); - container->add(errWrap); - - auto errPrefix = std::make_shared("error_text"); - errPrefix->create({3, 3}, {}, {0.7, 0, 0.3, 1}, {1, 1, 1, 1}, f); - errPrefix->setText(errPrefixText); - errPrefix->setPos({8, 16}); - errWrap->add(errPrefix); - - auto errMsg = std::make_shared("error_text"); - errMsg->create({3, 3}, {}, {}, {1, 0.5, 0.6, 1}, f); - errMsg->setText(what); - errMsg->setPos({8, 52}); - errWrap->add(errMsg); + const std::string errPrefixText = "Encountered an error while loading the menu for " + subgame + " ;-;"; + Font f(client.game->textures, client.game->textures["font"]); + + auto errWrap = std::make_shared("error"); + container->add(errWrap); + + auto errPrefix = std::make_shared("error_text"); + errPrefix->create({ 3, 3 }, {}, { 0.7, 0, 0.3, 1 }, { 1, 1, 1, 1 }, f); + errPrefix->setText(errPrefixText); + errPrefix->setPos({ 8, 16 }); + errWrap->add(errPrefix); + + auto errMsg = std::make_shared("error_text"); + errMsg->create({ 3, 3 }, {}, {}, { 1, 0.5, 0.6, 1 }, f); + errMsg->setText(what); + errMsg->setPos({ 8, 52 }); + errWrap->add(errMsg); } sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) const { - sol::error err = r; - std::string errString = err.what(); - - try { - std::string::size_type lineNumStart = errString.find(':'); - if (lineNumStart == std::string::npos) throw std::out_of_range("Improperly formatted error. [0]"); - std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); - if (lineNumEnd == std::string::npos) throw std::out_of_range("Improperly formatted error. [1]"); - - std::string fileName = errString.substr(0, lineNumStart); - int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); - - for (const LuaMod::File& file : mod.files) if (file.path == fileName) - throw std::runtime_error(ErrorFormatter::formatError(fileName, lineNum, errString, file.file)); - - throw std::out_of_range("Error thrown outside of handled files. [2]"); - } - catch (const std::runtime_error& e) { - std::cout << Log::err << e.what() << std::endl; - throw; - } - catch (const std::out_of_range& e) { - std::cout << Log::err << "Failed to format error, " << e.what() << Log::endl; - throw std::runtime_error(errString); - } + sol::error err = r; + std::string errString = err.what(); + + try { + std::string::size_type lineNumStart = errString.find(':'); + if (lineNumStart == std::string::npos) throw std::out_of_range("Improperly formatted error. [0]"); + std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); + if (lineNumEnd == std::string::npos) throw std::out_of_range("Improperly formatted error. [1]"); + + std::string fileName = errString.substr(0, lineNumStart); + int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); + + for (const LuaMod::File& file : mod.files) + if (file.path == fileName) + throw std::runtime_error(ErrorFormatter::formatError(fileName, lineNum, errString, file.file)); + + throw std::out_of_range("Error thrown outside of handled files. [2]"); + } + catch (const std::runtime_error& e) { + std::cout << Log::err << e.what() << std::endl; + throw; + } + catch (const std::out_of_range& e) { + std::cout << Log::err << "Failed to format error, " << e.what() << Log::endl; + throw std::runtime_error(errString); + } } diff --git a/src/client/menu/MenuSandbox.h b/src/client/menu/MenuSandbox.h index 07bb153b..f9eb18ff 100644 --- a/src/client/menu/MenuSandbox.h +++ b/src/client/menu/MenuSandbox.h @@ -10,37 +10,46 @@ #include "client/gui/GuiBuilder.h" class Client; + class Subgame; + class AtlasRef; + class SubgameDef; + class GuiContainer; class MenuSandbox : LuaParser { -public: - MenuSandbox(glm::ivec2& window, Client& client, std::shared_ptr container); - void load(const SubgameDef& subgame); - - void update(double delta) override; - void windowResized(); - - using LuaParser::update; -private: - void reset(); - void loadApi(); - void loadAndRunMod(const std::string& modPath); - - void showError(const std::string& what, const std::string& subgame); - - sol::protected_function_result runFileSandboxed(const std::string& file); - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override; - - LuaMod mod {}; - std::vector> modAssets {}; - - std::shared_ptr container = nullptr; - std::shared_ptr luaContainer = nullptr; - GuiBuilder builder; - - Client& client; - glm::ivec2& win; + public: + MenuSandbox(glm::ivec2& window, Client& client, std::shared_ptr container); + + void load(const SubgameDef& subgame); + + void update(double delta) override; + + void windowResized(); + + using LuaParser::update; + private: + void reset(); + + void loadApi(); + + void loadAndRunMod(const std::string& modPath); + + void showError(const std::string& what, const std::string& subgame); + + sol::protected_function_result runFileSandboxed(const std::string& file); + + virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override; + + LuaMod mod{}; + std::vector> modAssets{}; + + std::shared_ptr container = nullptr; + std::shared_ptr luaContainer = nullptr; + GuiBuilder builder; + + Client& client; + glm::ivec2& win; }; diff --git a/src/client/menu/SubgameConfig.h b/src/client/menu/SubgameConfig.h index 51e749bb..f04a8e60 100644 --- a/src/client/menu/SubgameConfig.h +++ b/src/client/menu/SubgameConfig.h @@ -7,7 +7,7 @@ #include struct SubgameConfig { - std::string name; - std::string description; - std::string version; + std::string name; + std::string description; + std::string version; }; \ No newline at end of file diff --git a/src/client/menu/SubgameDef.h b/src/client/menu/SubgameDef.h index d064f6eb..574f70db 100644 --- a/src/client/menu/SubgameDef.h +++ b/src/client/menu/SubgameDef.h @@ -11,8 +11,8 @@ class AtlasRef; class SubgameDef { -public: - std::shared_ptr iconRef = nullptr; - SubgameConfig config {}; - std::string subgamePath = ""; + public: + std::shared_ptr iconRef = nullptr; + SubgameConfig config{}; + std::string subgamePath = ""; }; diff --git a/src/client/scene/ConnectScene.cpp b/src/client/scene/ConnectScene.cpp index 69fee691..888c4249 100644 --- a/src/client/scene/ConnectScene.cpp +++ b/src/client/scene/ConnectScene.cpp @@ -25,228 +25,222 @@ * @param addr - The server address to connect to. */ -ConnectScene::ConnectScene(Client &client, Address addr) : Scene(client), - connection(client.connection) { - - client.renderer.setClearColor(10, 10, 10); - - Font f(client.game->textures, client.game->textures["font"]); - - auto statusText = std::make_shared("statusText"); - statusText->create({2, 2}, {}, {}, {1, 1, 1, 1}, f); - statusText->setText("Connecting..."); - statusText->setPos({32, 24}); - components.add(statusText); - - auto loadBar = std::make_shared("loadBar"); - loadBar->create({1, 32}, {}, {0.17, 0.75, 0.93, 1}); - loadBar->setPos({0, client.renderer.window.getSize().y - 32}); - components.add(loadBar); - - connection.attemptConnect(std::move(addr)); - - client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) { - components.get("loadBar")->setPos({0, win.y - 32}); - }); +ConnectScene::ConnectScene(Client& client, Address addr) : Scene(client), + connection(client.connection) { + + client.renderer.setClearColor(10, 10, 10); + + Font f(client.game->textures, client.game->textures["font"]); + + auto statusText = std::make_shared("statusText"); + statusText->create({ 2, 2 }, {}, {}, { 1, 1, 1, 1 }, f); + statusText->setText("Connecting..."); + statusText->setPos({ 32, 24 }); + components.add(statusText); + + auto loadBar = std::make_shared("loadBar"); + loadBar->create({ 1, 32 }, {}, { 0.17, 0.75, 0.93, 1 }); + loadBar->setPos({ 0, client.renderer.window.getSize().y - 32 }); + components.add(loadBar); + + connection.attemptConnect(std::move(addr)); + + client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) { + components.get("loadBar")->setPos({ 0, win.y - 32 }); + }); } void ConnectScene::update() { - client.game->textures.update(); - - switch (connectState) { - default: - throw std::runtime_error("Invalid connection state."); - - case State::DONE: - case State::FAILED_CONNECT: - break; - - case State::CONNECTING: - handleConnecting(); - break; - - case State::PROPERTIES: { - components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.1, 32}); - - ENetEvent e; - if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { - PacketView p(e.packet); - - if (p.type == Packet::Type::SERVER_INFO) { - auto statusText = components.get("statusText"); - statusText->setText(statusText->getText() + "Received server properties.\n"); - - // TODO: Reimplement this somewhere or something. + client.game->textures.update(); + + switch (connectState) { + default:throw std::runtime_error("Invalid connection state."); + + case State::DONE: + case State::FAILED_CONNECT:break; + + case State::CONNECTING:handleConnecting(); + break; + + case State::PROPERTIES: { + components.get("loadBar")->setScale({ client.renderer.window.getSize().x * 0.1, 32 }); + + ENetEvent e; + if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { + PacketView p(e.packet); + + if (p.type == Packet::Type::SERVER_INFO) { + auto statusText = components.get("statusText"); + statusText->setText(statusText->getText() + "Received server properties.\n"); + + // TODO: Reimplement this somewhere or something. // state.seed = p.d.read(); - - connectState = State::IDENTIFIER_LIST; - Packet resp(Packet::Type::BLOCK_IDENTIFIER_LIST); - resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); - } - } - break; - } - - case State::IDENTIFIER_LIST: { - components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.2, 32}); - - ENetEvent e; - if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { - PacketView p(e.packet); - - if (p.type == Packet::Type::BLOCK_IDENTIFIER_LIST) { - auto statusText = components.get("statusText"); - statusText->setText(statusText->getText() + "Received block index-identifier table.\n"); - - client.game->getDefs().setIdentifiers(p.d.read>()); - - Packet resp(Packet::Type::BIOME_IDENTIFIER_LIST); - resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); - } - else if (p.type == Packet::Type::BIOME_IDENTIFIER_LIST) { - auto statusText = components.get("statusText"); - statusText->setText(statusText->getText() + "Received biome index-identifier table.\nDownloading mods...\n"); - - client.game->getBiomes().setIdentifiers(p.d.read>()); - - connectState = State::MODS; - Packet resp(Packet::Type::MODS); - resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); - } - } - break; - } - - case State::MODS: { - components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.4, 32}); - ENetEvent e; - if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { - PacketView p(e.packet); - - auto statusText = components.get("statusText"); - - if (p.type == Packet::Type::MODS) { - auto luaMod = LuaMod::fromPacket(p); - statusText->setText(statusText->getText() + "Received mod " + luaMod.config.name + ".\n"); - client.game->getParser().getHandler().addLuaMod(std::move(luaMod)); - } - else if (p.type == Packet::Type::MOD_ORDER) { - client.game->getParser().getHandler().setModsOrder(p.d.read>()); - - statusText->setText(statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n"); - - connectState = State::MEDIA; - Packet resp(Packet::Type::MEDIA); - resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); - } - } - break; - } - - case State::MEDIA: { - components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.6, 32}); - - ENetEvent e; - if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { - PacketView p(e.packet); - - auto statusText = components.get("statusText"); - - if (p.type == Packet::Type::MEDIA) { - AssetType t = static_cast(p.d.read()); - unsigned int count = 0; - - while (t != AssetType::END) { - std::string assetName = p.d.read(); - - if (t == AssetType::TEXTURE) { - int width = p.d.read(); - int height = p.d.read(); - - std::string data = p.d.read(); - std::string uncompressed = gzip::decompress(data.data(), data.length()); - - client.game->textures.addImage( - reinterpret_cast(const_cast(uncompressed.data())), - assetName, true, width, height); - } - else if (t == AssetType::MODEL) { - std::string format = p.d.read(); - std::string data = p.d.read(); - - client.game->models.models.insert({assetName, SerializedModel{assetName, data, format}}); - } - - t = static_cast(p.d.read()); - count++; - } - - statusText->setText(statusText->getText() + "Received " + std::to_string(count) + "x media files.\n"); - } - else if (p.type == Packet::Type::MEDIA_DONE) { - components.get("loadBar")->setScale({client.renderer.window.getSize().x, 32}); - statusText->setText(statusText->getText() + "Done downloading media.\nJoining world...\n"); - - connectState = State::DONE; - client.scene.setScene(std::make_unique(client)); - } - } - break; - } - } + + connectState = State::IDENTIFIER_LIST; + Packet resp(Packet::Type::BLOCK_IDENTIFIER_LIST); + resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); + } + } + break; + } + + case State::IDENTIFIER_LIST: { + components.get("loadBar")->setScale({ client.renderer.window.getSize().x * 0.2, 32 }); + + ENetEvent e; + if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { + PacketView p(e.packet); + + if (p.type == Packet::Type::BLOCK_IDENTIFIER_LIST) { + auto statusText = components.get("statusText"); + statusText->setText(statusText->getText() + "Received block index-identifier table.\n"); + + client.game->getDefs().setIdentifiers(p.d.read>()); + + Packet resp(Packet::Type::BIOME_IDENTIFIER_LIST); + resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); + } + else if (p.type == Packet::Type::BIOME_IDENTIFIER_LIST) { + auto statusText = components.get("statusText"); + statusText->setText( + statusText->getText() + "Received biome index-identifier table.\nDownloading mods...\n"); + + client.game->getBiomes().setIdentifiers(p.d.read>()); + + connectState = State::MODS; + Packet resp(Packet::Type::MODS); + resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); + } + } + break; + } + + case State::MODS: { + components.get("loadBar")->setScale({ client.renderer.window.getSize().x * 0.4, 32 }); + ENetEvent e; + if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { + PacketView p(e.packet); + + auto statusText = components.get("statusText"); + + if (p.type == Packet::Type::MODS) { + auto luaMod = LuaMod::fromPacket(p); + statusText->setText(statusText->getText() + "Received mod " + luaMod.config.name + ".\n"); + client.game->getParser().getHandler().addLuaMod(std::move(luaMod)); + } + else if (p.type == Packet::Type::MOD_ORDER) { + client.game->getParser().getHandler().setModsOrder(p.d.read>()); + + statusText->setText( + statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n"); + + connectState = State::MEDIA; + Packet resp(Packet::Type::MEDIA); + resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); + } + } + break; + } + + case State::MEDIA: { + components.get("loadBar")->setScale({ client.renderer.window.getSize().x * 0.6, 32 }); + + ENetEvent e; + if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) { + PacketView p(e.packet); + + auto statusText = components.get("statusText"); + + if (p.type == Packet::Type::MEDIA) { + AssetType t = static_cast(p.d.read()); + unsigned int count = 0; + + while (t != AssetType::END) { + std::string assetName = p.d.read(); + + if (t == AssetType::TEXTURE) { + int width = p.d.read(); + int height = p.d.read(); + + std::string data = p.d.read(); + std::string uncompressed = gzip::decompress(data.data(), data.length()); + + client.game->textures.addImage( + reinterpret_cast(const_cast(uncompressed.data())), + assetName, true, width, height); + } + else if (t == AssetType::MODEL) { + std::string format = p.d.read(); + std::string data = p.d.read(); + + client.game->models.models.insert({ assetName, SerializedModel{ assetName, data, format }}); + } + + t = static_cast(p.d.read()); + count++; + } + + statusText->setText(statusText->getText() + "Received " + std::to_string(count) + "x media files.\n"); + } + else if (p.type == Packet::Type::MEDIA_DONE) { + components.get("loadBar")->setScale({ client.renderer.window.getSize().x, 32 }); + statusText->setText(statusText->getText() + "Done downloading media.\nJoining world...\n"); + + connectState = State::DONE; + client.scene.setScene(std::make_unique(client)); + } + } + break; + } + } } void ConnectScene::handleConnecting() { - Packet resp(Packet::Type::SERVER_INFO); - auto statusText = components.get("statusText"); - - switch (connection.getConnectionStatus()) { - default: - throw std::runtime_error("Uncaught connection error."); - - case ServerConnection::State::ENET_ERROR: - throw std::runtime_error("Enet Initialization error."); - break; - - case ServerConnection::State::FAILED_CONNECT: - connectState = State::FAILED_CONNECT; - statusText->setText(statusText->getText() + "\nFailed to connect :(\n"); - break; - - case ServerConnection::State::ATTEMPTING_CONNECT: - connection.processConnecting(); - - dotsTime += client.getDelta(); - if (dotsTime > 1) { - dotsTime -= 1; - statusText->setText(statusText->getText() + "."); - } - - break; - - case ServerConnection::State::CONNECTED: - connectState = State::PROPERTIES; - statusText->setText(statusText->getText() + " Connected!~\n"); - - resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); - - break; - } + Packet resp(Packet::Type::SERVER_INFO); + auto statusText = components.get("statusText"); + + switch (connection.getConnectionStatus()) { + default:throw std::runtime_error("Uncaught connection error."); + + case ServerConnection::State::ENET_ERROR:throw std::runtime_error("Enet Initialization error."); + break; + + case ServerConnection::State::FAILED_CONNECT:connectState = State::FAILED_CONNECT; + statusText->setText(statusText->getText() + "\nFailed to connect :(\n"); + break; + + case ServerConnection::State::ATTEMPTING_CONNECT:connection.processConnecting(); + + dotsTime += client.getDelta(); + if (dotsTime > 1) { + dotsTime -= 1; + statusText->setText(statusText->getText() + "."); + } + + break; + + case ServerConnection::State::CONNECTED:connectState = State::PROPERTIES; + statusText->setText(statusText->getText() + " Connected!~\n"); + + resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT); + + break; + } } void ConnectScene::draw() { - Renderer& renderer = client.renderer; - - renderer.beginChunkDeferredCalls(); - renderer.endDeferredCalls(); - renderer.beginGUIDrawCalls(); - renderer.enableTexture(&client.game->textures.atlasTexture); - - components.draw(renderer); - - renderer.swapBuffers(); + Renderer& renderer = client.renderer; + + renderer.beginChunkDeferredCalls(); + renderer.endDeferredCalls(); + renderer.beginGUIDrawCalls(); + renderer.enableTexture(&client.game->textures.atlasTexture); + + components.draw(renderer); + + renderer.swapBuffers(); } void ConnectScene::cleanup() { - client.renderer.window.removeResizeCallback("scene"); + client.renderer.window.removeResizeCallback("scene"); } \ No newline at end of file diff --git a/src/client/scene/ConnectScene.h b/src/client/scene/ConnectScene.h index 5b549b2c..bb75c06d 100644 --- a/src/client/scene/ConnectScene.h +++ b/src/client/scene/ConnectScene.h @@ -9,33 +9,36 @@ #include "client/gui/basic/GuiContainer.h" class ServerConnection; + class Address; class ConnectScene : public Scene { -public: - enum class State { - CONNECTING, - FAILED_CONNECT, - PROPERTIES, - IDENTIFIER_LIST, - MODS, - MEDIA, - DONE - }; - - ConnectScene(Client& state, Address addr); - - void update() override; - void draw() override; - void cleanup() override; - - void handleConnecting(); - -private: - State connectState = State::CONNECTING; - ServerConnection& connection; - - GuiContainer components; - - double dotsTime = 0; + public: + enum class State { + CONNECTING, + FAILED_CONNECT, + PROPERTIES, + IDENTIFIER_LIST, + MODS, + MEDIA, + DONE + }; + + ConnectScene(Client& state, Address addr); + + void update() override; + + void draw() override; + + void cleanup() override; + + void handleConnecting(); + + private: + State connectState = State::CONNECTING; + ServerConnection& connection; + + GuiContainer components; + + double dotsTime = 0; }; diff --git a/src/client/scene/GameScene.cpp b/src/client/scene/GameScene.cpp index 8f360602..2c09541a 100644 --- a/src/client/scene/GameScene.cpp +++ b/src/client/scene/GameScene.cpp @@ -9,73 +9,73 @@ #include "client/graph/Renderer.h" GameScene::GameScene(Client& client) : Scene(client), - world(std::make_shared(client.game, client.connection, client.renderer)), - debugGui(client.renderer.window.getSize(), client.game, world) { - - Packet r(Packet::Type::CONNECT_DATA_RECVD); - r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT); - - world.l()->connect(); - client.game->init(world, world.l()->getPlayer(), client); - world.l()->updatePlayerDimension(); - - client.renderer.window.addResizeCallback("gamescene", Util::bind_this(&debugGui, &DebugGui::bufferResized)); - client.renderer.setClearColor(148, 194, 240); - client.renderer.window.input.lockMouse(true); + world(std::make_shared(client.game, client.connection, client.renderer)), + debugGui(client.renderer.window.getSize(), client.game, world) { + + Packet r(Packet::Type::CONNECT_DATA_RECVD); + r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT); + + world.l()->connect(); + client.game->init(world, world.l()->getPlayer(), client); + world.l()->updatePlayerDimension(); + + client.renderer.window.addResizeCallback("gamescene", Util::bind_this(&debugGui, &DebugGui::bufferResized)); + client.renderer.setClearColor(148, 194, 240); + client.renderer.window.input.lockMouse(true); } void GameScene::update() { - Window& window = client.renderer.window; - - client.game->update(client.getDelta()); - world->update(client.getDelta()); - - for (auto entity : entities) entity->update(client.getDelta()); - - double lastFps = 1 / client.getDelta(); - debugGui.update(world.l()->getPlayer().l(), lastFps, world.l()->getActiveDimension().l()->getMeshChunkCount(), - drawCalls, world.l()->getNet().serverSideChunkGens, world.l()->getNet().recvPackets); - - world.l()->getNet().serverSideChunkGens = 0; - world.l()->getNet().recvPackets = 0; - - if (window.input.keyPressed(GLFW_KEY_F1)) { - hudVisible = !hudVisible; - debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1); - world.l()->getPlayer().l()->setHudVisible(hudVisible); - } - - if (window.input.keyPressed(GLFW_KEY_F3)) { - debugVisible = !debugVisible; - debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1); - } + Window& window = client.renderer.window; + + client.game->update(client.getDelta()); + world->update(client.getDelta()); + + for (auto entity : entities) entity->update(client.getDelta()); + + double lastFps = 1 / client.getDelta(); + debugGui.update(world.l()->getPlayer().l(), lastFps, world.l()->getActiveDimension().l()->getMeshChunkCount(), + drawCalls, world.l()->getNet().serverSideChunkGens, world.l()->getNet().recvPackets); + + world.l()->getNet().serverSideChunkGens = 0; + world.l()->getNet().recvPackets = 0; + + if (window.input.keyPressed(GLFW_KEY_F1)) { + hudVisible = !hudVisible; + debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1); + world.l()->getPlayer().l()->setHudVisible(hudVisible); + } + + if (window.input.keyPressed(GLFW_KEY_F3)) { + debugVisible = !debugVisible; + debugGui.changeVisibilityState(hudVisible ? debugVisible ? 0 : 2 : 1); + } } void GameScene::draw() { - Renderer& renderer = client.renderer; - Camera& camera = renderer.camera; - - renderer.beginChunkDeferredCalls(); - renderer.enableTexture(&client.game->textures.atlasTexture); - - drawCalls = world.l()->renderChunks(renderer); - - renderer.beginEntityDeferredCalls(); - - for (auto entity : entities) entity->draw(renderer); - world.l()->renderEntities(renderer); - - renderer.endDeferredCalls(); - renderer.beginGUIDrawCalls(); - renderer.enableTexture(&client.game->textures.atlasTexture); - - world.l()->getPlayer().l()->drawHud(renderer); - debugGui.draw(renderer); - world.l()->getPlayer().l()->drawMenu(renderer); - - renderer.swapBuffers(); + Renderer& renderer = client.renderer; + Camera& camera = renderer.camera; + + renderer.beginChunkDeferredCalls(); + renderer.enableTexture(&client.game->textures.atlasTexture); + + drawCalls = world.l()->renderChunks(renderer); + + renderer.beginEntityDeferredCalls(); + + for (auto entity : entities) entity->draw(renderer); + world.l()->renderEntities(renderer); + + renderer.endDeferredCalls(); + renderer.beginGUIDrawCalls(); + renderer.enableTexture(&client.game->textures.atlasTexture); + + world.l()->getPlayer().l()->drawHud(renderer); + debugGui.draw(renderer); + world.l()->getPlayer().l()->drawMenu(renderer); + + renderer.swapBuffers(); } void GameScene::cleanup() { - client.renderer.window.removeResizeCallback("gamescene"); + client.renderer.window.removeResizeCallback("gamescene"); } diff --git a/src/client/scene/GameScene.h b/src/client/scene/GameScene.h index 6ccb8acf..f3f20ab1 100644 --- a/src/client/scene/GameScene.h +++ b/src/client/scene/GameScene.h @@ -13,25 +13,27 @@ #include "client/conn/ClientNetworkInterpreter.h" class LocalSubgame; + class Drawable; class GameScene : public Scene { -public: - GameScene(Client& client); - - void update() override; - void draw() override; - - void cleanup() override; - -public: - WorldPtr world; - - DebugGui debugGui; - std::vector entities; - int drawCalls = 0; - - bool debugVisible = true; - bool hudVisible = true; + public: + GameScene(Client& client); + + void update() override; + + void draw() override; + + void cleanup() override; + + public: + WorldPtr world; + + DebugGui debugGui; + std::vector entities; + int drawCalls = 0; + + bool debugVisible = true; + bool hudVisible = true; }; diff --git a/src/client/scene/LuaErrorScene.cpp b/src/client/scene/LuaErrorScene.cpp index 8683faf1..7f338f3b 100644 --- a/src/client/scene/LuaErrorScene.cpp +++ b/src/client/scene/LuaErrorScene.cpp @@ -10,52 +10,52 @@ #include "client/gui/basic/GuiRect.h" #include "client/gui/basic/GuiText.h" -LuaErrorScene::LuaErrorScene(Client& client, const std::string &err) : Scene(client), err(err) { - client.renderer.setClearColor(0, 0, 0); - client.renderer.window.input.lockMouse(false); - - Font f(client.game->textures, client.game->textures["font"]); - glm::ivec2 win = client.renderer.window.getSize(); - - auto container = std::make_shared("container"); - container->create({800, 500}, {}, {0.05, 0.05, 0.05, 1}); - container->setPos({win.x / 2 - 800 / 2, win.y / 2 - 500 / 2}); - components.add(container); - - auto titleText = std::make_shared("titleText"); - titleText->create({3, 3}, {}, {}, {1, 0.4, 0.5, 1}, f); - titleText->setText("The Zepha sandbox has encountered an error."); - titleText->setPos({16, 12}); - container->add(titleText); - - auto errorText = std::make_shared("errorText"); - errorText->create({2, 2}, {}, {}, {0.85, 0.85, 0.85, 1}, f); - errorText->setText(err); - errorText->setPos({16, 48}); - container->add(errorText); - - client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) { - components.get("container")->setPos({win.x / 2 - 800 / 2, win.y / 2 - 500 / 2}); - }); +LuaErrorScene::LuaErrorScene(Client& client, const std::string& err) : Scene(client), err(err) { + client.renderer.setClearColor(0, 0, 0); + client.renderer.window.input.lockMouse(false); + + Font f(client.game->textures, client.game->textures["font"]); + glm::ivec2 win = client.renderer.window.getSize(); + + auto container = std::make_shared("container"); + container->create({ 800, 500 }, {}, { 0.05, 0.05, 0.05, 1 }); + container->setPos({ win.x / 2 - 800 / 2, win.y / 2 - 500 / 2 }); + components.add(container); + + auto titleText = std::make_shared("titleText"); + titleText->create({ 3, 3 }, {}, {}, { 1, 0.4, 0.5, 1 }, f); + titleText->setText("The Zepha sandbox has encountered an error."); + titleText->setPos({ 16, 12 }); + container->add(titleText); + + auto errorText = std::make_shared("errorText"); + errorText->create({ 2, 2 }, {}, {}, { 0.85, 0.85, 0.85, 1 }, f); + errorText->setText(err); + errorText->setPos({ 16, 48 }); + container->add(errorText); + + client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) { + components.get("container")->setPos({ win.x / 2 - 800 / 2, win.y / 2 - 500 / 2 }); + }); } void LuaErrorScene::update() { - client.game->textures.update(); + client.game->textures.update(); } void LuaErrorScene::draw() { - Renderer& renderer = client.renderer; - - renderer.beginChunkDeferredCalls(); - renderer.endDeferredCalls(); - renderer.beginGUIDrawCalls(); - renderer.enableTexture(&client.game->textures.atlasTexture); - - components.draw(renderer); - - renderer.swapBuffers(); + Renderer& renderer = client.renderer; + + renderer.beginChunkDeferredCalls(); + renderer.endDeferredCalls(); + renderer.beginGUIDrawCalls(); + renderer.enableTexture(&client.game->textures.atlasTexture); + + components.draw(renderer); + + renderer.swapBuffers(); } void LuaErrorScene::cleanup() { - client.renderer.window.removeResizeCallback("scene"); + client.renderer.window.removeResizeCallback("scene"); } \ No newline at end of file diff --git a/src/client/scene/LuaErrorScene.h b/src/client/scene/LuaErrorScene.h index 6ddb58e3..1d50ebc1 100644 --- a/src/client/scene/LuaErrorScene.h +++ b/src/client/scene/LuaErrorScene.h @@ -9,14 +9,16 @@ #include "client/gui/basic/GuiContainer.h" class LuaErrorScene : public Scene { -public: - LuaErrorScene(Client& client, const std::string& err); - - void update() override; - void draw() override; - void cleanup() override; - -private: - GuiContainer components; - const std::string err; + public: + LuaErrorScene(Client& client, const std::string& err); + + void update() override; + + void draw() override; + + void cleanup() override; + + private: + GuiContainer components; + const std::string err; }; diff --git a/src/client/scene/MainMenuScene.cpp b/src/client/scene/MainMenuScene.cpp index 548c89ff..4532e069 100644 --- a/src/client/scene/MainMenuScene.cpp +++ b/src/client/scene/MainMenuScene.cpp @@ -20,219 +20,232 @@ #include "ConnectScene.h" MainMenuScene::MainMenuScene(Client& client) : - Scene(client), - components(std::make_unique()), - menuContainer(std::make_shared("__menu")), - sandbox(sandboxArea, client, menuContainer) { - - client.renderer.setClearColor(0, 0, 0); - client.renderer.window.input.lockMouse(false); - - Font f(client.game->textures, client.game->textures["font"]); - win = client.renderer.window.getSize(); - sandboxArea = win - glm::ivec2(0, 18 * GS); - - components->add(menuContainer); - - branding = std::make_shared("zephaBranding"); - components->add(branding); - { - auto zephaText = std::make_shared("zephaText"); - zephaText->create({GS, GS}, {}, {}, {1, 1, 1, 1}, f); - zephaText->setText("Zepha"); - branding->add(zephaText); - - auto alphaText = std::make_shared("alphaText"); - alphaText->create({GS, GS}, {}, {}, {1, 0.5, 0.7, 1}, f); - alphaText->setText("ALPHA"); - alphaText->setPos({25*GS, 0}); - branding->add(alphaText); - } - - navigationBar = std::make_shared("navigationBar"); - navigationBar->add(std::make_shared("navigationBarBg")); - navigationBar->add(std::make_shared("navigationBarIcons")); - - auto navigationBarIcons = navigationBar->get("navigationBarIcons"); - - components->add(navigationBar); - { - auto settingsButton = std::make_shared("settingsButton"); - settingsButton->create({16 * GS, 16 * GS}, {}, - client.game->textures["crop(0, 0, 16, 16, menu_flag_settings)"], - client.game->textures["crop(16, 0, 16, 16, menu_flag_settings)"]); - - navigationBar->get("navigationBarIcons")->add(settingsButton); - - auto closeButton = std::make_shared("closeButton"); - closeButton->create({16 * GS, 16 * GS}, {}, - client.game->textures["crop(0, 0, 16, 16, menu_flag_quit)"], - client.game->textures["crop(16, 0, 16, 16, menu_flag_quit)"]); - - closeButton->setCallback(GuiComponent::CallbackType::PRIMARY, [](bool down, glm::ivec2) { if (down) exit(0); }); - navigationBar->get("navigationBarIcons")->add(closeButton); - - auto serversButton = std::make_shared("serversButton"); - serversButton->create({16 * GS, 16 * GS}, {}, - client.game->textures["crop(0, 0, 16, 16, menu_flag_multiplayer)"], - client.game->textures["crop(16, 0, 16, 16, menu_flag_multiplayer)"]); - - serversButton->setPos({GS, GS}); - navigationBarIcons->add(serversButton); - - auto contentButton = std::make_shared("contentButton"); - contentButton->create({16 * GS, 16 * GS}, {}, - client.game->textures["crop(0, 0, 16, 16, menu_flag_content)"], - client.game->textures["crop(16, 0, 16, 16, menu_flag_content)"]); - - contentButton->setPos({GS + GS * 18, GS}); - contentButton->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) { - if (!down) return; - client.scene.setScene(std::make_unique(client, Address { "127.0.0.1" })); - }); - - navigationBarIcons->add(contentButton); - - auto divider = std::make_shared("divider"); - divider->create({GS, GS * 10}, {}, {1, 1, 1, 0.3}); - divider->setPos({GS * 2 + GS * 18 * 2, GS * 4}); - navigationBarIcons->add(divider); - - findSubgames(); - - for (unsigned int i = 0; i < subgames.size(); i++) { - auto &subgame = subgames[i]; - auto button = std::make_shared(subgame.config.name); - - button->create({16 * GS, 16 * GS}, {}, - client.game->textures["crop(0, 0, 16, 16, " + subgame.iconRef->name + ")"], - client.game->textures["crop(16, 0, 16, 16, " + subgame.iconRef->name + ")"]); - - button->setPos({GS * 7 + GS * 18 * (i + 2), GS}); - button->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) { - if (!down) return; - selectedSubgame = &subgame; - sandbox.load(*selectedSubgame); - }); - - navigationBarIcons->add(button); - } - } - - if (subgames.size() > 0) { - selectedSubgame = &subgames[0]; - sandbox.load(*selectedSubgame); - } - - positionElements(); - - client.renderer.window.addResizeCallback("mainmenu", [&](glm::ivec2 win) { - this->win = win; - sandboxArea = win - glm::ivec2(0, 18 * GS); - positionElements(); - }); + Scene(client), + components(std::make_unique()), + menuContainer(std::make_shared("__menu")), + sandbox(sandboxArea, client, menuContainer) { + + client.renderer.setClearColor(0, 0, 0); + client.renderer.window.input.lockMouse(false); + + Font f(client.game->textures, client.game->textures["font"]); + win = client.renderer.window.getSize(); + sandboxArea = win - glm::ivec2(0, 18 * GS); + + components->add(menuContainer); + + branding = std::make_shared("zephaBranding"); + components->add(branding); + { + auto zephaText = std::make_shared("zephaText"); + zephaText->create({ GS, GS }, {}, {}, { 1, 1, 1, 1 }, f); + zephaText->setText("Zepha"); + branding->add(zephaText); + + auto alphaText = std::make_shared("alphaText"); + alphaText->create({ GS, GS }, {}, {}, { 1, 0.5, 0.7, 1 }, f); + alphaText->setText("ALPHA"); + alphaText->setPos({ 25 * GS, 0 }); + branding->add(alphaText); + } + + navigationBar = std::make_shared("navigationBar"); + navigationBar->add(std::make_shared("navigationBarBg")); + navigationBar->add(std::make_shared("navigationBarIcons")); + + auto navigationBarIcons = navigationBar->get("navigationBarIcons"); + + components->add(navigationBar); + { + auto settingsButton = std::make_shared("settingsButton"); + settingsButton->create({ 16 * GS, 16 * GS }, {}, + client.game->textures["crop(0, 0, 16, 16, menu_flag_settings)"], + client.game->textures["crop(16, 0, 16, 16, menu_flag_settings)"]); + + navigationBar->get("navigationBarIcons")->add(settingsButton); + + auto closeButton = std::make_shared("closeButton"); + closeButton->create({ 16 * GS, 16 * GS }, {}, + client.game->textures["crop(0, 0, 16, 16, menu_flag_quit)"], + client.game->textures["crop(16, 0, 16, 16, menu_flag_quit)"]); + + closeButton->setCallback(GuiComponent::CallbackType::PRIMARY, [](bool down, glm::ivec2) { if (down) exit(0); }); + navigationBar->get("navigationBarIcons")->add(closeButton); + + auto serversButton = std::make_shared("serversButton"); + serversButton->create({ 16 * GS, 16 * GS }, {}, + client.game->textures["crop(0, 0, 16, 16, menu_flag_multiplayer)"], + client.game->textures["crop(16, 0, 16, 16, menu_flag_multiplayer)"]); + + serversButton->setPos({ GS, GS }); + navigationBarIcons->add(serversButton); + + auto contentButton = std::make_shared("contentButton"); + contentButton->create({ 16 * GS, 16 * GS }, {}, + client.game->textures["crop(0, 0, 16, 16, menu_flag_content)"], + client.game->textures["crop(16, 0, 16, 16, menu_flag_content)"]); + + contentButton->setPos({ GS + GS * 18, GS }); + contentButton->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) { + if (!down) return; + client.scene.setScene(std::make_unique(client, Address{ "127.0.0.1" })); + }); + + navigationBarIcons->add(contentButton); + + auto divider = std::make_shared("divider"); + divider->create({ GS, GS * 10 }, {}, { 1, 1, 1, 0.3 }); + divider->setPos({ GS * 2 + GS * 18 * 2, GS * 4 }); + navigationBarIcons->add(divider); + + findSubgames(); + + for (unsigned int i = 0; i < subgames.size(); i++) { + auto& subgame = subgames[i]; + auto button = std::make_shared(subgame.config.name); + + button->create({ 16 * GS, 16 * GS }, {}, + client.game->textures["crop(0, 0, 16, 16, " + subgame.iconRef->name + ")"], + client.game->textures["crop(16, 0, 16, 16, " + subgame.iconRef->name + ")"]); + + button->setPos({ GS * 7 + GS * 18 * (i + 2), GS }); + button->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) { + if (!down) return; + selectedSubgame = &subgame; + sandbox.load(*selectedSubgame); + }); + + navigationBarIcons->add(button); + } + } + + if (subgames.size() > 0) { + selectedSubgame = &subgames[0]; + sandbox.load(*selectedSubgame); + } + + positionElements(); + + client.renderer.window.addResizeCallback("mainmenu", [&](glm::ivec2 win) { + this->win = win; + sandboxArea = win - glm::ivec2(0, 18 * GS); + positionElements(); + }); } void MainMenuScene::findSubgames() { - std::string subgamesPath = "../subgames"; - - cf_dir_t subgamesDir; - cf_dir_open(&subgamesDir, subgamesPath.data()); - while (subgamesDir.has_next) { - cf_file_t subgameFolder; - cf_read_file(&subgamesDir, &subgameFolder); - if (!subgameFolder.is_dir || strncmp(subgameFolder.name, ".", 1) == 0) { cf_dir_next(&subgamesDir); continue; } - - try { - bool hasConf = false, hasIcon = false, hasMods = false; - - cf_dir_t subgame; - cf_dir_open(&subgame, subgameFolder.path); - while (subgame.has_next) { - cf_file_t file; - cf_read_file(&subgame, &file); - - if (!file.is_dir && strncmp(file.name, "icon.png\0", 9) == 0) hasIcon = true; - if (!file.is_dir && strncmp(file.name, "conf.json\0", 10) == 0) hasConf = true; - if ( file.is_dir && strncmp(file.name, "mods\0", 5) == 0) hasMods = true; - - cf_dir_next(&subgame); - } - cf_dir_close(&subgame); - - if (!hasConf) throw std::runtime_error(std::string("Subgame ") + std::string(subgameFolder.name) + " is missing a conf.json."); - if (!hasMods) throw std::runtime_error(std::string("Subgame ") + std::string(subgameFolder.name) + " is missing a 'mods' directory."); - - nlohmann::json j{}; - try { - std::ifstream(std::string(subgameFolder.path) + "/conf.json") >> j; - } catch (...) { throw std::runtime_error(std::string(subgameFolder.name) + "/conf.json is not a valid JSON object."); } - - if (!j.is_object()) - throw std::runtime_error(std::string(subgameFolder.name) + "/conf.json is not a valid JSON object."); - if (!j["name"].is_string() || j["name"] == "") - throw std::runtime_error("The 'name' property in " + std::string(subgameFolder.name) + "/conf.json is missing or invalid."); - if (!j["version"].is_string() || j["version"] == "") - throw std::runtime_error("The 'version' property in " + std::string(subgameFolder.name) + "/conf.json is missing or invalid."); - - std::string name = j["name"]; - std::string description = (j["description"].is_string() ? j["description"] : ""); - std::string version = j["version"]; - - std::shared_ptr icon = client.game->textures["menu_flag_missing"]; - if (hasIcon) icon = client.game->textures.loadImage(std::string(subgameFolder.path) + "/icon.png", name); - - subgames.push_back({icon, {name, description, version}, subgameFolder.path}); - } - catch(const std::runtime_error& e) { - std::cout << Log::err << "Encountered an error while loading subgames:\n\t" << e.what() << Log::endl; - } - - cf_dir_next(&subgamesDir); - } - cf_dir_close(&subgamesDir); - - std::sort(subgames.begin(), subgames.end(), [](SubgameDef& a, SubgameDef& b) { return a.config.name < b.config.name; }); + std::string subgamesPath = "../subgames"; + + cf_dir_t subgamesDir; + cf_dir_open(&subgamesDir, subgamesPath.data()); + while (subgamesDir.has_next) { + cf_file_t subgameFolder; + cf_read_file(&subgamesDir, &subgameFolder); + if (!subgameFolder.is_dir || strncmp(subgameFolder.name, ".", 1) == 0) { + cf_dir_next(&subgamesDir); + continue; + } + + try { + bool hasConf = false, hasIcon = false, hasMods = false; + + cf_dir_t subgame; + cf_dir_open(&subgame, subgameFolder.path); + while (subgame.has_next) { + cf_file_t file; + cf_read_file(&subgame, &file); + + if (!file.is_dir && strncmp(file.name, "icon.png\0", 9) == 0) hasIcon = true; + if (!file.is_dir && strncmp(file.name, "conf.json\0", 10) == 0) hasConf = true; + if (file.is_dir && strncmp(file.name, "mods\0", 5) == 0) hasMods = true; + + cf_dir_next(&subgame); + } + cf_dir_close(&subgame); + + if (!hasConf) + throw std::runtime_error( + std::string("Subgame ") + std::string(subgameFolder.name) + " is missing a conf.json."); + if (!hasMods) + throw std::runtime_error( + std::string("Subgame ") + std::string(subgameFolder.name) + " is missing a 'mods' directory."); + + nlohmann::json j{}; + try { + std::ifstream(std::string(subgameFolder.path) + "/conf.json") >> j; + } + catch (...) { + throw std::runtime_error(std::string(subgameFolder.name) + "/conf.json is not a valid JSON object."); + } + + if (!j.is_object()) + throw std::runtime_error(std::string(subgameFolder.name) + "/conf.json is not a valid JSON object."); + if (!j["name"].is_string() || j["name"] == "") + throw std::runtime_error( + "The 'name' property in " + std::string(subgameFolder.name) + "/conf.json is missing or invalid."); + if (!j["version"].is_string() || j["version"] == "") + throw std::runtime_error("The 'version' property in " + std::string(subgameFolder.name) + + "/conf.json is missing or invalid."); + + std::string name = j["name"]; + std::string description = (j["description"].is_string() ? j["description"] : ""); + std::string version = j["version"]; + + std::shared_ptr icon = client.game->textures["menu_flag_missing"]; + if (hasIcon) icon = client.game->textures.loadImage(std::string(subgameFolder.path) + "/icon.png", name); + + subgames.push_back({ icon, { name, description, version }, subgameFolder.path }); + } + catch (const std::runtime_error& e) { + std::cout << Log::err << "Encountered an error while loading subgames:\n\t" << e.what() << Log::endl; + } + + cf_dir_next(&subgamesDir); + } + cf_dir_close(&subgamesDir); + + std::sort(subgames.begin(), subgames.end(), + [](SubgameDef& a, SubgameDef& b) { return a.config.name < b.config.name; }); } void MainMenuScene::positionElements() { - sandbox.windowResized(); - - branding->setPos({win.x - 55*GS, win.y - 30*GS}); - - navigationBar->setPos({0, win.y - 18*GS}); - - auto navigationBarBg = navigationBar->get("navigationBarBg"); - for (unsigned int i = 0; i < static_cast(win.x) / 64.f / GS; i++) { - auto segment = std::make_shared("segment_" + std::to_string(i)); - segment->create({64 * GS, 18 * GS}, {}, client.game->textures["menu_bar_bg"]); - segment->setPos({i * 64 * GS, 0}); - navigationBarBg->add(segment); - } - - auto navigationBarIcons = navigationBar->get("navigationBarIcons"); - navigationBarIcons->get("closeButton")->setPos({win.x - 16 * GS - GS, GS}); - navigationBarIcons->get("settingsButton")->setPos({win.x - 16 * GS * 2 - GS * 3, GS}); + sandbox.windowResized(); + + branding->setPos({ win.x - 55 * GS, win.y - 30 * GS }); + + navigationBar->setPos({ 0, win.y - 18 * GS }); + + auto navigationBarBg = navigationBar->get("navigationBarBg"); + for (unsigned int i = 0; i < static_cast(win.x) / 64.f / GS; i++) { + auto segment = std::make_shared("segment_" + std::to_string(i)); + segment->create({ 64 * GS, 18 * GS }, {}, client.game->textures["menu_bar_bg"]); + segment->setPos({ i * 64 * GS, 0 }); + navigationBarBg->add(segment); + } + + auto navigationBarIcons = navigationBar->get("navigationBarIcons"); + navigationBarIcons->get("closeButton")->setPos({ win.x - 16 * GS - GS, GS }); + navigationBarIcons->get("settingsButton")->setPos({ win.x - 16 * GS * 2 - GS * 3, GS }); } void MainMenuScene::update() { - client.game->textures.update(); - sandbox.update(client.getDelta()); - - components->handleMouseInput(client.renderer.window); + client.game->textures.update(); + sandbox.update(client.getDelta()); + + components->handleMouseInput(client.renderer.window); } void MainMenuScene::draw() { - client.renderer.beginChunkDeferredCalls(); - client.renderer.endDeferredCalls(); - - client.renderer.beginGUIDrawCalls(); - client.renderer.enableTexture(&client.game->textures.atlasTexture); - components->draw(client.renderer); - client.renderer.swapBuffers(); + client.renderer.beginChunkDeferredCalls(); + client.renderer.endDeferredCalls(); + + client.renderer.beginGUIDrawCalls(); + client.renderer.enableTexture(&client.game->textures.atlasTexture); + components->draw(client.renderer); + client.renderer.swapBuffers(); } void MainMenuScene::cleanup() { - client.renderer.window.setCursorHand(false); - client.renderer.window.removeResizeCallback("mainmenu"); + client.renderer.window.setCursorHand(false); + client.renderer.window.removeResizeCallback("mainmenu"); } \ No newline at end of file diff --git a/src/client/scene/MainMenuScene.h b/src/client/scene/MainMenuScene.h index d1ff20d9..8396e81d 100644 --- a/src/client/scene/MainMenuScene.h +++ b/src/client/scene/MainMenuScene.h @@ -12,30 +12,33 @@ class Client; class MainMenuScene : public Scene { -public: - explicit MainMenuScene(Client& client); - - void update() override; - void draw() override; - - void cleanup() override; -private: - void positionElements(); - void findSubgames(); - - static constexpr float GS = 3; - - glm::ivec2 win {}; - glm::ivec2 sandboxArea {}; - - std::unique_ptr components; - std::shared_ptr branding; - std::shared_ptr navigationBar; - std::shared_ptr menuContainer; - - MenuSandbox sandbox; - - std::vector subgames; - SubgameDef* selectedSubgame = nullptr; + public: + explicit MainMenuScene(Client& client); + + void update() override; + + void draw() override; + + void cleanup() override; + + private: + void positionElements(); + + void findSubgames(); + + static constexpr float GS = 3; + + glm::ivec2 win{}; + glm::ivec2 sandboxArea{}; + + std::unique_ptr components; + std::shared_ptr branding; + std::shared_ptr navigationBar; + std::shared_ptr menuContainer; + + MenuSandbox sandbox; + + std::vector subgames; + SubgameDef* selectedSubgame = nullptr; }; diff --git a/src/client/scene/Scene.h b/src/client/scene/Scene.h index ad4a366c..b7fc1d06 100644 --- a/src/client/scene/Scene.h +++ b/src/client/scene/Scene.h @@ -10,15 +10,17 @@ class Client; class Scene { -public: - explicit Scene(Client& client) : client(client) {} - - virtual void update() = 0; - virtual void draw() = 0; - virtual void cleanup() = 0; - - virtual ~Scene() = default; - - Client& client; + public: + explicit Scene(Client& client) : client(client) {} + + virtual void update() = 0; + + virtual void draw() = 0; + + virtual void cleanup() = 0; + + virtual ~Scene() = default; + + Client& client; }; diff --git a/src/client/scene/SceneManager.cpp b/src/client/scene/SceneManager.cpp index 07c61f7d..2b63ad24 100644 --- a/src/client/scene/SceneManager.cpp +++ b/src/client/scene/SceneManager.cpp @@ -12,8 +12,8 @@ */ void SceneManager::setScene(std::unique_ptr newScene) { - cleanupScene(); - scene = std::move(newScene); + cleanupScene(); + scene = std::move(newScene); } @@ -23,7 +23,7 @@ void SceneManager::setScene(std::unique_ptr newScene) { */ const Scene& SceneManager::getScene() { - return *scene; + return *scene; } @@ -32,9 +32,9 @@ const Scene& SceneManager::getScene() { */ void SceneManager::update() { - if (!scene) return; - scene->update(); - scene->draw(); + if (!scene) return; + scene->update(); + scene->draw(); } @@ -44,8 +44,8 @@ void SceneManager::update() { */ void SceneManager::cleanupScene() { - if (scene) scene->cleanup(); - scene = nullptr; + if (scene) scene->cleanup(); + scene = nullptr; } @@ -54,5 +54,5 @@ void SceneManager::cleanupScene() { */ SceneManager::~SceneManager() { - cleanupScene(); + cleanupScene(); } \ No newline at end of file diff --git a/src/client/scene/SceneManager.h b/src/client/scene/SceneManager.h index 5583c321..b86d6bd0 100644 --- a/src/client/scene/SceneManager.h +++ b/src/client/scene/SceneManager.h @@ -9,16 +9,18 @@ #include "Scene.h" class SceneManager { -public: - void setScene(std::unique_ptr scene); - const Scene& getScene(); - - void update(); - void cleanupScene(); - - ~SceneManager(); - -private: - std::unique_ptr scene = nullptr; + public: + void setScene(std::unique_ptr scene); + + const Scene& getScene(); + + void update(); + + void cleanupScene(); + + ~SceneManager(); + + private: + std::unique_ptr scene = nullptr; }; diff --git a/src/client/stream/ChunkMeshDetails.h b/src/client/stream/ChunkMeshDetails.h index b96eaa14..89c5a169 100644 --- a/src/client/stream/ChunkMeshDetails.h +++ b/src/client/stream/ChunkMeshDetails.h @@ -10,8 +10,8 @@ #include "client/graph/mesh/ChunkVertex.h" struct ChunkMeshDetails { - std::vector vertices; - std::vector indices; - - glm::ivec3 pos {}; + std::vector vertices; + std::vector indices; + + glm::ivec3 pos{}; }; diff --git a/src/client/stream/MeshGenStream.cpp b/src/client/stream/MeshGenStream.cpp index c174db3f..208819af 100644 --- a/src/client/stream/MeshGenStream.cpp +++ b/src/client/stream/MeshGenStream.cpp @@ -11,101 +11,102 @@ #include "world/dim/chunk/Chunk.h" #include "world/dim/LocalDimension.h" -MeshGenStream::MeshGenStream(SubgamePtr game, LocalDimension &dimension) : - dimension(dimension), - noiseSampler({NoiseSample {16}, NoiseSample {16}, NoiseSample {16}}) { - - noise::module::Perlin offsetBaseNoise; - offsetBaseNoise.SetFrequency(8); - offsetBaseNoise.SetOctaveCount(3); - - noise::module::Turbulence offsetTurbulence; - offsetTurbulence.SetSourceModule(0, offsetBaseNoise); - offsetTurbulence.SetFrequency(4.0); - offsetTurbulence.SetPower(0.125); - - // 8 is just a random value to offset results - noiseSampler[0].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x + 8, pos.y, pos.z); }); - noiseSampler[1].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x, pos.y + 8, pos.z); }); - noiseSampler[2].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x, pos.y, pos.z + 8); }); - - threads.reserve(THREADS); - for (int i = 0; i < THREADS; i++) threads.emplace_back(*game.l(), noiseSampler); +MeshGenStream::MeshGenStream(SubgamePtr game, LocalDimension& dimension) : + dimension(dimension), + noiseSampler({ NoiseSample{ 16 }, NoiseSample{ 16 }, NoiseSample{ 16 }}) { + + noise::module::Perlin offsetBaseNoise; + offsetBaseNoise.SetFrequency(8); + offsetBaseNoise.SetOctaveCount(3); + + noise::module::Turbulence offsetTurbulence; + offsetTurbulence.SetSourceModule(0, offsetBaseNoise); + offsetTurbulence.SetFrequency(4.0); + offsetTurbulence.SetPower(0.125); + + // 8 is just a random value to offset results + noiseSampler[0].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x + 8, pos.y, pos.z); }); + noiseSampler[1].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x, pos.y + 8, pos.z); }); + noiseSampler[2].populate([&](glm::ivec3 pos) { return offsetTurbulence.GetValue(pos.x, pos.y, pos.z + 8); }); + + threads.reserve(THREADS); + for (int i = 0; i < THREADS; i++) threads.emplace_back(*game.l(), noiseSampler); } std::vector MeshGenStream::update() { - std::vector finishedChunks; - - for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { - for (Thread& t : threads) { - auto& j = t.jobs[i]; - if (j.busy) continue; - - if (j.thisChunk) { - j.thisChunk = nullptr; - finishedChunks.push_back(j.meshDetails); - j.meshDetails = new ChunkMeshDetails(); - } - - if (!queuedTasks.empty()) { - auto pos = queuedTasks.front(); - queuedMap.erase(pos); - queuedTasks.pop_front(); - - std::shared_ptr chunk = dimension.getChunk(pos); - if (chunk == nullptr) goto breakAddTask; - - j.meshDetails->pos = pos; - j.thisChunk = std::shared_ptr(chunk); - - int ind = 0; - for (const glm::ivec3& dir : Vec::TO_VEC) { - std::shared_ptr adjacent = dimension.getChunk(pos + dir); - j.adjacentChunks[ind++] = std::shared_ptr(adjacent); - if (adjacent == nullptr) goto breakAddTask; - } - - j.busy = true; - - } - - breakAddTask:; - } - } - - return std::move(finishedChunks); + std::vector finishedChunks; + + for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { + for (Thread& t : threads) { + auto& j = t.jobs[i]; + if (j.busy) continue; + + if (j.thisChunk) { + j.thisChunk = nullptr; + finishedChunks.push_back(j.meshDetails); + j.meshDetails = new ChunkMeshDetails(); + } + + if (!queuedTasks.empty()) { + auto pos = queuedTasks.front(); + queuedMap.erase(pos); + queuedTasks.pop_front(); + + std::shared_ptr chunk = dimension.getChunk(pos); + if (chunk == nullptr) goto breakAddTask; + + j.meshDetails->pos = pos; + j.thisChunk = std::shared_ptr(chunk); + + int ind = 0; + for (const glm::ivec3& dir : Vec::TO_VEC) { + std::shared_ptr adjacent = dimension.getChunk(pos + dir); + j.adjacentChunks[ind++] = std::shared_ptr(adjacent); + if (adjacent == nullptr) goto breakAddTask; + } + + j.busy = true; + + } + + breakAddTask:; + } + } + + return std::move(finishedChunks); } -MeshGenStream::Thread::Thread(LocalSubgame &defs, std::array& offsetSamplers) : - game(defs), offsetSamplers(offsetSamplers), thread(std::bind(&MeshGenStream::Thread::exec, this)) {} +MeshGenStream::Thread::Thread(LocalSubgame& defs, std::array& offsetSamplers) : + game(defs), offsetSamplers(offsetSamplers), thread(std::bind(&MeshGenStream::Thread::exec, this)) {} void MeshGenStream::Thread::exec() { - while (keepAlive) { - bool empty = true; - - for (auto i = 0; i < jobs.size(); i++) { - auto& u = jobs[i]; - if (!u.busy) continue; - - ChunkMeshGenerator m(u.meshDetails, game.getDefs(), game.getBiomes(), u.thisChunk, u.adjacentChunks, offsetSamplers); - empty = false; - u.busy = false; - } - - if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + while (keepAlive) { + bool empty = true; + + for (auto i = 0; i < jobs.size(); i++) { + auto& u = jobs[i]; + if (!u.busy) continue; + + ChunkMeshGenerator m(u.meshDetails, game.getDefs(), game.getBiomes(), u.thisChunk, u.adjacentChunks, + offsetSamplers); + empty = false; + u.busy = false; + } + + if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } void MeshGenStream::queue(glm::ivec3 pos, bool priority) { - if (!queuedMap.count(pos)) { - priority ? queuedTasks.push_front(pos) : queuedTasks.push_back(pos); - queuedMap.insert(pos); - } + if (!queuedMap.count(pos)) { + priority ? queuedTasks.push_front(pos) : queuedTasks.push_back(pos); + queuedMap.insert(pos); + } } MeshGenStream::~MeshGenStream() { - for (auto& t : threads) { - t.keepAlive = false; - t.thread.join(); - } + for (auto& t : threads) { + t.keepAlive = false; + t.thread.join(); + } } \ No newline at end of file diff --git a/src/client/stream/MeshGenStream.h b/src/client/stream/MeshGenStream.h index 0e8b0d6b..1666fb7b 100644 --- a/src/client/stream/MeshGenStream.h +++ b/src/client/stream/MeshGenStream.h @@ -15,52 +15,55 @@ #include "world/gen/NoiseSample.h" class Chunk; + class LocalSubgame; class LocalDimension; class MeshGenStream { -public: - static const int THREADS = 4; - static const int THREAD_QUEUE_SIZE = 16; - - explicit MeshGenStream(SubgamePtr game, LocalDimension& dimension); - ~MeshGenStream(); - - void queue(glm::ivec3 pos, bool priority = false); - - //Will return a vector of MeshDetails pointers containing finished meshes. - //Frees up the threads and starts new tasks. - std::vector update(); - - struct Job { - std::shared_ptr thisChunk = nullptr; - std::array, 6> adjacentChunks {}; - - ChunkMeshDetails* meshDetails = new ChunkMeshDetails(); - - bool busy = false; - }; - - struct Thread { - explicit Thread(LocalSubgame &defs, std::array& offsetSampler); - void exec(); - - LocalSubgame &game; - std::array& offsetSamplers; - std::vector jobs = std::vector(THREAD_QUEUE_SIZE); - - bool keepAlive = true; - std::thread thread {}; - }; - - std::vector threads; -private: - - LocalDimension& dimension; - - std::array noiseSampler; - std::deque queuedTasks; - std::unordered_set queuedMap; + public: + static const int THREADS = 4; + static const int THREAD_QUEUE_SIZE = 16; + + explicit MeshGenStream(SubgamePtr game, LocalDimension& dimension); + + ~MeshGenStream(); + + void queue(glm::ivec3 pos, bool priority = false); + + //Will return a vector of MeshDetails pointers containing finished meshes. + //Frees up the threads and starts new tasks. + std::vector update(); + + struct Job { + std::shared_ptr thisChunk = nullptr; + std::array, 6> adjacentChunks{}; + + ChunkMeshDetails* meshDetails = new ChunkMeshDetails(); + + bool busy = false; + }; + + struct Thread { + explicit Thread(LocalSubgame& defs, std::array& offsetSampler); + + void exec(); + + LocalSubgame& game; + std::array& offsetSamplers; + std::vector jobs = std::vector(THREAD_QUEUE_SIZE); + + bool keepAlive = true; + std::thread thread{}; + }; + + std::vector threads; + private: + + LocalDimension& dimension; + + std::array noiseSampler; + std::deque queuedTasks; + std::unordered_set queuedMap; }; diff --git a/src/client/stream/WorldInterpolationStream.cpp b/src/client/stream/WorldInterpolationStream.cpp index b8b51c63..239e1d8e 100644 --- a/src/client/stream/WorldInterpolationStream.cpp +++ b/src/client/stream/WorldInterpolationStream.cpp @@ -9,12 +9,12 @@ #include "world/dim/chunk/Chunk.h" WorldInterpolationStream::WorldInterpolationStream(LocalSubgame& game, LocalWorld& world, unsigned int seed) { - threads.reserve(THREADS); - for (int i = 0; i < THREADS; i++) threads.emplace_back(game, world, seed); + threads.reserve(THREADS); + for (int i = 0; i < THREADS; i++) threads.emplace_back(game, world, seed); } void WorldInterpolationStream::queuePacket(std::unique_ptr p) { - queuedPacketTasks.push(std::move(p)); + queuedPacketTasks.push(std::move(p)); } //bool WorldInterpolationStream::queuePosition(glm::vec3 pos){ @@ -27,34 +27,34 @@ void WorldInterpolationStream::queuePacket(std::unique_ptr p) { //} std::unique_ptr>> WorldInterpolationStream::update() { - auto finishedChunks = std::make_unique>>(); + auto finishedChunks = std::make_unique>>(); // auto finishedMapBlocks = std::make_unique>>(); - - for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { - for (auto& t : threads) { - auto& j = t.jobs[i]; - if (j.locked) continue; - - if (!j.chunks.empty()) { - for (auto& c : j.chunks) finishedChunks->emplace_back(std::move(c)); - j.chunks.clear(); + + for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { + for (auto& t : threads) { + auto& j = t.jobs[i]; + if (j.locked) continue; + + if (!j.chunks.empty()) { + for (auto& c : j.chunks) finishedChunks->emplace_back(std::move(c)); + j.chunks.clear(); // j.job = JobType::EMPTY; - } + } // else if (u.mapblock != nullptr) { // finishedMapBlocks->push_back(u.mapblock); // u.mapblock = nullptr; // u.job = JobType::EMPTY; // } - - if (!queuedPacketTasks.empty()) { - auto packet = std::move(queuedPacketTasks.front()); - queuedPacketTasks.pop(); + + if (!queuedPacketTasks.empty()) { + auto packet = std::move(queuedPacketTasks.front()); + queuedPacketTasks.pop(); // j.job = JobType::PACKET; - j.packet = std::move(packet); - j.locked = true; - - } + j.packet = std::move(packet); + j.locked = true; + + } // else if (!queuedInterpTasks.empty()) { // auto it = queuedInterpTasks.begin(); // glm::vec3 pos = *it; @@ -65,52 +65,52 @@ std::unique_ptr>> WorldInterpolationStream::u // j.mapBlockPos = pos; // j.locked = true; // } - } - } - - return finishedChunks; + } + } + + return finishedChunks; } WorldInterpolationStream::Thread::Thread(LocalSubgame& game, LocalWorld& world, unsigned int seed) : - thread(std::bind(&WorldInterpolationStream::Thread::run, this)) {} + thread(std::bind(&WorldInterpolationStream::Thread::run, this)) {} void WorldInterpolationStream::Thread::run() { - while (!kill) { - bool empty = true; - for (Job& u : jobs) { - if (u.locked) { + while (!kill) { + bool empty = true; + for (Job& u : jobs) { + if (u.locked) { // if (u.job == JobType::PACKET) { - empty = false; - - if (u.packet->type == Packet::Type::CHUNK) { - u.chunks.reserve(1); - u.chunks.emplace_back(std::make_shared()); - u.chunks.back()->deserialize(u.packet->d); - } - else if (u.packet->type == Packet::Type::MAPBLOCK) { - u.chunks.reserve(64); - while (!u.packet->d.atEnd()) { - std::string dat = u.packet->d.read(); - Deserializer d(dat); - u.chunks.emplace_back(std::make_shared()); - u.chunks.back()->deserialize(d); - } - } - - u.locked = false; + empty = false; + + if (u.packet->type == Packet::Type::CHUNK) { + u.chunks.reserve(1); + u.chunks.emplace_back(std::make_shared()); + u.chunks.back()->deserialize(u.packet->d); + } + else if (u.packet->type == Packet::Type::MAPBLOCK) { + u.chunks.reserve(64); + while (!u.packet->d.atEnd()) { + std::string dat = u.packet->d.read(); + Deserializer d(dat); + u.chunks.emplace_back(std::make_shared()); + u.chunks.back()->deserialize(d); + } + } + + u.locked = false; // } // else if (u.job == JobType::FARMAP) { // throw std::runtime_error("Farmap no exist yet."); // } - } - } - if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + } + } + if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } WorldInterpolationStream::~WorldInterpolationStream() { - for (auto& t : threads) { - t.kill = true; - t.thread.join(); - } + for (auto& t : threads) { + t.kill = true; + t.thread.join(); + } } \ No newline at end of file diff --git a/src/client/stream/WorldInterpolationStream.h b/src/client/stream/WorldInterpolationStream.h index c12bcb51..fb4d7f90 100644 --- a/src/client/stream/WorldInterpolationStream.h +++ b/src/client/stream/WorldInterpolationStream.h @@ -15,56 +15,61 @@ #include "util/CovariantPtr.h" class Chunk; + class LocalSubgame; + class PacketView; class WorldInterpolationStream { -public: - static const int THREADS = 4; - static const int THREAD_QUEUE_SIZE = 16; - - WorldInterpolationStream(LocalSubgame& game, LocalWorld& world, unsigned int seed); - - // Queue parsing of packet `p`. - void queuePacket(std::unique_ptr p); - // Queue interpolation of Mapblock at `pos`. + public: + static const int THREADS = 4; + static const int THREAD_QUEUE_SIZE = 16; + + WorldInterpolationStream(LocalSubgame& game, LocalWorld& world, unsigned int seed); + + // Queue parsing of packet `p`. + void queuePacket(std::unique_ptr p); + + // Queue interpolation of Mapblock at `pos`. // bool queuePosition(glm::vec3 pos); - // Returns a vector of BlockChunks that have finished processing, - // and gives the threads new data to work with. - std::unique_ptr>> update(); - - ~WorldInterpolationStream(); -private: + // Returns a vector of BlockChunks that have finished processing, + // and gives the threads new data to work with. + std::unique_ptr>> update(); + + ~WorldInterpolationStream(); + + private: // enum class JobType { // EMPTY, // PACKET, // FARMAP // }; - - struct Job { - bool locked = false; + + struct Job { + bool locked = false; // JobType job = JobType::EMPTY; - - std::shared_ptr packet = nullptr; - std::vector> chunks = {}; + + std::shared_ptr packet = nullptr; + std::vector> chunks = {}; // std::shared_ptr mapblock = nullptr; // glm::vec3 mapBlockPos = {0, 0, 0}; - }; - - struct Thread { - explicit Thread(LocalSubgame& game, LocalWorld& world, unsigned int seed); - void run(); - - bool kill = false; - - std::vector jobs = std::vector(THREAD_QUEUE_SIZE); - - std::thread thread; - }; - - std::vector threads; - std::queue> queuedPacketTasks; + }; + + struct Thread { + explicit Thread(LocalSubgame& game, LocalWorld& world, unsigned int seed); + + void run(); + + bool kill = false; + + std::vector jobs = std::vector(THREAD_QUEUE_SIZE); + + std::thread thread; + }; + + std::vector threads; + std::queue> queuedPacketTasks; // std::unordered_set queuedInterpMap; // std::queue queuedInterpTasks; }; diff --git a/src/game/LocalSubgame.cpp b/src/game/LocalSubgame.cpp index 59ecb3b3..dda74565 100644 --- a/src/game/LocalSubgame.cpp +++ b/src/game/LocalSubgame.cpp @@ -12,13 +12,13 @@ */ LocalSubgame::LocalSubgame(const std::string& baseAssets) : - textures(2048), - - lua(std::make_unique(*this)), - biomes(std::make_unique()), - defs(std::make_unique(textures)) { - - textures.loadDirectory(baseAssets); + textures(2048), + + lua(std::make_unique(*this)), + biomes(std::make_unique()), + defs(std::make_unique(textures)) { + + textures.loadDirectory(baseAssets); } @@ -30,7 +30,7 @@ LocalSubgame::LocalSubgame(const std::string& baseAssets) : */ void LocalSubgame::init(WorldPtr world, PlayerPtr player, Client& client) { - lua->init(world, player, client); + lua->init(world, player, client); } @@ -40,6 +40,6 @@ void LocalSubgame::init(WorldPtr world, PlayerPtr player, Client& client) { */ void LocalSubgame::update(double delta) { - lua->update(delta); - textures.update(); + lua->update(delta); + textures.update(); } diff --git a/src/game/LocalSubgame.h b/src/game/LocalSubgame.h index f3031f2b..bc8e0325 100644 --- a/src/game/LocalSubgame.h +++ b/src/game/LocalSubgame.h @@ -17,26 +17,31 @@ #include "game/atlas/LocalDefinitionAtlas.h" class Client; + class LocalWorld; + class LocalPlayer; class LocalSubgame : public Subgame { -public: - explicit LocalSubgame(const std::string& baseAssets); - - void init(WorldPtr world, PlayerPtr player, Client& client); - void update(double delta); - - LocalDefinitionAtlas& getDefs() override { return *defs; }; - LocalBiomeAtlas& getBiomes() override { return *biomes; }; - LocalLuaParser& getParser() override { return *lua; }; - - ModelStore models; - TextureAtlas textures; - -private: - std::shared_ptr lua; - std::shared_ptr biomes; - std::shared_ptr defs; + public: + explicit LocalSubgame(const std::string& baseAssets); + + void init(WorldPtr world, PlayerPtr player, Client& client); + + void update(double delta); + + LocalDefinitionAtlas& getDefs() override { return *defs; }; + + LocalBiomeAtlas& getBiomes() override { return *biomes; }; + + LocalLuaParser& getParser() override { return *lua; }; + + ModelStore models; + TextureAtlas textures; + + private: + std::shared_ptr lua; + std::shared_ptr biomes; + std::shared_ptr defs; }; diff --git a/src/game/ServerSubgame.cpp b/src/game/ServerSubgame.cpp index 83eb4f01..59a694d2 100644 --- a/src/game/ServerSubgame.cpp +++ b/src/game/ServerSubgame.cpp @@ -9,22 +9,22 @@ #include "server/ServerClients.h" ServerSubgame::ServerSubgame(const std::string& subgame, unsigned int seed) : - subgamePath("../subgames/" + subgame + "/"), - - defs(std::make_unique()), - biomes(std::make_unique(seed)), - lua(std::make_unique(*this)) { - - if (subgame.empty()) throw std::runtime_error("No subgame specified."); - else if (!cf_file_exists(subgamePath.data())) throw std::runtime_error("Subgame does not exist."); + subgamePath("../subgames/" + subgame + "/"), + + defs(std::make_unique()), + biomes(std::make_unique(seed)), + lua(std::make_unique(*this)) { + + if (subgame.empty()) throw std::runtime_error("No subgame specified."); + else if (!cf_file_exists(subgamePath.data())) throw std::runtime_error("Subgame does not exist."); } void ServerSubgame::init(WorldPtr world) { - lua->init(world, subgamePath); + lua->init(world, subgamePath); } void ServerSubgame::update(double delta) { - lua->update(delta); + lua->update(delta); } ServerSubgame::~ServerSubgame() {} diff --git a/src/game/ServerSubgame.h b/src/game/ServerSubgame.h index d614ba45..f87494db 100644 --- a/src/game/ServerSubgame.h +++ b/src/game/ServerSubgame.h @@ -14,28 +14,33 @@ #include "game/atlas/ServerDefinitionAtlas.h" class ServerWorld; + class ServerClients; class ServerSubgame : public Subgame { -public: - ServerSubgame(const std::string& subgame, unsigned int seed); - ~ServerSubgame(); - - void init(WorldPtr world); - void update(double delta); - - std::string subgamePath; - - ServerDefinitionAtlas& getDefs() override { return *defs; }; - ServerBiomeAtlas& getBiomes() override { return *biomes; }; - ServerLuaParser& getParser() override { return *lua; }; - - AssetStorage assets; - -private: - - std::unique_ptr lua; - std::unique_ptr biomes; - std::unique_ptr defs; + public: + ServerSubgame(const std::string& subgame, unsigned int seed); + + ~ServerSubgame(); + + void init(WorldPtr world); + + void update(double delta); + + std::string subgamePath; + + ServerDefinitionAtlas& getDefs() override { return *defs; }; + + ServerBiomeAtlas& getBiomes() override { return *biomes; }; + + ServerLuaParser& getParser() override { return *lua; }; + + AssetStorage assets; + + private: + + std::unique_ptr lua; + std::unique_ptr biomes; + std::unique_ptr defs; }; diff --git a/src/game/Subgame.h b/src/game/Subgame.h index 1a7160ed..35d99989 100644 --- a/src/game/Subgame.h +++ b/src/game/Subgame.h @@ -5,13 +5,18 @@ #pragma once class World; + class LuaParser; + class BiomeAtlas; + class DefinitionAtlas; class Subgame { -public: - virtual DefinitionAtlas& getDefs() = 0; - virtual BiomeAtlas& getBiomes() = 0; - virtual LuaParser& getParser() = 0; + public: + virtual DefinitionAtlas& getDefs() = 0; + + virtual BiomeAtlas& getBiomes() = 0; + + virtual LuaParser& getParser() = 0; }; \ No newline at end of file diff --git a/src/game/atlas/BiomeAtlas.cpp b/src/game/atlas/BiomeAtlas.cpp index 3af18052..3293643a 100644 --- a/src/game/atlas/BiomeAtlas.cpp +++ b/src/game/atlas/BiomeAtlas.cpp @@ -7,21 +7,22 @@ #include "game/def/BiomeDef.h" unsigned int BiomeAtlas::size() { - return defs.size(); + return defs.size(); } BiomeDef& BiomeAtlas::biomeFromId(unsigned int index) { - if (index >= defs.size()) throw std::runtime_error("Undefined biome ID " + std::to_string(index) + " requested."); - return *defs.at(static_cast(index)); + if (index >= defs.size()) throw std::runtime_error("Undefined biome ID " + std::to_string(index) + " requested."); + return *defs.at(static_cast(index)); } BiomeDef& BiomeAtlas::biomeFromStr(const std::string& identifier) { - if (defTable.count(identifier) <= 0) throw std::runtime_error("Undefined biome identifier " + identifier + " requested."); - return *defs.at(static_cast(defTable.at(identifier))); + if (defTable.count(identifier) <= 0) + throw std::runtime_error("Undefined biome identifier " + identifier + " requested."); + return *defs.at(static_cast(defTable.at(identifier))); } std::vector BiomeAtlas::biomesFromTag(const std::string& tag) { - std::vector matched {}; + std::vector matched{}; for (auto biome : defs) if (biome->tags.count(tag) && biome->tags.at(tag) != 0) matched.push_back(biome); return std::move(matched); diff --git a/src/game/atlas/BiomeAtlas.h b/src/game/atlas/BiomeAtlas.h index 7975d082..6128d226 100644 --- a/src/game/atlas/BiomeAtlas.h +++ b/src/game/atlas/BiomeAtlas.h @@ -11,18 +11,21 @@ class BiomeDef; class BiomeAtlas { -public: - BiomeAtlas() = default; - virtual void registerBiome(BiomeDef* def) = 0; - - BiomeDef& biomeFromId(unsigned int index); - BiomeDef& biomeFromStr(const std::string& identifier); + public: + BiomeAtlas() = default; + + virtual void registerBiome(BiomeDef* def) = 0; + + BiomeDef& biomeFromId(unsigned int index); + + BiomeDef& biomeFromStr(const std::string& identifier); + std::vector biomesFromTag(const std::string& tag); - - unsigned int size(); - - const static unsigned int INVALID = 0; -protected: - std::vector defs; - std::unordered_map defTable; + + unsigned int size(); + + const static unsigned int INVALID = 0; + protected: + std::vector defs; + std::unordered_map defTable; }; \ No newline at end of file diff --git a/src/game/atlas/DefinitionAtlas.cpp b/src/game/atlas/DefinitionAtlas.cpp index 77ff1400..e83dc639 100644 --- a/src/game/atlas/DefinitionAtlas.cpp +++ b/src/game/atlas/DefinitionAtlas.cpp @@ -9,44 +9,45 @@ #include "game/def/CraftItemDef.h" ItemDef& DefinitionAtlas::fromId(unsigned int id) const { - if (id > defs.size()) throw std::runtime_error("Undefined definition id " + std::to_string(id) + " requested."); - return *defs.at(static_cast(id)); + if (id > defs.size()) throw std::runtime_error("Undefined definition id " + std::to_string(id) + " requested."); + return *defs.at(static_cast(id)); } -ItemDef &DefinitionAtlas::fromStr(const std::string& identifier) const { - if (identifier == "") return *defs.at(AIR); - if (defTable.count(identifier) <= 0) throw std::runtime_error("Undefined definition identifier " + identifier + " requested."); - return *defs.at(static_cast(defTable.at(identifier))); +ItemDef& DefinitionAtlas::fromStr(const std::string& identifier) const { + if (identifier == "") return *defs.at(AIR); + if (defTable.count(identifier) <= 0) + throw std::runtime_error("Undefined definition identifier " + identifier + " requested."); + return *defs.at(static_cast(defTable.at(identifier))); } BlockDef& DefinitionAtlas::blockFromId(unsigned int index) const { - ItemDef& def = fromId(index); - if (def.type != ItemDef::Type::BLOCK) throw std::runtime_error(std::to_string(index) + " is not a block."); - return static_cast(def); + ItemDef& def = fromId(index); + if (def.type != ItemDef::Type::BLOCK) throw std::runtime_error(std::to_string(index) + " is not a block."); + return static_cast(def); } -BlockDef &DefinitionAtlas::blockFromStr(const std::string& identifier) const { - ItemDef& def = fromStr(identifier); - if (def.type != ItemDef::Type::BLOCK) throw std::runtime_error(identifier + " is not a block."); - return static_cast(def); +BlockDef& DefinitionAtlas::blockFromStr(const std::string& identifier) const { + ItemDef& def = fromStr(identifier); + if (def.type != ItemDef::Type::BLOCK) throw std::runtime_error(identifier + " is not a block."); + return static_cast(def); } CraftItemDef& DefinitionAtlas::craftItemFromId(unsigned int index) const { - ItemDef& def = fromId(index); - if (def.type != ItemDef::Type::CRAFTITEM) throw std::runtime_error(std::to_string(index) + " is not a craftitem."); - return static_cast(def); + ItemDef& def = fromId(index); + if (def.type != ItemDef::Type::CRAFTITEM) throw std::runtime_error(std::to_string(index) + " is not a craftitem."); + return static_cast(def); } -CraftItemDef &DefinitionAtlas::craftItemFromStr(const std::string& identifier) const { - ItemDef& def = fromStr(identifier); - if (def.type != ItemDef::Type::CRAFTITEM) throw std::runtime_error(identifier + " is not a craftitem."); - return static_cast(def); +CraftItemDef& DefinitionAtlas::craftItemFromStr(const std::string& identifier) const { + ItemDef& def = fromStr(identifier); + if (def.type != ItemDef::Type::CRAFTITEM) throw std::runtime_error(identifier + " is not a craftitem."); + return static_cast(def); } unsigned int DefinitionAtlas::size() { - return static_cast(defs.size()); + return static_cast(defs.size()); } DefinitionAtlas::~DefinitionAtlas() { - for (auto def : defs) delete def; + for (auto def : defs) delete def; } \ No newline at end of file diff --git a/src/game/atlas/DefinitionAtlas.h b/src/game/atlas/DefinitionAtlas.h index ab9db83b..d5adc227 100644 --- a/src/game/atlas/DefinitionAtlas.h +++ b/src/game/atlas/DefinitionAtlas.h @@ -9,29 +9,36 @@ #include class ItemDef; + class BlockDef; + class CraftItemDef; class DefinitionAtlas { -public: - virtual void registerDef(ItemDef* def) = 0; - - ItemDef& fromId(unsigned int index) const; - ItemDef& fromStr(const std::string& identifier) const; - - //Specializations that throw an error upon an invalid usertype. - BlockDef& blockFromId(unsigned int index) const; - BlockDef& blockFromStr(const std::string& identifier) const; - CraftItemDef& craftItemFromId(unsigned int index) const; - CraftItemDef& craftItemFromStr(const std::string& identifier) const; - - unsigned int size(); - - const static unsigned int INVALID = 0; - const static unsigned int AIR = 1; - - ~DefinitionAtlas(); -protected: - std::vector defs; - std::unordered_map defTable; + public: + virtual void registerDef(ItemDef* def) = 0; + + ItemDef& fromId(unsigned int index) const; + + ItemDef& fromStr(const std::string& identifier) const; + + //Specializations that throw an error upon an invalid usertype. + BlockDef& blockFromId(unsigned int index) const; + + BlockDef& blockFromStr(const std::string& identifier) const; + + CraftItemDef& craftItemFromId(unsigned int index) const; + + CraftItemDef& craftItemFromStr(const std::string& identifier) const; + + unsigned int size(); + + const static unsigned int INVALID = 0; + const static unsigned int AIR = 1; + + ~DefinitionAtlas(); + + protected: + std::vector defs; + std::unordered_map defTable; }; diff --git a/src/game/atlas/LocalBiomeAtlas.cpp b/src/game/atlas/LocalBiomeAtlas.cpp index ed1be917..7da2bf20 100644 --- a/src/game/atlas/LocalBiomeAtlas.cpp +++ b/src/game/atlas/LocalBiomeAtlas.cpp @@ -7,25 +7,26 @@ #include "game/def/BiomeDef.h" LocalBiomeAtlas::LocalBiomeAtlas() { - BiomeDef* invalid = new BiomeDef(); - invalid->identifier = "invalid"; - invalid->humidity = -1; - invalid->temperature = -1; - invalid->roughness = -1; - - defs.push_back(invalid); - defTable.insert({"invalid", 0}); + BiomeDef* invalid = new BiomeDef(); + invalid->identifier = "invalid"; + invalid->humidity = -1; + invalid->temperature = -1; + invalid->roughness = -1; + + defs.push_back(invalid); + defTable.insert({ "invalid", 0 }); } void LocalBiomeAtlas::setIdentifiers(const std::vector& identifiers) { - for (unsigned int i = 0; i < identifiers.size(); i++) { - if (i >= 1) defs.emplace_back(); //Don't emplace invalid - defTable.insert({identifiers[i], i}); - } + for (unsigned int i = 0; i < identifiers.size(); i++) { + if (i >= 1) defs.emplace_back(); //Don't emplace invalid + defTable.insert({ identifiers[i], i }); + } } -void LocalBiomeAtlas::registerBiome(BiomeDef *def) { - if (!defTable.count(def->identifier)) throw std::runtime_error("Client/Server biome desync: " + def->identifier + "."); - def->index = defTable[def->identifier]; - defs[def->index] = def; +void LocalBiomeAtlas::registerBiome(BiomeDef* def) { + if (!defTable.count(def->identifier)) + throw std::runtime_error("Client/Server biome desync: " + def->identifier + "."); + def->index = defTable[def->identifier]; + defs[def->index] = def; } diff --git a/src/game/atlas/LocalBiomeAtlas.h b/src/game/atlas/LocalBiomeAtlas.h index 8c0f42bd..eb8b6951 100644 --- a/src/game/atlas/LocalBiomeAtlas.h +++ b/src/game/atlas/LocalBiomeAtlas.h @@ -7,8 +7,10 @@ #include "BiomeAtlas.h" class LocalBiomeAtlas : public BiomeAtlas { -public: - LocalBiomeAtlas(); - void registerBiome(BiomeDef* def) override; - void setIdentifiers(const std::vector& identifiers); + public: + LocalBiomeAtlas(); + + void registerBiome(BiomeDef* def) override; + + void setIdentifiers(const std::vector& identifiers); }; diff --git a/src/game/atlas/LocalDefinitionAtlas.cpp b/src/game/atlas/LocalDefinitionAtlas.cpp index 39eae0c1..f440aa6c 100644 --- a/src/game/atlas/LocalDefinitionAtlas.cpp +++ b/src/game/atlas/LocalDefinitionAtlas.cpp @@ -8,43 +8,44 @@ #include "TextureAtlas.h" LocalDefinitionAtlas::LocalDefinitionAtlas(TextureAtlas& atlas) { - //Invalid Node - BlockModel invalidModel = BlockModel::createCube({atlas["_missing"]}, {}, {}); - BlockDef* invalid = new BlockDef(); - invalid->identifier = "invalid"; - invalid->name = "INVALID"; - invalid->maxStackSize = 64; - invalid->model = invalidModel; - invalid->farModel = invalidModel; - invalid->sBoxes = {{{0, 0, 0}, {1, 1, 1}}}; - invalid->cBoxes = {{{0, 0, 0}, {1, 1, 1}}}; - defs.push_back(invalid); - defTable.insert({"invalid", 0}); - - //Air Node - BlockModel nullModel {}; - BlockDef* air = new BlockDef(); - air->identifier = "air"; - air->index = 1; - air->name = "Air"; - air->maxStackSize = 64; - air->model = nullModel; - air->farModel = nullModel; - air->solid = false; - air->culls = false; - defs.push_back(air); - defTable.insert({"air", 1}); + //Invalid Node + BlockModel invalidModel = BlockModel::createCube({ atlas["_missing"] }, {}, {}); + BlockDef* invalid = new BlockDef(); + invalid->identifier = "invalid"; + invalid->name = "INVALID"; + invalid->maxStackSize = 64; + invalid->model = invalidModel; + invalid->farModel = invalidModel; + invalid->sBoxes = {{{ 0, 0, 0 }, { 1, 1, 1 }}}; + invalid->cBoxes = {{{ 0, 0, 0 }, { 1, 1, 1 }}}; + defs.push_back(invalid); + defTable.insert({ "invalid", 0 }); + + //Air Node + BlockModel nullModel{}; + BlockDef* air = new BlockDef(); + air->identifier = "air"; + air->index = 1; + air->name = "Air"; + air->maxStackSize = 64; + air->model = nullModel; + air->farModel = nullModel; + air->solid = false; + air->culls = false; + defs.push_back(air); + defTable.insert({ "air", 1 }); } void LocalDefinitionAtlas::setIdentifiers(const std::vector& identifiers) { - for (unsigned int i = 0; i < identifiers.size(); i++) { - if (i >= 2) defs.emplace_back(); //Don't emplace air or ignore - defTable.insert({identifiers[i], i}); - } + for (unsigned int i = 0; i < identifiers.size(); i++) { + if (i >= 2) defs.emplace_back(); //Don't emplace air or ignore + defTable.insert({ identifiers[i], i }); + } } void LocalDefinitionAtlas::registerDef(ItemDef* def) { - if (!defTable.count(def->identifier)) throw std::runtime_error("Client/Server definition desync: " + def->identifier + "."); - def->index = defTable[def->identifier]; - defs[def->index] = def; + if (!defTable.count(def->identifier)) + throw std::runtime_error("Client/Server definition desync: " + def->identifier + "."); + def->index = defTable[def->identifier]; + defs[def->index] = def; } diff --git a/src/game/atlas/LocalDefinitionAtlas.h b/src/game/atlas/LocalDefinitionAtlas.h index 1ffb5747..18c4267e 100644 --- a/src/game/atlas/LocalDefinitionAtlas.h +++ b/src/game/atlas/LocalDefinitionAtlas.h @@ -9,9 +9,10 @@ class TextureAtlas; class LocalDefinitionAtlas : public DefinitionAtlas { -public: - LocalDefinitionAtlas(TextureAtlas& atlas); - void registerDef(ItemDef* def) override; - - void setIdentifiers(const std::vector& identifiers); + public: + LocalDefinitionAtlas(TextureAtlas& atlas); + + void registerDef(ItemDef* def) override; + + void setIdentifiers(const std::vector& identifiers); }; diff --git a/src/game/atlas/ServerBiomeAtlas.cpp b/src/game/atlas/ServerBiomeAtlas.cpp index 0c2ee78e..d82bdd53 100644 --- a/src/game/atlas/ServerBiomeAtlas.cpp +++ b/src/game/atlas/ServerBiomeAtlas.cpp @@ -7,18 +7,18 @@ #include "game/def/BiomeDef.h" ServerBiomeAtlas::ServerBiomeAtlas(unsigned int seed) : - seed(seed) { - + seed(seed) { + BiomeDef* invalid = new BiomeDef(); invalid->identifier = "invalid"; invalid->humidity = -1; invalid->temperature = -1; invalid->roughness = -1; - registerBiome(invalid); + registerBiome(invalid); } -void ServerBiomeAtlas::registerBiome(BiomeDef *def) { - defs.push_back(def); - defTable.insert({def->identifier, def->index}); +void ServerBiomeAtlas::registerBiome(BiomeDef* def) { + defs.push_back(def); + defTable.insert({ def->identifier, def->index }); } diff --git a/src/game/atlas/ServerBiomeAtlas.h b/src/game/atlas/ServerBiomeAtlas.h index 8551f045..fc574abd 100644 --- a/src/game/atlas/ServerBiomeAtlas.h +++ b/src/game/atlas/ServerBiomeAtlas.h @@ -7,9 +7,10 @@ #include "BiomeAtlas.h" class ServerBiomeAtlas : public BiomeAtlas { -public: - ServerBiomeAtlas(unsigned int seed); - void registerBiome(BiomeDef* def) override; - - unsigned int seed; + public: + ServerBiomeAtlas(unsigned int seed); + + void registerBiome(BiomeDef* def) override; + + unsigned int seed; }; diff --git a/src/game/atlas/ServerDefinitionAtlas.cpp b/src/game/atlas/ServerDefinitionAtlas.cpp index 74a773d6..fe14d8ca 100644 --- a/src/game/atlas/ServerDefinitionAtlas.cpp +++ b/src/game/atlas/ServerDefinitionAtlas.cpp @@ -7,33 +7,33 @@ #include "game/def/BlockDef.h" ServerDefinitionAtlas::ServerDefinitionAtlas() { - //Invalid Node - BlockModel invalidModel = BlockModel::createCube({}, {}, {}); - BlockDef* invalid = new BlockDef(); - invalid->identifier = "invalid"; - invalid->name = "INVALID"; - invalid->maxStackSize = 64; - invalid->model = invalidModel; - invalid->farModel = invalidModel; - invalid->sBoxes = {{{0, 0, 0}, {1, 1, 1}}}; - invalid->cBoxes = {{{0, 0, 0}, {1, 1, 1}}}; - registerDef(invalid); - - //Air Node - BlockModel nullModel {}; - BlockDef* air = new BlockDef(); - air->identifier = "air"; - air->index = 1; - air->name = "Air"; - air->maxStackSize = 64; - air->model = nullModel; - air->farModel = nullModel; - air->solid = false; - air->culls = false; - registerDef(air); + //Invalid Node + BlockModel invalidModel = BlockModel::createCube({}, {}, {}); + BlockDef* invalid = new BlockDef(); + invalid->identifier = "invalid"; + invalid->name = "INVALID"; + invalid->maxStackSize = 64; + invalid->model = invalidModel; + invalid->farModel = invalidModel; + invalid->sBoxes = {{{ 0, 0, 0 }, { 1, 1, 1 }}}; + invalid->cBoxes = {{{ 0, 0, 0 }, { 1, 1, 1 }}}; + registerDef(invalid); + + //Air Node + BlockModel nullModel{}; + BlockDef* air = new BlockDef(); + air->identifier = "air"; + air->index = 1; + air->name = "Air"; + air->maxStackSize = 64; + air->model = nullModel; + air->farModel = nullModel; + air->solid = false; + air->culls = false; + registerDef(air); } void ServerDefinitionAtlas::registerDef(ItemDef* def) { - defs.push_back(def); - defTable.insert({def->identifier, def->index}); + defs.push_back(def); + defTable.insert({ def->identifier, def->index }); } \ No newline at end of file diff --git a/src/game/atlas/ServerDefinitionAtlas.h b/src/game/atlas/ServerDefinitionAtlas.h index 6628ee51..bae83e2b 100644 --- a/src/game/atlas/ServerDefinitionAtlas.h +++ b/src/game/atlas/ServerDefinitionAtlas.h @@ -7,7 +7,8 @@ #include "DefinitionAtlas.h" class ServerDefinitionAtlas : public DefinitionAtlas { -public: - ServerDefinitionAtlas(); - void registerDef(ItemDef* def) override; + public: + ServerDefinitionAtlas(); + + void registerDef(ItemDef* def) override; }; diff --git a/src/game/atlas/TextureAtlas.cpp b/src/game/atlas/TextureAtlas.cpp index dc398342..76d36f3a 100644 --- a/src/game/atlas/TextureAtlas.cpp +++ b/src/game/atlas/TextureAtlas.cpp @@ -14,11 +14,11 @@ #include "game/atlas/asset/AtlasRef.h" TextureAtlas::TextureAtlas(unsigned int width, unsigned int height) : - pixelSize(width, (height == 0 ? width : height)), - tileSize(pixelSize.x / 16, pixelSize.y / 16), - atlasData(pixelSize.x * 4 * pixelSize.y) { - - maxTextureSlots = tileSize.x * tileSize.y; + pixelSize(width, (height == 0 ? width : height)), + tileSize(pixelSize.x / 16, pixelSize.y / 16), + atlasData(pixelSize.x * 4 * pixelSize.y) { + + maxTextureSlots = tileSize.x * tileSize.y; // int maxTexSize, texUnits; // @@ -27,294 +27,300 @@ TextureAtlas::TextureAtlas(unsigned int width, unsigned int height) : // // glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &texUnits); // std::cout << Log::info << "This GPU supports " << texUnits << " texture units." << Log::endl; - - empty = std::vector(tileSize.x * tileSize.y, true); - atlasTexture.loadFromBytes(&atlasData[0], pixelSize.x, pixelSize.y); - - createMissingImage(); + + empty = std::vector(tileSize.x * tileSize.y, true); + atlasTexture.loadFromBytes(&atlasData[0], pixelSize.x, pixelSize.y); + + createMissingImage(); } std::vector> TextureAtlas::loadDirectory(const std::string& path, bool base, bool recursive) { - std::vector> refs {}; - - cf_dir_t dir; - cf_dir_open(&dir, (path).c_str()); - - while (dir.has_next) { - cf_file_t file; - cf_read_file(&dir, &file); - - if (!file.is_dir && strcmp(file.ext, ".png") == 0) { - refs.push_back(loadImage(file.path, std::string(file.name).substr(0, std::string(file.name).size() - 4), base)); - } - - if (recursive && file.is_dir && strncmp(file.name, ".", 1) != 0) { - auto vec = loadDirectory(file.path, base, recursive); - refs.insert(refs.end(), vec.begin(), vec.end()); - } - - cf_dir_next(&dir); - } - cf_dir_close(&dir); - - return refs; + std::vector> refs{}; + + cf_dir_t dir; + cf_dir_open(&dir, (path).c_str()); + + while (dir.has_next) { + cf_file_t file; + cf_read_file(&dir, &file); + + if (!file.is_dir && strcmp(file.ext, ".png") == 0) { + refs.push_back( + loadImage(file.path, std::string(file.name).substr(0, std::string(file.name).size() - 4), base)); + } + + if (recursive && file.is_dir && strncmp(file.name, ".", 1) != 0) { + auto vec = loadDirectory(file.path, base, recursive); + refs.insert(refs.end(), vec.begin(), vec.end()); + } + + cf_dir_next(&dir); + } + cf_dir_close(&dir); + + return refs; } -std::shared_ptr TextureAtlas::loadImage(const std::string &path, const std::string &name, bool base) { - int width, height; - unsigned char* data = stbi_load(path.data(), &width, &height, nullptr, 4); - auto ref = addImage(data, name, base, width, height); - free(data); - return ref; +std::shared_ptr TextureAtlas::loadImage(const std::string& path, const std::string& name, bool base) { + int width, height; + unsigned char* data = stbi_load(path.data(), &width, &height, nullptr, 4); + auto ref = addImage(data, name, base, width, height); + free(data); + return ref; } void TextureAtlas::update() { - auto it = textures.cbegin(); - - while (it != textures.cend()) { - auto curr = it++; - - if (!curr->second->base && curr->second.unique()) { - deleteImage(curr->second); - textures.erase(curr); - } - } + auto it = textures.cbegin(); + + while (it != textures.cend()) { + auto curr = it++; + + if (!curr->second->base && curr->second.unique()) { + deleteImage(curr->second); + textures.erase(curr); + } + } } -glm::vec4 TextureAtlas::sampleTexturePixel(const std::shared_ptr &atlasRef, glm::vec2 pixel) { - glm::vec2 absPos = {atlasRef->pos.x + pixel.x, atlasRef->pos.y + pixel.y}; - unsigned int index = (static_cast(absPos.y) * pixelSize.x + static_cast(absPos.x)) * 4; - - return { - static_cast(atlasData[index]) / 255.f, - static_cast(atlasData[index + 1]) / 255.f, - static_cast(atlasData[index + 2]) / 255.f, - static_cast(atlasData[index + 3]) / 255.f, - }; +glm::vec4 TextureAtlas::sampleTexturePixel(const std::shared_ptr& atlasRef, glm::vec2 pixel) { + glm::vec2 absPos = { atlasRef->pos.x + pixel.x, atlasRef->pos.y + pixel.y }; + unsigned int index = (static_cast(absPos.y) * pixelSize.x + static_cast(absPos.x)) * 4; + + return { + static_cast(atlasData[index]) / 255.f, + static_cast(atlasData[index + 1]) / 255.f, + static_cast(atlasData[index + 2]) / 255.f, + static_cast(atlasData[index + 3]) / 255.f, + }; } -std::shared_ptr TextureAtlas::addImage(unsigned char *data, const std::string& name, bool base, int texWidth, int texHeight) { - std::shared_ptr ref; - - if (textures.count(name) != 0) ref = textures[name]; - else ref = std::make_shared(); - - ref->name = name; - ref->base = base; - ref->width = texWidth; - ref->height = texHeight; - - auto tileWidth = static_cast(std::ceil(texWidth / 16.0f)); - auto tileHeight = static_cast(std::ceil(texHeight / 16.0f)); - - if (tileWidth != ref->tileWidth || tileHeight != ref->tileHeight) { - ref->tileWidth = tileWidth; - ref->tileHeight = tileHeight; - - auto space = findImageSpace(tileWidth, tileHeight); - if (space.x < 0) throw std::runtime_error("Failed to find space in the dynamic definition atlas."); - - textureSlotsUsed += tileWidth * tileHeight; - - ref->tileX = static_cast(space.x); - ref->tileY = static_cast(space.y); - - ref->pos = {space.x * 16, space.y * 16, space.x * 16 + texWidth, space.y * 16 + texHeight}; - ref->uv = {(space.x * 16) / pixelSize.x, (space.y * 16) / pixelSize.y, - (space.x * 16 + texWidth) / pixelSize.x, (space.y * 16 + texHeight) / pixelSize.y}; - - textures.insert({name, ref}); - } - - updateAtlas(ref->tileX, ref->tileY, texWidth, texHeight, data); - return ref; +std::shared_ptr +TextureAtlas::addImage(unsigned char* data, const std::string& name, bool base, int texWidth, int texHeight) { + std::shared_ptr ref; + + if (textures.count(name) != 0) ref = textures[name]; + else ref = std::make_shared(); + + ref->name = name; + ref->base = base; + ref->width = texWidth; + ref->height = texHeight; + + auto tileWidth = static_cast(std::ceil(texWidth / 16.0f)); + auto tileHeight = static_cast(std::ceil(texHeight / 16.0f)); + + if (tileWidth != ref->tileWidth || tileHeight != ref->tileHeight) { + ref->tileWidth = tileWidth; + ref->tileHeight = tileHeight; + + auto space = findImageSpace(tileWidth, tileHeight); + if (space.x < 0) throw std::runtime_error("Failed to find space in the dynamic definition atlas."); + + textureSlotsUsed += tileWidth * tileHeight; + + ref->tileX = static_cast(space.x); + ref->tileY = static_cast(space.y); + + ref->pos = { space.x * 16, space.y * 16, space.x * 16 + texWidth, space.y * 16 + texHeight }; + ref->uv = { (space.x * 16) / pixelSize.x, (space.y * 16) / pixelSize.y, + (space.x * 16 + texWidth) / pixelSize.x, (space.y * 16 + texHeight) / pixelSize.y }; + + textures.insert({ name, ref }); + } + + updateAtlas(ref->tileX, ref->tileY, texWidth, texHeight, data); + return ref; } std::shared_ptr TextureAtlas::generateCrackImage(const std::string& name, unsigned short crackLevel) { - RawTexData base = getBytesOfTex(name); - - std::string crackStr("zeus:default:crack_" + std::to_string(crackLevel)); - RawTexData crack = getBytesOfTex(crackStr); - - for (int i = 0; i < base.width * base.height; i++) { - float alpha = crack.data[i * 4 + 3] / 255.f; - - base.data[i * 4 + 0] = static_cast(base.data[i * 4 + 0] * (1 - alpha) + crack.data[i * 4 + 0] * alpha); - base.data[i * 4 + 1] = static_cast(base.data[i * 4 + 1] * (1 - alpha) + crack.data[i * 4 + 1] * alpha); - base.data[i * 4 + 2] = static_cast(base.data[i * 4 + 2] * (1 - alpha) + crack.data[i * 4 + 2] * alpha); - } - - auto ref = addImage(base.data, name + "_crack_" + std::to_string(crackLevel), false, base.width, base.height); - - delete [] base.data; - delete [] crack.data; - - return ref; + RawTexData base = getBytesOfTex(name); + + std::string crackStr("zeus:default:crack_" + std::to_string(crackLevel)); + RawTexData crack = getBytesOfTex(crackStr); + + for (int i = 0; i < base.width * base.height; i++) { + float alpha = crack.data[i * 4 + 3] / 255.f; + + base.data[i * 4 + 0] = static_cast(base.data[i * 4 + 0] * (1 - alpha) + + crack.data[i * 4 + 0] * alpha); + base.data[i * 4 + 1] = static_cast(base.data[i * 4 + 1] * (1 - alpha) + + crack.data[i * 4 + 1] * alpha); + base.data[i * 4 + 2] = static_cast(base.data[i * 4 + 2] * (1 - alpha) + + crack.data[i * 4 + 2] * alpha); + } + + auto ref = addImage(base.data, name + "_crack_" + std::to_string(crackLevel), false, base.width, base.height); + + delete[] base.data; + delete[] crack.data; + + return ref; } -std::shared_ptr TextureAtlas::operator[](const std::string &name) { - if (textures.count(name)) return textures[name]; - - std::shared_ptr gen = generateTexture(name); - if (gen) return gen; - - throw std::runtime_error("Invalid texture: '" + name + "'"); +std::shared_ptr TextureAtlas::operator[](const std::string& name) { + if (textures.count(name)) return textures[name]; + + std::shared_ptr gen = generateTexture(name); + if (gen) return gen; + + throw std::runtime_error("Invalid texture: '" + name + "'"); } std::shared_ptr TextureAtlas::generateTexture(std::string req) { - req.erase(std::remove(req.begin(), req.end(), ' '), req.end()); - - if (req.find_first_of('(') != std::string::npos) { - if (req.find_last_of(')') == std::string::npos) { - throw std::runtime_error("Mismatched braces."); - } - - std::string::size_type paramsBegin = req.find_first_of('('); - std::string::size_type paramsEnd = req.find_last_of(')'); - - std::string paramName = req.substr(0, paramsBegin); - std::string paramsString = req.substr(paramsBegin + 1, paramsEnd - paramsBegin - 1); - - std::vector params; - std::string::size_type pos = 0; - while ((pos = paramsString.find(',')) != std::string::npos) { - params.push_back(paramsString.substr(0, pos)); - paramsString.erase(0, pos + 1); - } - params.push_back(paramsString); - - if (paramName == "crop") { - if (params.size() != 5) throw std::runtime_error("crop() requires 5 parameters."); - glm::ivec4 loc = {atof(params[0].data()), atof(params[1].data()), atof(params[2].data()), atof(params[3].data())}; - std::shared_ptr src = operator[](params[4]); - - auto data = getBytesAtPos({src->pos.x + loc.x, src->pos.y + loc.y}, {loc.z, loc.w}).data; - return addImage(data, req, false, loc.z, loc.w); - } - else { - throw std::runtime_error("Invalid parameter."); - return nullptr; - } - } - - return nullptr; + req.erase(std::remove(req.begin(), req.end(), ' '), req.end()); + + if (req.find_first_of('(') != std::string::npos) { + if (req.find_last_of(')') == std::string::npos) { + throw std::runtime_error("Mismatched braces."); + } + + std::string::size_type paramsBegin = req.find_first_of('('); + std::string::size_type paramsEnd = req.find_last_of(')'); + + std::string paramName = req.substr(0, paramsBegin); + std::string paramsString = req.substr(paramsBegin + 1, paramsEnd - paramsBegin - 1); + + std::vector params; + std::string::size_type pos = 0; + while ((pos = paramsString.find(',')) != std::string::npos) { + params.push_back(paramsString.substr(0, pos)); + paramsString.erase(0, pos + 1); + } + params.push_back(paramsString); + + if (paramName == "crop") { + if (params.size() != 5) throw std::runtime_error("crop() requires 5 parameters."); + glm::ivec4 loc = { atof(params[0].data()), atof(params[1].data()), atof(params[2].data()), + atof(params[3].data()) }; + std::shared_ptr src = operator[](params[4]); + + auto data = getBytesAtPos({ src->pos.x + loc.x, src->pos.y + loc.y }, { loc.z, loc.w }).data; + return addImage(data, req, false, loc.z, loc.w); + } + else { + throw std::runtime_error("Invalid parameter."); + return nullptr; + } + } + + return nullptr; } -TextureAtlas::RawTexData TextureAtlas::getBytesOfTex(const std::string &name) { - glm::vec4 pos; - - if (textures.count(name)) pos = textures[name]->pos; - else { - std::cout << Log::err << "Invalid base texture \"" << name << "\"." << Log::endl; - pos = textures["_missing"]->pos; - } - - return getBytesAtPos({pos.x, pos.y}, {pos.z - pos.x, pos.w - pos.y}); +TextureAtlas::RawTexData TextureAtlas::getBytesOfTex(const std::string& name) { + glm::vec4 pos; + + if (textures.count(name)) pos = textures[name]->pos; + else { + std::cout << Log::err << "Invalid base texture \"" << name << "\"." << Log::endl; + pos = textures["_missing"]->pos; + } + + return getBytesAtPos({ pos.x, pos.y }, { pos.z - pos.x, pos.w - pos.y }); } TextureAtlas::RawTexData TextureAtlas::getBytesAtPos(glm::ivec2 pos, glm::ivec2 dims) { - RawTexData data {}; - data.width = dims.x; - data.height = dims.y; - - auto pixels = new unsigned char[data.width * data.height * 4]; - - for (int i = 0; i < data.width * data.height; i++) { - int xx = pos.x + (i % data.width); - int yy = pos.y + (i / data.width); - - pixels[i * 4 + 0] = atlasData[xx * 4 + yy * (pixelSize.x * 4)]; - pixels[i * 4 + 1] = atlasData[xx * 4 + 1 + yy * (pixelSize.x * 4)]; - pixels[i * 4 + 2] = atlasData[xx * 4 + 2 + yy * (pixelSize.x * 4)]; - pixels[i * 4 + 3] = atlasData[xx * 4 + 3 + yy * (pixelSize.x * 4)]; - } - - data.data = pixels; - - return data; + RawTexData data{}; + data.width = dims.x; + data.height = dims.y; + + auto pixels = new unsigned char[data.width * data.height * 4]; + + for (int i = 0; i < data.width * data.height; i++) { + int xx = pos.x + (i % data.width); + int yy = pos.y + (i / data.width); + + pixels[i * 4 + 0] = atlasData[xx * 4 + yy * (pixelSize.x * 4)]; + pixels[i * 4 + 1] = atlasData[xx * 4 + 1 + yy * (pixelSize.x * 4)]; + pixels[i * 4 + 2] = atlasData[xx * 4 + 2 + yy * (pixelSize.x * 4)]; + pixels[i * 4 + 3] = atlasData[xx * 4 + 3 + yy * (pixelSize.x * 4)]; + } + + data.data = pixels; + + return data; } glm::vec2 TextureAtlas::findImageSpace(int w, int h) { - for (int j = 0; j < tileSize.y - (h - 1); j++) { - for (int i = 0; i < tileSize.x - (w - 1); i++) { - if (empty[j * tileSize.x + i]) { - bool space = true; - - for (int k = 0; k < h; k++) { - for (int l = 0; l < w; l++) { - if (!empty[(j + k) * tileSize.x + (i + l)]) { - space = false; - break; - } - } - - if (!space) break; - } - - if (space) { - for (int k = 0; k < h; k++) { - for (int l = 0; l < w; l++) { - empty[(j + k) * tileSize.x + (i + l)] = false; - } - } - return glm::vec2(i, j); - } - } - } - } - - return glm::vec2(-1, -1); + for (int j = 0; j < tileSize.y - (h - 1); j++) { + for (int i = 0; i < tileSize.x - (w - 1); i++) { + if (empty[j * tileSize.x + i]) { + bool space = true; + + for (int k = 0; k < h; k++) { + for (int l = 0; l < w; l++) { + if (!empty[(j + k) * tileSize.x + (i + l)]) { + space = false; + break; + } + } + + if (!space) break; + } + + if (space) { + for (int k = 0; k < h; k++) { + for (int l = 0; l < w; l++) { + empty[(j + k) * tileSize.x + (i + l)] = false; + } + } + return glm::vec2(i, j); + } + } + } + } + + return glm::vec2(-1, -1); } void TextureAtlas::createMissingImage() { - auto data = new unsigned char[16 * 4 * 16]; - for (int i = 0; i < 16 * 16; i++) { - - unsigned char m = 0; - if ((i % 16 < 8) ^ ((i / 16) < 8)) m = 255; - - data[i * 4 + 0] = m; - data[i * 4 + 1] = 0; - data[i * 4 + 2] = m; - data[i * 4 + 3] = 255; - } - - addImage(data, "_missing", true, 16, 16); - delete [] data; + auto data = new unsigned char[16 * 4 * 16]; + for (int i = 0; i < 16 * 16; i++) { + + unsigned char m = 0; + if ((i % 16 < 8) ^ ((i / 16) < 8)) m = 255; + + data[i * 4 + 0] = m; + data[i * 4 + 1] = 0; + data[i * 4 + 2] = m; + data[i * 4 + 3] = 255; + } + + addImage(data, "_missing", true, 16, 16); + delete[] data; } -void TextureAtlas::updateAtlas(int tileX, int tileY, int texWidth, int texHeight, unsigned char *data) { - int baseX = tileX * 16; - int baseY = tileY * 16; - - atlasTexture.updateTexture(baseX, baseY, texWidth, texHeight, data); - - for (int i = 0; i < texWidth * texHeight * 4; i++) { - int xx = (i / 4) % texWidth; - int yy = (i / 4) / texWidth; - int of = i % 4; - - atlasData[(baseX + xx + (baseY + yy) * pixelSize.x) * 4 + of] = data[(xx + yy * texWidth) * 4 + of]; - } +void TextureAtlas::updateAtlas(int tileX, int tileY, int texWidth, int texHeight, unsigned char* data) { + int baseX = tileX * 16; + int baseY = tileY * 16; + + atlasTexture.updateTexture(baseX, baseY, texWidth, texHeight, data); + + for (int i = 0; i < texWidth * texHeight * 4; i++) { + int xx = (i / 4) % texWidth; + int yy = (i / 4) / texWidth; + int of = i % 4; + + atlasData[(baseX + xx + (baseY + yy) * pixelSize.x) * 4 + of] = data[(xx + yy * texWidth) * 4 + of]; + } } void TextureAtlas::deleteImage(std::shared_ptr ref) { - // Actually delete the image from the texture (for debugging) - - //auto data = new unsigned char[ref->width * ref->height * 4]; - // - //for (int i = 0; i < ref->width * ref->height * 4; i++) { - // data[i] = 0; - //} - // - //updateAtlas(ref->tileX, ref->tileY, ref->width, ref->height, data); - //delete[] data; - - textureSlotsUsed -= ref->tileWidth * ref->tileHeight; - - for (float i = ref->tileX; i < ref->tileX + ref->tileWidth; i++) { - for (float j = ref->tileY; j < ref->tileY + ref->tileHeight; j++) { - empty[j * tileSize.x + i] = true; - } - } + // Actually delete the image from the texture (for debugging) + + //auto data = new unsigned char[ref->width * ref->height * 4]; + // + //for (int i = 0; i < ref->width * ref->height * 4; i++) { + // data[i] = 0; + //} + // + //updateAtlas(ref->tileX, ref->tileY, ref->width, ref->height, data); + //delete[] data; + + textureSlotsUsed -= ref->tileWidth * ref->tileHeight; + + for (float i = ref->tileX; i < ref->tileX + ref->tileWidth; i++) { + for (float j = ref->tileY; j < ref->tileY + ref->tileHeight; j++) { + empty[j * tileSize.x + i] = true; + } + } } \ No newline at end of file diff --git a/src/game/atlas/TextureAtlas.h b/src/game/atlas/TextureAtlas.h index 90b591de..15273e1a 100644 --- a/src/game/atlas/TextureAtlas.h +++ b/src/game/atlas/TextureAtlas.h @@ -15,48 +15,57 @@ class AtlasRef; class TextureAtlas { -public: - struct RawTexData { - unsigned char* data; - int width; - int height; - }; - - TextureAtlas() = default; - explicit TextureAtlas(unsigned int width, unsigned int height = 0); - - void update(); - - std::vector> loadDirectory(const std::string& path, bool base = true, bool recursive = true); - std::shared_ptr loadImage(const std::string& path, const std::string& name, bool base = false); - - glm::vec4 sampleTexturePixel(const std::shared_ptr& atlasRef, glm::vec2 pixel); - std::shared_ptr operator[](const std::string& name); - - std::shared_ptr addImage(unsigned char *data, const std::string& name, bool base, int texWidth, int texHeight); - std::shared_ptr generateCrackImage(const std::string &name, unsigned short crackLevel); - - glm::ivec2 pixelSize {}; - glm::ivec2 tileSize {}; - - Texture atlasTexture {}; - std::vector atlasData; - - unsigned int textureSlotsUsed = 0; - unsigned int maxTextureSlots = 0; -private: - std::shared_ptr generateTexture(std::string req); - - RawTexData getBytesOfTex(const std::string& name); - RawTexData getBytesAtPos(glm::ivec2 pos, glm::ivec2 dims); - glm::vec2 findImageSpace(int w, int h); - - void createMissingImage(); - void updateAtlas(int tileX, int tileY, int texWidth, int texHeight, unsigned char *data); - - void deleteImage(std::shared_ptr ref); - - std::map> textures; - std::vector empty; + public: + struct RawTexData { + unsigned char* data; + int width; + int height; + }; + + TextureAtlas() = default; + + explicit TextureAtlas(unsigned int width, unsigned int height = 0); + + void update(); + + std::vector> + loadDirectory(const std::string& path, bool base = true, bool recursive = true); + + std::shared_ptr loadImage(const std::string& path, const std::string& name, bool base = false); + + glm::vec4 sampleTexturePixel(const std::shared_ptr& atlasRef, glm::vec2 pixel); + + std::shared_ptr operator[](const std::string& name); + + std::shared_ptr + addImage(unsigned char* data, const std::string& name, bool base, int texWidth, int texHeight); + + std::shared_ptr generateCrackImage(const std::string& name, unsigned short crackLevel); + + glm::ivec2 pixelSize{}; + glm::ivec2 tileSize{}; + + Texture atlasTexture{}; + std::vector atlasData; + + unsigned int textureSlotsUsed = 0; + unsigned int maxTextureSlots = 0; + private: + std::shared_ptr generateTexture(std::string req); + + RawTexData getBytesOfTex(const std::string& name); + + RawTexData getBytesAtPos(glm::ivec2 pos, glm::ivec2 dims); + + glm::vec2 findImageSpace(int w, int h); + + void createMissingImage(); + + void updateAtlas(int tileX, int tileY, int texWidth, int texHeight, unsigned char* data); + + void deleteImage(std::shared_ptr ref); + + std::map> textures; + std::vector empty; }; diff --git a/src/game/atlas/asset/AssetStorage.h b/src/game/atlas/asset/AssetStorage.h index c7de5dfc..41c29067 100644 --- a/src/game/atlas/asset/AssetStorage.h +++ b/src/game/atlas/asset/AssetStorage.h @@ -10,8 +10,8 @@ #include "SerializedModel.h" class AssetStorage { -public: - std::vector textures; - std::vector models; + public: + std::vector textures; + std::vector models; }; diff --git a/src/game/atlas/asset/AssetType.h b/src/game/atlas/asset/AssetType.h index 7c71735a..d63b9fad 100644 --- a/src/game/atlas/asset/AssetType.h +++ b/src/game/atlas/asset/AssetType.h @@ -5,7 +5,7 @@ #pragma once enum class AssetType { - END = 0, - TEXTURE, - MODEL + END = 0, + TEXTURE, + MODEL }; diff --git a/src/game/atlas/asset/AtlasRef.h b/src/game/atlas/asset/AtlasRef.h index 2ebfac52..21c29c08 100644 --- a/src/game/atlas/asset/AtlasRef.h +++ b/src/game/atlas/asset/AtlasRef.h @@ -5,18 +5,18 @@ #pragma once struct AtlasRef { - int tileX = 0; - int tileY = 0; - int tileWidth = 0; - int tileHeight = 0; - - bool base = false; - - glm::vec4 pos {}; - glm::vec4 uv {}; - std::string name = ""; - - int width = 0; - int height = 0; + int tileX = 0; + int tileY = 0; + int tileWidth = 0; + int tileHeight = 0; + + bool base = false; + + glm::vec4 pos{}; + glm::vec4 uv{}; + std::string name = ""; + + int width = 0; + int height = 0; }; diff --git a/src/game/atlas/asset/ModelStore.h b/src/game/atlas/asset/ModelStore.h index 5ab999e9..abd820c6 100644 --- a/src/game/atlas/asset/ModelStore.h +++ b/src/game/atlas/asset/ModelStore.h @@ -9,6 +9,6 @@ #include "SerializedModel.h" class ModelStore { -public: - std::map models; + public: + std::map models; }; diff --git a/src/game/atlas/asset/SerializedModel.h b/src/game/atlas/asset/SerializedModel.h index 9e7e3dbd..019f76ee 100644 --- a/src/game/atlas/asset/SerializedModel.h +++ b/src/game/atlas/asset/SerializedModel.h @@ -7,7 +7,7 @@ #include struct SerializedModel { - std::string name {}; - std::string data {}; - std::string format {}; + std::string name{}; + std::string data{}; + std::string format{}; }; \ No newline at end of file diff --git a/src/game/atlas/asset/ServerTexture.h b/src/game/atlas/asset/ServerTexture.h index ed4fc128..7b0bf27b 100644 --- a/src/game/atlas/asset/ServerTexture.h +++ b/src/game/atlas/asset/ServerTexture.h @@ -7,9 +7,9 @@ #include struct ServerTexture { - std::string name {}; - std::string data {}; - unsigned int width = 0; - unsigned int height = 0; + std::string name{}; + std::string data{}; + unsigned int width = 0; + unsigned int height = 0; }; diff --git a/src/game/def/BiomeDef.h b/src/game/def/BiomeDef.h index a8f3fb0f..46aac987 100644 --- a/src/game/def/BiomeDef.h +++ b/src/game/def/BiomeDef.h @@ -15,22 +15,22 @@ class Schematic; struct BiomeDef { - std::string identifier = ""; - unsigned int index = 0; - std::unordered_map tags {}; - - float temperature = 0; - float humidity = 0; - float roughness = 0; - - unsigned int topBlock = 0; - unsigned int soilBlock = 0; - unsigned int rockBlock = 0; - - std::vector heightmap; - std::vector volume; - - std::vector> schematics; - - glm::vec3 tint {}; + std::string identifier = ""; + unsigned int index = 0; + std::unordered_map tags{}; + + float temperature = 0; + float humidity = 0; + float roughness = 0; + + unsigned int topBlock = 0; + unsigned int soilBlock = 0; + unsigned int rockBlock = 0; + + std::vector heightmap; + std::vector volume; + + std::vector> schematics; + + glm::vec3 tint{}; }; diff --git a/src/game/def/BlockDef.cpp b/src/game/def/BlockDef.cpp index e36194e0..a004cc3b 100644 --- a/src/game/def/BlockDef.cpp +++ b/src/game/def/BlockDef.cpp @@ -5,35 +5,35 @@ #include "BlockDef.h" void BlockDef::createModel() { - std::unique_ptr entity = std::make_unique(); - unsigned int indOffset = 0; - - std::vector entityVertices; - std::vector indices; - - for (std::vector& pArray : model.parts) { - for (MeshPart& p : pArray) { - for (const BlockModelVertex &vertex : p.vertices) { - entityVertices.push_back(EntityVertex { - vertex.pos - glm::vec3(0.5f), - {vertex.tex.x, vertex.tex.y, 0, 1}, - {1, 1, 1}, - true, - vertex.nml, - {}, {} - }); - } - - for (unsigned int index : p.indices) indices.push_back(indOffset + index); - indOffset += p.vertices.size(); - } - } - - entity->create(entityVertices, indices); - entityModel = std::make_shared(); - entityModel->fromMesh(std::move(entity)); + std::unique_ptr entity = std::make_unique(); + unsigned int indOffset = 0; + + std::vector entityVertices; + std::vector indices; + + for (std::vector& pArray : model.parts) { + for (MeshPart& p : pArray) { + for (const BlockModelVertex& vertex : p.vertices) { + entityVertices.push_back(EntityVertex{ + vertex.pos - glm::vec3(0.5f), + { vertex.tex.x, vertex.tex.y, 0, 1 }, + { 1, 1, 1 }, + true, + vertex.nml, + {}, {} + }); + } + + for (unsigned int index : p.indices) indices.push_back(indOffset + index); + indOffset += p.vertices.size(); + } + } + + entity->create(entityVertices, indices); + entityModel = std::make_shared(); + entityModel->fromMesh(std::move(entity)); } bool BlockDef::hasInteraction() { - return callbacks.count(Callback::INTERACT) || callbacks.count(Callback::INTERACT_CLIENT); + return callbacks.count(Callback::INTERACT) || callbacks.count(Callback::INTERACT_CLIENT); } diff --git a/src/game/def/BlockDef.h b/src/game/def/BlockDef.h index a47c6c3a..e2ef5e87 100644 --- a/src/game/def/BlockDef.h +++ b/src/game/def/BlockDef.h @@ -15,26 +15,27 @@ #include "game/def/mesh/SelectionBox.h" class BlockDef : public ItemDef { -public: - BlockDef(): ItemDef {"", "", 0, 0, ItemDef::Type::BLOCK} {}; - - void createModel(); - bool hasInteraction(); - - BlockModel model; - BlockModel farModel; - - bool culls = true; - bool solid = true; - bool lightPropagates = false; - - int health = 0; - int defense = 0; - - glm::ivec3 lightSource {}; - - std::vector sBoxes {}; - std::vector cBoxes {}; - - std::unordered_map callbacks {}; + public: + BlockDef() : ItemDef{ "", "", 0, 0, ItemDef::Type::BLOCK } {}; + + void createModel(); + + bool hasInteraction(); + + BlockModel model; + BlockModel farModel; + + bool culls = true; + bool solid = true; + bool lightPropagates = false; + + int health = 0; + int defense = 0; + + glm::ivec3 lightSource{}; + + std::vector sBoxes{}; + std::vector cBoxes{}; + + std::unordered_map callbacks{}; }; diff --git a/src/game/def/CraftItemDef.cpp b/src/game/def/CraftItemDef.cpp index b9a116c0..02e865c3 100644 --- a/src/game/def/CraftItemDef.cpp +++ b/src/game/def/CraftItemDef.cpp @@ -7,94 +7,100 @@ #include "game/atlas/TextureAtlas.h" #include "game/atlas/asset/AtlasRef.h" -CraftItemDef::CraftItemDef(const std::string &identifier, const std::string &name, unsigned short maxStackSize, - const std::vector& textures, const std::vector>& textureRefs) : - CraftItemDef(identifier, 0, name, maxStackSize, textures, textureRefs) {} +CraftItemDef::CraftItemDef(const std::string& identifier, const std::string& name, unsigned short maxStackSize, + const std::vector& textures, const std::vector>& textureRefs) : + CraftItemDef(identifier, 0, name, maxStackSize, textures, textureRefs) {} CraftItemDef::CraftItemDef(const std::string& identifier, unsigned int index, const std::string& name, - unsigned short maxStackSize, const std::vector& textures, const std::vector>& textureRefs) : - - ItemDef {identifier, name, index, maxStackSize, ItemDef::Type::CRAFTITEM}, - textures(textures), - textureRefs(textureRefs) {} + unsigned short maxStackSize, const std::vector& textures, + const std::vector>& textureRefs) : + + ItemDef{ identifier, name, index, maxStackSize, ItemDef::Type::CRAFTITEM }, + textures(textures), + textureRefs(textureRefs) {} void CraftItemDef::createModel(TextureAtlas& atlas) { - std::unique_ptr mesh = std::make_unique(); - - std::vector vertices; - std::vector indices {0, 1, 2, 2, 3, 0, 4, 7, 6, 6, 5, 4}; - - const std::shared_ptr& ref = textureRefs[0]; - static const float xo = 0.040f; - - for (unsigned int i = 0; i <= 1; i++) { - float xx = xo * (i == 1 ? -1 : 1); - std::vector myVerts = { - {{xx, -0.5, -0.5}, {ref->uv.x, ref->uv.w, 0, 1}, {1, 1, 1}, true, {(i == 1 ? -1 : 1), 0, 0}, {}, {}}, - {{xx, 0.5, -0.5}, {ref->uv.x, ref->uv.y, 0, 1}, {1, 1, 1}, true, {(i == 1 ? -1 : 1), 0, 0}, {}, {}}, - {{xx, 0.5, 0.5}, {ref->uv.z, ref->uv.y, 0, 1}, {1, 1, 1}, true, {(i == 1 ? -1 : 1), 0, 0}, {}, {}}, - {{xx, -0.5, 0.5}, {ref->uv.z, ref->uv.w, 0, 1}, {1, 1, 1}, true, {(i == 1 ? -1 : 1), 0, 0}, {}, {}} - }; - vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); - } - - unsigned int indOffset = 8; - for (unsigned int i = 0; i < 16*16; i++) { - glm::vec2 samplePos = {i % 16, i / 16}; - glm::vec2 off {samplePos.x / 16.f, samplePos.y / 16.f}; - glm::vec4 col = atlas.sampleTexturePixel(ref, samplePos); - - if (col.w < 0.5) continue; - - if (samplePos.y == 0 || atlas.sampleTexturePixel(ref, {samplePos.x, samplePos.y - 1}).w < 0.5) { - std::vector myVerts = { - {{-xo, 0.5 - off.y, -0.5 + off.x }, col, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - {{-xo, 0.5 - off.y, -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - {{ xo, 0.5 - off.y, -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, 1, 0}, {}, {}}, - {{ xo, 0.5 - off.y, -0.5 + off.x }, col, {1, 1, 1}, false, {0, 1, 0}, {}, {}}}; - vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); - std::vector myInds = {indOffset, indOffset+1, indOffset+2, indOffset+2, indOffset+3, indOffset}; - indices.insert(indices.end(), myInds.begin(), myInds.end()); - indOffset += 4; - } - - if (samplePos.y == 15 || atlas.sampleTexturePixel(ref, {samplePos.x, samplePos.y + 1}).w < 0.5) { - std::vector myVerts = { - {{-xo, 0.5 - off.y - 0.0625, -0.5 + off.x }, col, {1, 1, 1}, false, {0, -1, 0}, {}, {}}, - {{-xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, -1, 0}, {}, {}}, - {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, -1, 0}, {}, {}}, - {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x }, col, {1, 1, 1}, false, {0, -1, 0}, {}, {}}}; - vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); - std::vector myInds = {indOffset, indOffset+3, indOffset+2, indOffset+2, indOffset+1, indOffset}; - indices.insert(indices.end(), myInds.begin(), myInds.end()); - indOffset += 4; - } - - if (samplePos.x == 0 || atlas.sampleTexturePixel(ref, {samplePos.x - 1, samplePos.y}).w < 0.5) { - std::vector myVerts = { - {{-xo, 0.5 - off.y - 0.0625, -0.5 + off.x}, col, {1, 1, 1}, false, {0, 0, 1}, {}, {}}, - {{-xo, 0.5 - off.y , -0.5 + off.x}, col, {1, 1, 1}, false, {0, 0, 1}, {}, {}}, - {{ xo, 0.5 - off.y , -0.5 + off.x}, col, {1, 1, 1}, false, {0, 0, 1}, {}, {}}, - {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x}, col, {1, 1, 1}, false, {0, 0, 1}, {}, {}}}; - vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); - std::vector myInds = {indOffset, indOffset+1, indOffset+2, indOffset+2, indOffset+3, indOffset}; - indices.insert(indices.end(), myInds.begin(), myInds.end()); - indOffset += 4; - } - - if (samplePos.x == 15 || atlas.sampleTexturePixel(ref, {samplePos.x + 1, samplePos.y}).w < 0.5) { - std::vector myVerts = { - {{-xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, 0, -1}, {}, {}}, - {{-xo, 0.5 - off.y , -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, 0, -1}, {}, {}}, - {{ xo, 0.5 - off.y , -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, 0, -1}, {}, {}}, - {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625}, col, {1, 1, 1}, false, {0, 0, -1}, {}, {}}}; - vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); - std::vector myInds = {indOffset, indOffset+3, indOffset+2, indOffset+2, indOffset+1, indOffset}; - indices.insert(indices.end(), myInds.begin(), myInds.end()); - indOffset += 4; - } - } - - mesh->create(vertices, indices); - entityModel->fromMesh(std::move(mesh)); + std::unique_ptr mesh = std::make_unique(); + + std::vector vertices; + std::vector indices{ 0, 1, 2, 2, 3, 0, 4, 7, 6, 6, 5, 4 }; + + const std::shared_ptr& ref = textureRefs[0]; + static const float xo = 0.040f; + + for (unsigned int i = 0; i <= 1; i++) { + float xx = xo * (i == 1 ? -1 : 1); + std::vector myVerts = { + {{ xx, -0.5, -0.5 }, { ref->uv.x, ref->uv.w, 0, 1 }, { 1, 1, 1 }, true, { (i == 1 ? -1 : 1), 0, 0 }, {}, + {}}, + {{ xx, 0.5, -0.5 }, { ref->uv.x, ref->uv.y, 0, 1 }, { 1, 1, 1 }, true, { (i == 1 ? -1 : 1), 0, 0 }, {}, {}}, + {{ xx, 0.5, 0.5 }, { ref->uv.z, ref->uv.y, 0, 1 }, { 1, 1, 1 }, true, { (i == 1 ? -1 : 1), 0, 0 }, {}, {}}, + {{ xx, -0.5, 0.5 }, { ref->uv.z, ref->uv.w, 0, 1 }, { 1, 1, 1 }, true, { (i == 1 ? -1 : 1), 0, 0 }, {}, {}} + }; + vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); + } + + unsigned int indOffset = 8; + for (unsigned int i = 0; i < 16 * 16; i++) { + glm::vec2 samplePos = { i % 16, i / 16 }; + glm::vec2 off{ samplePos.x / 16.f, samplePos.y / 16.f }; + glm::vec4 col = atlas.sampleTexturePixel(ref, samplePos); + + if (col.w < 0.5) continue; + + if (samplePos.y == 0 || atlas.sampleTexturePixel(ref, { samplePos.x, samplePos.y - 1 }).w < 0.5) { + std::vector myVerts = { + {{ -xo, 0.5 - off.y, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}}, + {{ -xo, 0.5 - off.y, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}}, + {{ xo, 0.5 - off.y, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}}, + {{ xo, 0.5 - off.y, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, 1, 0 }, {}, {}}}; + vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); + std::vector myInds = { indOffset, indOffset + 1, indOffset + 2, indOffset + 2, indOffset + 3, + indOffset }; + indices.insert(indices.end(), myInds.begin(), myInds.end()); + indOffset += 4; + } + + if (samplePos.y == 15 || atlas.sampleTexturePixel(ref, { samplePos.x, samplePos.y + 1 }).w < 0.5) { + std::vector myVerts = { + {{ -xo, 0.5 - off.y - 0.0625, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, -1, 0 }, {}, {}}, + {{ -xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, -1, 0 }, {}, {}}, + {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, -1, 0 }, {}, {}}, + {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, -1, 0 }, {}, {}}}; + vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); + std::vector myInds = { indOffset, indOffset + 3, indOffset + 2, indOffset + 2, indOffset + 1, + indOffset }; + indices.insert(indices.end(), myInds.begin(), myInds.end()); + indOffset += 4; + } + + if (samplePos.x == 0 || atlas.sampleTexturePixel(ref, { samplePos.x - 1, samplePos.y }).w < 0.5) { + std::vector myVerts = { + {{ -xo, 0.5 - off.y - 0.0625, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, 0, 1 }, {}, {}}, + {{ -xo, 0.5 - off.y, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, 0, 1 }, {}, {}}, + {{ xo, 0.5 - off.y, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, 0, 1 }, {}, {}}, + {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x }, col, { 1, 1, 1 }, false, { 0, 0, 1 }, {}, {}}}; + vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); + std::vector myInds = { indOffset, indOffset + 1, indOffset + 2, indOffset + 2, indOffset + 3, + indOffset }; + indices.insert(indices.end(), myInds.begin(), myInds.end()); + indOffset += 4; + } + + if (samplePos.x == 15 || atlas.sampleTexturePixel(ref, { samplePos.x + 1, samplePos.y }).w < 0.5) { + std::vector myVerts = { + {{ -xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, 0, -1 }, {}, {}}, + {{ -xo, 0.5 - off.y, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, 0, -1 }, {}, {}}, + {{ xo, 0.5 - off.y, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, 0, -1 }, {}, {}}, + {{ xo, 0.5 - off.y - 0.0625, -0.5 + off.x + 0.0625 }, col, { 1, 1, 1 }, false, { 0, 0, -1 }, {}, {}}}; + vertices.insert(vertices.end(), myVerts.begin(), myVerts.end()); + std::vector myInds = { indOffset, indOffset + 3, indOffset + 2, indOffset + 2, indOffset + 1, + indOffset }; + indices.insert(indices.end(), myInds.begin(), myInds.end()); + indOffset += 4; + } + } + + mesh->create(vertices, indices); + entityModel->fromMesh(std::move(mesh)); } \ No newline at end of file diff --git a/src/game/def/CraftItemDef.h b/src/game/def/CraftItemDef.h index 311d0cb0..b35bfc27 100644 --- a/src/game/def/CraftItemDef.h +++ b/src/game/def/CraftItemDef.h @@ -9,19 +9,22 @@ #include "ItemDef.h" class AtlasRef; + class TextureAtlas; class CraftItemDef : public ItemDef { -public: - CraftItemDef() = default; - CraftItemDef(const std::string& identifier, const std::string& name, unsigned short maxStackSize, - const std::vector& textures, const std::vector>& textureRefs); - - CraftItemDef(const std::string& identifier, unsigned int index, const std::string& name, - unsigned short maxStackSize, const std::vector& textures, const std::vector>& textureRefs); - - void createModel(TextureAtlas& atlas); - - std::vector textures {}; - std::vector> textureRefs {}; + public: + CraftItemDef() = default; + + CraftItemDef(const std::string& identifier, const std::string& name, unsigned short maxStackSize, + const std::vector& textures, const std::vector>& textureRefs); + + CraftItemDef(const std::string& identifier, unsigned int index, const std::string& name, + unsigned short maxStackSize, const std::vector& textures, + const std::vector>& textureRefs); + + void createModel(TextureAtlas& atlas); + + std::vector textures{}; + std::vector> textureRefs{}; }; diff --git a/src/game/def/ItemDef.h b/src/game/def/ItemDef.h index 011b7abe..8f0f9a27 100644 --- a/src/game/def/ItemDef.h +++ b/src/game/def/ItemDef.h @@ -9,23 +9,23 @@ #include "client/graph/Model.h" class ItemDef { -public: - ItemDef(const ItemDef& o) = delete; - - enum class Type { - INVALID, - BLOCK, - CRAFTITEM - }; - - std::string identifier = ""; - std::string name = ""; - unsigned int index = 0; - - unsigned short maxStackSize; - - Type type = Type::INVALID; - - std::shared_ptr entityModel = std::make_shared(); + public: + ItemDef(const ItemDef& o) = delete; + + enum class Type { + INVALID, + BLOCK, + CRAFTITEM + }; + + std::string identifier = ""; + std::string name = ""; + unsigned int index = 0; + + unsigned short maxStackSize; + + Type type = Type::INVALID; + + std::shared_ptr entityModel = std::make_shared(); }; diff --git a/src/game/def/mesh/BlockModel.cpp b/src/game/def/mesh/BlockModel.cpp index 642b5d3c..f80be2e7 100644 --- a/src/game/def/mesh/BlockModel.cpp +++ b/src/game/def/mesh/BlockModel.cpp @@ -8,88 +8,88 @@ BlockModel BlockModel::createCube(std::vector> textureRefs, - std::vector blendInds, std::vector> blendMaskRefs) { - - BlockModel blockModel; - blockModel.visible = true; - blockModel.culls = true; - - std::vector vertices {}; - std::vector indices {}; - unsigned int accessInd; - - for (auto& ref : textureRefs) if (ref != nullptr) blockModel.textureRefs.insert(ref); - - if (textureRefs.empty()) textureRefs.emplace_back(nullptr); - if (blendInds.empty()) blendInds.emplace_back(0); - if (blendMaskRefs.empty()) blendMaskRefs.emplace_back(nullptr); - - //Left Face - vertices = { - {{0, 0, 0}, {}, {0, 1}, {0, 1}}, - {{0, 0, 1}, {}, {1, 1}, {1, 1}}, - {{0, 1, 1}, {}, {1, 0}, {1, 0}}, - {{0, 1, 0}, {}, {0, 0}, {0, 0}}}; - indices = {0, 1, 2, 2, 3, 0}; - accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 2)); - MeshPart leftMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); - blockModel.parts[static_cast(EVec::LEFT)].push_back(leftMeshPart); - - //Right Face - vertices = { - {{1, 1, 1}, {}, {1, 0}, {1, 0}}, - {{1, 0, 1}, {}, {1, 1}, {1, 1}}, - {{1, 0, 0}, {}, {0, 1}, {0, 1}}, - {{1, 1, 0}, {}, {0, 0}, {0, 0}}}; - indices = {0, 1, 2, 2, 3, 0}; - accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 3)); - MeshPart rightMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); - blockModel.parts[static_cast(EVec::RIGHT)].push_back(rightMeshPart); - - //Top Face - vertices = { - {{0, 1, 0}, {}, {0, 0}, {0, 0}}, - {{0, 1, 1}, {}, {0, 1}, {0, 1}}, - {{1, 1, 1}, {}, {1, 1}, {1, 1}}, - {{1, 1, 0}, {}, {1, 0}, {1, 0}}}; - indices = {0, 1, 2, 2, 3, 0}; - accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 0)); - MeshPart topMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); - blockModel.parts[static_cast(EVec::TOP)].push_back(topMeshPart); - - //Bottom Face - vertices = { - {{0, 0, 0}, {}, {0, 0}, {0, 0}}, - {{1, 0, 0}, {}, {1, 0}, {1, 0}}, - {{1, 0, 1}, {}, {1, 1}, {1, 1}}, - {{0, 0, 1}, {}, {0, 1}, {0, 1}}}; - indices = {0, 1, 2, 2, 3, 0}; - accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 1)); - MeshPart bottomMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); - blockModel.parts[static_cast(EVec::BOTTOM)].push_back(bottomMeshPart); - - //Front Face - vertices = { - {{0, 0, 1}, {}, {0, 1}, {0, 1}}, - {{1, 0, 1}, {}, {1, 1}, {1, 1}}, - {{1, 1, 1}, {}, {1, 0}, {1, 0}}, - {{0, 1, 1}, {}, {0, 0}, {0, 0}}}; - indices = {0, 1, 2, 2, 3, 0}; - accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 4)); - MeshPart frontMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); - blockModel.parts[static_cast(EVec::FRONT)].push_back(frontMeshPart); - - //Back Face - vertices = { - {{0, 0, 0}, {}, {0, 1}, {0, 1}}, - {{0, 1, 0}, {}, {0, 0}, {0, 0}}, - {{1, 1, 0}, {}, {1, 0}, {1, 0}}, - {{1, 0, 0}, {}, {1, 1}, {1, 1}}}; - indices = {0, 1, 2, 2, 3, 0}; - accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 5)); - MeshPart backMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); - blockModel.parts[static_cast(EVec::BACK)].push_back(backMeshPart); - - return blockModel; + std::vector blendInds, std::vector> blendMaskRefs) { + + BlockModel blockModel; + blockModel.visible = true; + blockModel.culls = true; + + std::vector vertices{}; + std::vector indices{}; + unsigned int accessInd; + + for (auto& ref : textureRefs) if (ref != nullptr) blockModel.textureRefs.insert(ref); + + if (textureRefs.empty()) textureRefs.emplace_back(nullptr); + if (blendInds.empty()) blendInds.emplace_back(0); + if (blendMaskRefs.empty()) blendMaskRefs.emplace_back(nullptr); + + //Left Face + vertices = { + {{ 0, 0, 0 }, {}, { 0, 1 }, { 0, 1 }}, + {{ 0, 0, 1 }, {}, { 1, 1 }, { 1, 1 }}, + {{ 0, 1, 1 }, {}, { 1, 0 }, { 1, 0 }}, + {{ 0, 1, 0 }, {}, { 0, 0 }, { 0, 0 }}}; + indices = { 0, 1, 2, 2, 3, 0 }; + accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 2)); + MeshPart leftMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); + blockModel.parts[static_cast(EVec::LEFT)].push_back(leftMeshPart); + + //Right Face + vertices = { + {{ 1, 1, 1 }, {}, { 1, 0 }, { 1, 0 }}, + {{ 1, 0, 1 }, {}, { 1, 1 }, { 1, 1 }}, + {{ 1, 0, 0 }, {}, { 0, 1 }, { 0, 1 }}, + {{ 1, 1, 0 }, {}, { 0, 0 }, { 0, 0 }}}; + indices = { 0, 1, 2, 2, 3, 0 }; + accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 3)); + MeshPart rightMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); + blockModel.parts[static_cast(EVec::RIGHT)].push_back(rightMeshPart); + + //Top Face + vertices = { + {{ 0, 1, 0 }, {}, { 0, 0 }, { 0, 0 }}, + {{ 0, 1, 1 }, {}, { 0, 1 }, { 0, 1 }}, + {{ 1, 1, 1 }, {}, { 1, 1 }, { 1, 1 }}, + {{ 1, 1, 0 }, {}, { 1, 0 }, { 1, 0 }}}; + indices = { 0, 1, 2, 2, 3, 0 }; + accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 0)); + MeshPart topMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); + blockModel.parts[static_cast(EVec::TOP)].push_back(topMeshPart); + + //Bottom Face + vertices = { + {{ 0, 0, 0 }, {}, { 0, 0 }, { 0, 0 }}, + {{ 1, 0, 0 }, {}, { 1, 0 }, { 1, 0 }}, + {{ 1, 0, 1 }, {}, { 1, 1 }, { 1, 1 }}, + {{ 0, 0, 1 }, {}, { 0, 1 }, { 0, 1 }}}; + indices = { 0, 1, 2, 2, 3, 0 }; + accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 1)); + MeshPart bottomMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); + blockModel.parts[static_cast(EVec::BOTTOM)].push_back(bottomMeshPart); + + //Front Face + vertices = { + {{ 0, 0, 1 }, {}, { 0, 1 }, { 0, 1 }}, + {{ 1, 0, 1 }, {}, { 1, 1 }, { 1, 1 }}, + {{ 1, 1, 1 }, {}, { 1, 0 }, { 1, 0 }}, + {{ 0, 1, 1 }, {}, { 0, 0 }, { 0, 0 }}}; + indices = { 0, 1, 2, 2, 3, 0 }; + accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 4)); + MeshPart frontMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); + blockModel.parts[static_cast(EVec::FRONT)].push_back(frontMeshPart); + + //Back Face + vertices = { + {{ 0, 0, 0 }, {}, { 0, 1 }, { 0, 1 }}, + {{ 0, 1, 0 }, {}, { 0, 0 }, { 0, 0 }}, + {{ 1, 1, 0 }, {}, { 1, 0 }, { 1, 0 }}, + {{ 1, 0, 0 }, {}, { 1, 1 }, { 1, 1 }}}; + indices = { 0, 1, 2, 2, 3, 0 }; + accessInd = (std::max)(0, (std::min)(static_cast(textureRefs.size() - 1), 5)); + MeshPart backMeshPart(vertices, indices, textureRefs[accessInd], blendInds[accessInd], blendMaskRefs[accessInd]); + blockModel.parts[static_cast(EVec::BACK)].push_back(backMeshPart); + + return blockModel; } diff --git a/src/game/def/mesh/BlockModel.h b/src/game/def/mesh/BlockModel.h index 5cbd4769..c2fd2452 100644 --- a/src/game/def/mesh/BlockModel.h +++ b/src/game/def/mesh/BlockModel.h @@ -10,13 +10,13 @@ #include "MeshPart.h" struct BlockModel { - std::array, 7> parts {}; - std::vector> meshMods {}; - std::set> textureRefs {}; - - bool culls = false; - bool visible = false; - - static BlockModel createCube(std::vector> textureRefs, - std::vector blendInds, std::vector> blendMaskRefs); + std::array, 7> parts{}; + std::vector> meshMods{}; + std::set> textureRefs{}; + + bool culls = false; + bool visible = false; + + static BlockModel createCube(std::vector> textureRefs, + std::vector blendInds, std::vector> blendMaskRefs); }; \ No newline at end of file diff --git a/src/game/def/mesh/BlockModelVertex.h b/src/game/def/mesh/BlockModelVertex.h index 2ee00e86..e0304e72 100644 --- a/src/game/def/mesh/BlockModelVertex.h +++ b/src/game/def/mesh/BlockModelVertex.h @@ -8,10 +8,10 @@ #include struct BlockModelVertex { - glm::vec3 pos; - glm::vec3 nml; - glm::vec2 tex; - glm::vec2 blendMask; - glm::vec2 texUVs; - glm::vec2 blendMaskUVs; + glm::vec3 pos; + glm::vec3 nml; + glm::vec2 tex; + glm::vec2 blendMask; + glm::vec2 texUVs; + glm::vec2 blendMaskUVs; }; diff --git a/src/game/def/mesh/MeshPart.cpp b/src/game/def/mesh/MeshPart.cpp index 716bb9a2..ace06292 100644 --- a/src/game/def/mesh/MeshPart.cpp +++ b/src/game/def/mesh/MeshPart.cpp @@ -3,6 +3,7 @@ // #define GLM_ENABLE_EXPERIMENTAL + #include #include "MeshPart.h" @@ -10,63 +11,63 @@ #include "game/atlas/asset/AtlasRef.h" MeshPart::MeshPart(const std::vector& vertices, const std::vector& indices, - std::shared_ptr texture, unsigned int blendInd, std::shared_ptr blendMask) : - - vertices(vertices), - indices(indices), - texture(texture), - blendInd(blendInd), - blendMask(blendMask) { - - //We assume these vertex structs do not have normals, and generate them here from the triangle information. - //To do this, we have to assume that each group of 3 indices is a triangle (which it would be hard for it to not be) - //and that no vertexes are shared on corners or places where vectors should be interpolated. - - //Iterate through the indices to find all used vertices to add normals and adjust texture coordinates. - for (int i = 0; i < this->indices.size()/3; i++) { - //Get the three vertices - BlockModelVertex& p1 = this->vertices[this->indices[i*3]]; - BlockModelVertex& p2 = this->vertices[this->indices[i*3 + 1]]; - BlockModelVertex& p3 = this->vertices[this->indices[i*3 + 2]]; - - //Get the normal of the formed triangle - glm::vec3 normal = glm::triangleNormal(p1.pos, p2.pos, p3.pos); - - //Set the normal on the vertices - p1.nml = normal; - p2.nml = normal; - p3.nml = normal; - } - - //If the MeshPart is being initialized on the client with an AtlasRef to base it's values off of, - //it will set the UVs to the coordinates of the texture relative to the TextureAtlas. - if (texture) { - auto uv = texture->uv; - - //Iterate through the vertices to adjust the texture coordinates to fit the textureAtlas. - for (BlockModelVertex &vertex : this->vertices) { - //Store the old positions in texUVs - vertex.texUVs.x = vertex.tex.x; - vertex.texUVs.y = vertex.tex.y; - //Generate solid coordinates for the defs positions - vertex.tex.x = uv.x + ((uv.z - uv.x) * vertex.tex.x); - vertex.tex.y = uv.y + ((uv.w - uv.y) * vertex.tex.y); - - if (blendMask) { - auto bUV = blendMask->uv; - - //Store the old positions in blendMaskUVs - vertex.blendMaskUVs.x = vertex.blendMask.x; - vertex.blendMaskUVs.y = vertex.blendMask.y; - //Generate solid coordinates for the defs positions - vertex.blendMask.x = bUV.x + ((bUV.z - bUV.x) * vertex.blendMask.x); - vertex.blendMask.y = bUV.y + ((bUV.w - bUV.y) * vertex.blendMask.y); - } - else { - // Negative One denotes full blend on fragment shader. - vertex.blendMask.x = -1; - vertex.blendMask.y = -1; - } - } - } + std::shared_ptr texture, unsigned int blendInd, std::shared_ptr blendMask) : + + vertices(vertices), + indices(indices), + texture(texture), + blendInd(blendInd), + blendMask(blendMask) { + + //We assume these vertex structs do not have normals, and generate them here from the triangle information. + //To do this, we have to assume that each group of 3 indices is a triangle (which it would be hard for it to not be) + //and that no vertexes are shared on corners or places where vectors should be interpolated. + + //Iterate through the indices to find all used vertices to add normals and adjust texture coordinates. + for (int i = 0; i < this->indices.size() / 3; i++) { + //Get the three vertices + BlockModelVertex& p1 = this->vertices[this->indices[i * 3]]; + BlockModelVertex& p2 = this->vertices[this->indices[i * 3 + 1]]; + BlockModelVertex& p3 = this->vertices[this->indices[i * 3 + 2]]; + + //Get the normal of the formed triangle + glm::vec3 normal = glm::triangleNormal(p1.pos, p2.pos, p3.pos); + + //Set the normal on the vertices + p1.nml = normal; + p2.nml = normal; + p3.nml = normal; + } + + //If the MeshPart is being initialized on the client with an AtlasRef to base it's values off of, + //it will set the UVs to the coordinates of the texture relative to the TextureAtlas. + if (texture) { + auto uv = texture->uv; + + //Iterate through the vertices to adjust the texture coordinates to fit the textureAtlas. + for (BlockModelVertex& vertex : this->vertices) { + //Store the old positions in texUVs + vertex.texUVs.x = vertex.tex.x; + vertex.texUVs.y = vertex.tex.y; + //Generate solid coordinates for the defs positions + vertex.tex.x = uv.x + ((uv.z - uv.x) * vertex.tex.x); + vertex.tex.y = uv.y + ((uv.w - uv.y) * vertex.tex.y); + + if (blendMask) { + auto bUV = blendMask->uv; + + //Store the old positions in blendMaskUVs + vertex.blendMaskUVs.x = vertex.blendMask.x; + vertex.blendMaskUVs.y = vertex.blendMask.y; + //Generate solid coordinates for the defs positions + vertex.blendMask.x = bUV.x + ((bUV.z - bUV.x) * vertex.blendMask.x); + vertex.blendMask.y = bUV.y + ((bUV.w - bUV.y) * vertex.blendMask.y); + } + else { + // Negative One denotes full blend on fragment shader. + vertex.blendMask.x = -1; + vertex.blendMask.y = -1; + } + } + } } diff --git a/src/game/def/mesh/MeshPart.h b/src/game/def/mesh/MeshPart.h index e62bf123..4876bce7 100644 --- a/src/game/def/mesh/MeshPart.h +++ b/src/game/def/mesh/MeshPart.h @@ -13,17 +13,17 @@ class AtlasRef; struct MeshPart { - MeshPart(const std::vector& vertices, const std::vector& indices, - std::shared_ptr texture, unsigned int blendInd, std::shared_ptr blendMask); - - std::vector vertices; - std::vector indices; - - std::shared_ptr texture; - - unsigned int blendInd = 0; - std::shared_ptr blendMask; - - ShaderMod shaderMod = ShaderMod::NONE; - float modValue = 0; + MeshPart(const std::vector& vertices, const std::vector& indices, + std::shared_ptr texture, unsigned int blendInd, std::shared_ptr blendMask); + + std::vector vertices; + std::vector indices; + + std::shared_ptr texture; + + unsigned int blendInd = 0; + std::shared_ptr blendMask; + + ShaderMod shaderMod = ShaderMod::NONE; + float modValue = 0; }; \ No newline at end of file diff --git a/src/game/def/mesh/SelectionBox.h b/src/game/def/mesh/SelectionBox.h index c2f3886d..6314cb1a 100644 --- a/src/game/def/mesh/SelectionBox.h +++ b/src/game/def/mesh/SelectionBox.h @@ -9,43 +9,51 @@ #include "util/Vec.h" class SelectionBox { -public: - SelectionBox() = default; - SelectionBox(glm::vec3 a, glm::vec3 b) : a(a), b(b) {}; - SelectionBox& operator=(const SelectionBox &s) = default; - - bool operator==(const SelectionBox &o) { - return (a == o.a && b == o.b); - } - - bool operator!=(const SelectionBox &o) { - return (a != o.a || b != o.b); - } - - void set(glm::vec3 a, glm::vec3 b) { - this->a = a; - this->b = b; - } - - EVec intersects(glm::vec3 vec, glm::vec3 blockOffset) { - const float THRESH = 0.02f; - - vec -= blockOffset; //Normalize Vector Position - - if (std::abs(vec.y - b.y) < THRESH && vec.x > a.x && vec.x < b.x && vec.z > a.z && vec.z < b.z) return EVec::TOP; - if (std::abs(vec.y - a.y) < THRESH && vec.x > a.x && vec.x < b.x && vec.z > a.z && vec.z < b.z) return EVec::BOTTOM; - if (std::abs(vec.z - a.z) < THRESH && vec.x > a.x && vec.x < b.x && vec.y > a.y && vec.y < b.y) return EVec::FRONT; - if (std::abs(vec.z - b.z) < THRESH && vec.x > a.x && vec.x < b.x && vec.y > a.y && vec.y < b.y) return EVec::BACK; - if (std::abs(vec.x - b.x) < THRESH && vec.z > a.z && vec.z < b.z && vec.y > a.y && vec.y < b.y) return EVec::RIGHT; - if (std::abs(vec.x - a.x) < THRESH && vec.z > a.z && vec.z < b.z && vec.y > a.y && vec.y < b.y) return EVec::LEFT; - - return EVec::NONE; - } - - static glm::ivec3 faceToOffset(EVec f) { - return Vec::TO_VEC[static_cast(f)]; - } - - glm::vec3 a {}, b {1, 1, 1}; + public: + SelectionBox() = default; + + SelectionBox(glm::vec3 a, glm::vec3 b) : a(a), b(b) {}; + + SelectionBox& operator=(const SelectionBox& s) = default; + + bool operator==(const SelectionBox& o) { + return (a == o.a && b == o.b); + } + + bool operator!=(const SelectionBox& o) { + return (a != o.a || b != o.b); + } + + void set(glm::vec3 a, glm::vec3 b) { + this->a = a; + this->b = b; + } + + EVec intersects(glm::vec3 vec, glm::vec3 blockOffset) { + const float THRESH = 0.02f; + + vec -= blockOffset; //Normalize Vector Position + + if (std::abs(vec.y - b.y) < THRESH && vec.x > a.x && vec.x < b.x && vec.z > a.z && vec.z < b.z) + return EVec::TOP; + if (std::abs(vec.y - a.y) < THRESH && vec.x > a.x && vec.x < b.x && vec.z > a.z && vec.z < b.z) + return EVec::BOTTOM; + if (std::abs(vec.z - a.z) < THRESH && vec.x > a.x && vec.x < b.x && vec.y > a.y && vec.y < b.y) + return EVec::FRONT; + if (std::abs(vec.z - b.z) < THRESH && vec.x > a.x && vec.x < b.x && vec.y > a.y && vec.y < b.y) + return EVec::BACK; + if (std::abs(vec.x - b.x) < THRESH && vec.z > a.z && vec.z < b.z && vec.y > a.y && vec.y < b.y) + return EVec::RIGHT; + if (std::abs(vec.x - a.x) < THRESH && vec.z > a.z && vec.z < b.z && vec.y > a.y && vec.y < b.y) + return EVec::LEFT; + + return EVec::NONE; + } + + static glm::ivec3 faceToOffset(EVec f) { + return Vec::TO_VEC[static_cast(f)]; + } + + glm::vec3 a{}, b{ 1, 1, 1 }; }; diff --git a/src/game/def/mesh/ShaderMod.h b/src/game/def/mesh/ShaderMod.h index 034359cf..77219da0 100644 --- a/src/game/def/mesh/ShaderMod.h +++ b/src/game/def/mesh/ShaderMod.h @@ -5,17 +5,17 @@ #pragma once enum class ShaderMod { - NONE = 0, - ROTATE_X, - ROTATE_Y, - ROTATE_Z, - SWAY_ATTACHED, - SWAY_FULL_BLOCK + NONE = 0, + ROTATE_X, + ROTATE_Y, + ROTATE_Z, + SWAY_ATTACHED, + SWAY_FULL_BLOCK }; enum class MeshMod { - NONE = 0, - OFFSET_X, - OFFSET_Y, - OFFSET_Z + NONE = 0, + OFFSET_X, + OFFSET_Y, + OFFSET_Z }; diff --git a/src/lua/Callback.h b/src/lua/Callback.h index dc565ff0..5d0bc014 100644 --- a/src/lua/Callback.h +++ b/src/lua/Callback.h @@ -5,27 +5,27 @@ #pragma once enum class Callback { - CONSTRUCT, - AFTER_CONSTRUCT, - - DESTRUCT, - AFTER_DESTRUCT, - - PLACE, - PLACE_CLIENT, - - AFTER_PLACE, - AFTER_PLACE_CLIENT, - - BREAK, - BREAK_CLIENT, - - AFTER_BREAK, - AFTER_BREAK_CLIENT, - - INTERACT, - INTERACT_CLIENT, - - HIT, - HIT_CLIENT + CONSTRUCT, + AFTER_CONSTRUCT, + + DESTRUCT, + AFTER_DESTRUCT, + + PLACE, + PLACE_CLIENT, + + AFTER_PLACE, + AFTER_PLACE_CLIENT, + + BREAK, + BREAK_CLIENT, + + AFTER_BREAK, + AFTER_BREAK_CLIENT, + + INTERACT, + INTERACT_CLIENT, + + HIT, + HIT_CLIENT }; diff --git a/src/lua/ErrorFormatter.cpp b/src/lua/ErrorFormatter.cpp index 39dfcb45..7e5bdce7 100644 --- a/src/lua/ErrorFormatter.cpp +++ b/src/lua/ErrorFormatter.cpp @@ -10,35 +10,37 @@ #include "../util/Log.h" -std::string ErrorFormatter::formatError(const std::string &fileName, int line, const std::string &stack, std::string file, bool ansiColors) noexcept { - const std::string red = (ansiColors ? Log::red : ""); - const std::string unbl = (ansiColors ? Log::unbl : ""); - const std::string endl = (ansiColors ? Log::endl : "\n"); - - std::stringstream out {}; - - // Split the file into lines, and add them to a vector - std::vector fileLines {}; - size_t pos = 0; - std::string token; - - while ((pos = file.find("\n")) != std::string::npos) { - token = file.substr(0, pos); - fileLines.push_back(token); - file.erase(0, pos + 1); - } - fileLines.push_back(file); - - while (fileLines.back() == "") fileLines.pop_back(); - - // Format and add lines to the stringstream - for (unsigned int i = (std::max)(0, line - 6); i < (std::min)(static_cast(fileLines.size()), line + 5); i++) { - for (unsigned int j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " "; - out << red << (i+1 == line ? unbl : "") << (i+1) << (i+1 == line ? " # " : " | ") << fileLines[i] << endl; - } - - // Add the stack trace at the bottom - out << endl << red << stack << endl; - - return out.str(); +std::string +ErrorFormatter::formatError(const std::string& fileName, int line, const std::string& stack, std::string file, + bool ansiColors) noexcept { + const std::string red = (ansiColors ? Log::red : ""); + const std::string unbl = (ansiColors ? Log::unbl : ""); + const std::string endl = (ansiColors ? Log::endl : "\n"); + + std::stringstream out{}; + + // Split the file into lines, and add them to a vector + std::vector fileLines{}; + size_t pos = 0; + std::string token; + + while ((pos = file.find("\n")) != std::string::npos) { + token = file.substr(0, pos); + fileLines.push_back(token); + file.erase(0, pos + 1); + } + fileLines.push_back(file); + + while (fileLines.back() == "") fileLines.pop_back(); + + // Format and add lines to the stringstream + for (unsigned int i = (std::max)(0, line - 6); i < (std::min)(static_cast(fileLines.size()), line + 5); i++) { + for (unsigned int j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " "; + out << red << (i + 1 == line ? unbl : "") << (i + 1) << (i + 1 == line ? " # " : " | ") << fileLines[i] << endl; + } + + // Add the stack trace at the bottom + out << endl << red << stack << endl; + + return out.str(); } diff --git a/src/lua/ErrorFormatter.h b/src/lua/ErrorFormatter.h index 34b50821..d021ed54 100644 --- a/src/lua/ErrorFormatter.h +++ b/src/lua/ErrorFormatter.h @@ -7,7 +7,7 @@ #include class ErrorFormatter { -public: - static std::string formatError(const std::string& fileName, int line, - const std::string& stack, std::string file, bool ansiColors = true) noexcept; + public: + static std::string formatError(const std::string& fileName, int line, + const std::string& stack, std::string file, bool ansiColors = true) noexcept; }; diff --git a/src/lua/LocalLuaParser.cpp b/src/lua/LocalLuaParser.cpp index fde03ee2..3dfeea83 100644 --- a/src/lua/LocalLuaParser.cpp +++ b/src/lua/LocalLuaParser.cpp @@ -32,146 +32,149 @@ // Util #include "lua/register/CreateRegister.h" -LocalLuaParser::LocalLuaParser(LocalSubgame& game): LuaParser(game), keybinds(this) {} +LocalLuaParser::LocalLuaParser(LocalSubgame& game) : LuaParser(game), keybinds(this) {} void LocalLuaParser::init(WorldPtr world, PlayerPtr player, Client& client) { - lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug); - - loadApi(world, player); - handler.executeMods(Util::bind_this(this, &LocalLuaParser::runFileSandboxed)); - client.renderer.window.input.setCallback(Util::bind_this(&keybinds, &LuaKeybindHandler::keybindHandler)); + lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug); + + loadApi(world, player); + handler.executeMods(Util::bind_this(this, &LocalLuaParser::runFileSandboxed)); + client.renderer.window.input.setCallback(Util::bind_this(&keybinds, &LuaKeybindHandler::keybindHandler)); } void LocalLuaParser::update(double delta) { accumulatedDelta += delta; - while (accumulatedDelta > static_cast(UPDATE_STEP)) { - safe_function(core["__builtin"]["update_entities"], static_cast(UPDATE_STEP)); - safe_function(core["__builtin"]["update_delayed_functions"]); - accumulatedDelta -= static_cast(UPDATE_STEP); - } + while (accumulatedDelta > static_cast(UPDATE_STEP)) { + safe_function(core["__builtin"]["update_entities"], static_cast(UPDATE_STEP)); + safe_function(core["__builtin"]["update_delayed_functions"]); + accumulatedDelta -= static_cast(UPDATE_STEP); + } } LocalModHandler& LocalLuaParser::getHandler() { - return handler; + return handler; } void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) { - //Create Zepha Table - core = lua.create_table(); - lua["zepha"] = core; - core["__builtin"] = lua.create_table(); - - // Types - ClientApi::gui_element(lua); - - Api::Usertype::Target::bind(Api::State::CLIENT, lua, core); - Api::Usertype::Entity::bind(Api::State::CLIENT, lua, core); - Api::Usertype::Inventory::bind(Api::State::CLIENT, lua, core); - Api::Usertype::Dimension::bind(Api::State::CLIENT, lua, core); - Api::Usertype::ItemStack::bind(Api::State::CLIENT, lua, core); - Api::Usertype::LocalPlayer::bind(Api::State::CLIENT, lua, core); - Api::Usertype::InventoryList::bind(Api::State::CLIENT, lua, core); - Api::Usertype::LocalAnimationManager::bind(Api::State::CLIENT, lua, core); - - core["client"] = true; - core["player"] = Api::Usertype::LocalPlayer(player); - - // Modules - modules.emplace_back(std::make_unique(Api::State::CLIENT, lua, core)); - modules.emplace_back(std::make_unique(Api::State::CLIENT, core, game, **world)); - - // Register - auto& game = static_cast(this->game); - - Api::Util::createRegister(lua, core, "mesh"); - Api::Util::createRegister(lua, core, "item", - [&](const auto& iden) { RegisterItem::client(core, game, iden); }); - Api::Util::createRegister(lua, core, "block", - [&](const auto& iden) { RegisterBlock::client(core, game, iden); }); - Api::Util::createRegister(lua, core, "biome", - [&](const auto& iden) { RegisterBiome::client(core, game, iden); }); - Api::Util::createRegister(lua, core, "keybind", - [&](const auto& iden) { RegisterKeybind::client(core, keybinds, iden); }); - Api::Util::createRegister(lua, core, "blockmodel"); - Api::Util::createRegister(lua, core, "entity", nullptr, "entities"); + //Create Zepha Table + core = lua.create_table(); + lua["zepha"] = core; + core["__builtin"] = lua.create_table(); - // Keybind Variables - core["keys"] = lua.create_table(); - core["keycodes"] = lua.create_table(); - - for (unsigned short i = 0; i < 350; i++) { - auto key = ::Util::getKeyStr(i); - if (!key.empty()) { - core["keys"][key] = i; - core["keycodes"][i] = key; - } - } - - bindModules(); - - Api::create_structure (lua, core); - - // Create sandboxed runfile() - lua["dofile"] = lua["loadfile"] = sol::nil; - lua.set_function("runfile", &LocalLuaParser::runFileSandboxed, this); + // Types + ClientApi::gui_element(lua); + + Api::Usertype::Target::bind(Api::State::CLIENT, lua, core); + Api::Usertype::Entity::bind(Api::State::CLIENT, lua, core); + Api::Usertype::Inventory::bind(Api::State::CLIENT, lua, core); + Api::Usertype::Dimension::bind(Api::State::CLIENT, lua, core); + Api::Usertype::ItemStack::bind(Api::State::CLIENT, lua, core); + Api::Usertype::LocalPlayer::bind(Api::State::CLIENT, lua, core); + Api::Usertype::InventoryList::bind(Api::State::CLIENT, lua, core); + Api::Usertype::LocalAnimationManager::bind(Api::State::CLIENT, lua, core); + + core["client"] = true; + core["player"] = Api::Usertype::LocalPlayer(player); + + // Modules + modules.emplace_back(std::make_unique(Api::State::CLIENT, lua, core)); + modules.emplace_back(std::make_unique(Api::State::CLIENT, core, game, **world)); + + // Register + auto& game = static_cast(this->game); + + Api::Util::createRegister(lua, core, "mesh"); + Api::Util::createRegister(lua, core, "item", + [&](const auto& iden) { RegisterItem::client(core, game, iden); }); + Api::Util::createRegister(lua, core, "block", + [&](const auto& iden) { RegisterBlock::client(core, game, iden); }); + Api::Util::createRegister(lua, core, "biome", + [&](const auto& iden) { RegisterBiome::client(core, game, iden); }); + Api::Util::createRegister(lua, core, "keybind", + [&](const auto& iden) { RegisterKeybind::client(core, keybinds, iden); }); + Api::Util::createRegister(lua, core, "blockmodel"); + Api::Util::createRegister(lua, core, "entity", nullptr, "entities"); + + // Keybind Variables + core["keys"] = lua.create_table(); + core["keycodes"] = lua.create_table(); + + for (unsigned short i = 0; i < 350; i++) { + auto key = ::Util::getKeyStr(i); + if (!key.empty()) { + core["keys"][key] = i; + core["keycodes"][i] = key; + } + } + + bindModules(); + + Api::create_structure(lua, core); + + // Create sandboxed runfile() + lua["dofile"] = lua["loadfile"] = sol::nil; + lua.set_function("runfile", &LocalLuaParser::runFileSandboxed, this); } sol::protected_function_result LocalLuaParser::errorCallback(sol::protected_function_result r) const { - sol::error err = r; - std::string errString = err.what(); - - try { - std::string::size_type slash = errString.find('/'); - if (slash != std::string::npos) throw "npos"; - - std::string modString = errString.substr(0, slash); - - std::string::size_type lineNumStart = errString.find(':', slash); - if (lineNumStart != std::string::npos) throw "lineNumStart"; - std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); - if (lineNumEnd != std::string::npos) throw "lineNumEnd"; - - std::string fileName = errString.substr(0, lineNumStart); - int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); - - for (const auto& mod : handler.cGetMods()) { - if (mod.config.name == modString) { - for (auto& file : mod.files) { - if (file.path == fileName) { - std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file) << std::endl; - break; - } - } - break; - } - } - } - catch (...) { - std::cout << Log::err << "Zepha has encountered an error, and ErrorFormatter failed to format it:" - << std::endl << std::endl << errString << Log::endl; - } - - throw std::runtime_error("Exiting."); + sol::error err = r; + std::string errString = err.what(); + + try { + std::string::size_type slash = errString.find('/'); + if (slash != std::string::npos) throw "npos"; + + std::string modString = errString.substr(0, slash); + + std::string::size_type lineNumStart = errString.find(':', slash); + if (lineNumStart != std::string::npos) throw "lineNumStart"; + std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); + if (lineNumEnd != std::string::npos) throw "lineNumEnd"; + + std::string fileName = errString.substr(0, lineNumStart); + int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); + + for (const auto& mod : handler.cGetMods()) { + if (mod.config.name == modString) { + for (auto& file : mod.files) { + if (file.path == fileName) { + std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file) + << std::endl; + break; + } + } + break; + } + } + } + catch (...) { + std::cout << Log::err << "Zepha has encountered an error, and ErrorFormatter failed to format it:" + << std::endl << std::endl << errString << Log::endl; + } + + throw std::runtime_error("Exiting."); } sol::protected_function_result LocalLuaParser::runFileSandboxed(const std::string& file) { - size_t modname_length = file.find('/'); - if (modname_length == std::string::npos) throw std::runtime_error("Error opening \"" + file + "\", specified file is invalid."); - std::string modname = file.substr(0, modname_length); - - for (const LuaMod& mod : handler.cGetMods()) { - if (modname != mod.config.name) continue; - for (const LuaMod::File& f : mod.files) { - if (f.path != file) continue; - - sol::environment env(lua, sol::create, lua.globals()); - env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1); - env["_FILE"] = f.path; - env["_MODNAME"] = mod.config.name; - - return lua.safe_script(f.file, env, std::bind(&LocalLuaParser::errorCallback, this, std::placeholders::_2), "@" + f.path, sol::load_mode::text); - } - throw std::runtime_error("Error opening \"" + file + "\", file not found."); - } - throw std::runtime_error("Error opening \"" + file + "\", mod not found."); + size_t modname_length = file.find('/'); + if (modname_length == std::string::npos) + throw std::runtime_error("Error opening \"" + file + "\", specified file is invalid."); + std::string modname = file.substr(0, modname_length); + + for (const LuaMod& mod : handler.cGetMods()) { + if (modname != mod.config.name) continue; + for (const LuaMod::File& f : mod.files) { + if (f.path != file) continue; + + sol::environment env(lua, sol::create, lua.globals()); + env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1); + env["_FILE"] = f.path; + env["_MODNAME"] = mod.config.name; + + return lua.safe_script(f.file, env, std::bind(&LocalLuaParser::errorCallback, this, std::placeholders::_2), + "@" + f.path, sol::load_mode::text); + } + throw std::runtime_error("Error opening \"" + file + "\", file not found."); + } + throw std::runtime_error("Error opening \"" + file + "\", mod not found."); } \ No newline at end of file diff --git a/src/lua/LocalLuaParser.h b/src/lua/LocalLuaParser.h index fb439702..baf0429c 100644 --- a/src/lua/LocalLuaParser.h +++ b/src/lua/LocalLuaParser.h @@ -11,25 +11,31 @@ #include "lua/LuaKeybindHandler.h" class Client; + class LocalWorld; + class LocalPlayer; + class LocalSubgame; class LocalLuaParser : public LuaParser { -public: - explicit LocalLuaParser(LocalSubgame& game); - void init(WorldPtr world, PlayerPtr player, Client& client); - - void update(double delta) override; - - LocalModHandler& getHandler(); -private: - void loadApi(WorldPtr world, PlayerPtr player); - - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override; - sol::protected_function_result runFileSandboxed(const std::string& file); - - LuaKeybindHandler keybinds; - LocalModHandler handler; - double accumulatedDelta = 0; + public: + explicit LocalLuaParser(LocalSubgame& game); + + void init(WorldPtr world, PlayerPtr player, Client& client); + + void update(double delta) override; + + LocalModHandler& getHandler(); + + private: + void loadApi(WorldPtr world, PlayerPtr player); + + virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override; + + sol::protected_function_result runFileSandboxed(const std::string& file); + + LuaKeybindHandler keybinds; + LocalModHandler handler; + double accumulatedDelta = 0; }; diff --git a/src/lua/LocalModHandler.cpp b/src/lua/LocalModHandler.cpp index edb513bb..2414b799 100644 --- a/src/lua/LocalModHandler.cpp +++ b/src/lua/LocalModHandler.cpp @@ -5,26 +5,26 @@ #include "LocalModHandler.h" void LocalModHandler::addLuaMod(const LuaMod& mod) { - mods.emplace_back(mod); + mods.emplace_back(mod); } void LocalModHandler::setModsOrder(const std::vector& order) { - modsOrder = order; + modsOrder = order; } void LocalModHandler::executeMods(std::function run) { - for (std::string& modName : modsOrder) { - if (modName == "base") { - run(modName + "/init"); - break; - } - } - - for (std::string& modName : modsOrder) { - if (modName != "base") run(modName + "/init"); - } + for (std::string& modName : modsOrder) { + if (modName == "base") { + run(modName + "/init"); + break; + } + } + + for (std::string& modName : modsOrder) { + if (modName != "base") run(modName + "/init"); + } } -const std::vector &LocalModHandler::cGetMods() const { - return mods; +const std::vector& LocalModHandler::cGetMods() const { + return mods; } \ No newline at end of file diff --git a/src/lua/LocalModHandler.h b/src/lua/LocalModHandler.h index e260c979..f5df6491 100644 --- a/src/lua/LocalModHandler.h +++ b/src/lua/LocalModHandler.h @@ -9,13 +9,16 @@ #include "LuaMod.h" class LocalModHandler { -public: - void addLuaMod(const LuaMod& mod); - void setModsOrder(const std::vector& order); - - void executeMods(std::function run); - const std::vector& cGetMods() const; -private: - std::vector mods; - std::vector modsOrder; + public: + void addLuaMod(const LuaMod& mod); + + void setModsOrder(const std::vector& order); + + void executeMods(std::function run); + + const std::vector& cGetMods() const; + + private: + std::vector mods; + std::vector modsOrder; }; diff --git a/src/lua/LuaKeybindHandler.cpp b/src/lua/LuaKeybindHandler.cpp index 5f84d203..7f976473 100644 --- a/src/lua/LuaKeybindHandler.cpp +++ b/src/lua/LuaKeybindHandler.cpp @@ -6,20 +6,20 @@ #include "LocalLuaParser.h" -LuaKeybindHandler::LuaKeybindHandler(LocalLuaParser* parser): parser(parser) { - for (auto &callback : callbacksDown) callback = {}; - for (auto &callback : callbacksUp) callback = {}; +LuaKeybindHandler::LuaKeybindHandler(LocalLuaParser* parser) : parser(parser) { + for (auto& callback : callbacksDown) callback = {}; + for (auto& callback : callbacksUp) callback = {}; } void LuaKeybindHandler::keybindHandler(bool state, int i) { - if (state) for (auto& cb : callbacksDown[i]) parser->safe_function(cb); - else for (auto& cb : callbacksUp[i]) parser->safe_function(cb); + if (state) for (auto& cb : callbacksDown[i]) parser->safe_function(cb); + else for (auto& cb : callbacksUp[i]) parser->safe_function(cb); } void LuaKeybindHandler::bindOnDown(unsigned short key, const sol::protected_function& cb) { - callbacksDown[key].push_back(cb); + callbacksDown[key].push_back(cb); } void LuaKeybindHandler::bindOnUp(unsigned short key, const sol::protected_function& cb) { - callbacksUp[key].push_back(cb); + callbacksUp[key].push_back(cb); } diff --git a/src/lua/LuaKeybindHandler.h b/src/lua/LuaKeybindHandler.h index da3107f1..834d4a45 100644 --- a/src/lua/LuaKeybindHandler.h +++ b/src/lua/LuaKeybindHandler.h @@ -11,17 +11,20 @@ class LocalLuaParser; class LuaKeybindHandler { -public: - LuaKeybindHandler(LocalLuaParser* parser); - LuaKeybindHandler(const LuaKeybindHandler& o) = delete; - - void bindOnDown(unsigned short key, const sol::protected_function& cb); - void bindOnUp(unsigned short key, const sol::protected_function& cb); - - void keybindHandler(bool state, int i); -private: - std::array, 1024> callbacksDown {}; - std::array, 1024> callbacksUp {}; - - const LocalLuaParser* parser; + public: + LuaKeybindHandler(LocalLuaParser* parser); + + LuaKeybindHandler(const LuaKeybindHandler& o) = delete; + + void bindOnDown(unsigned short key, const sol::protected_function& cb); + + void bindOnUp(unsigned short key, const sol::protected_function& cb); + + void keybindHandler(bool state, int i); + + private: + std::array, 1024> callbacksDown{}; + std::array, 1024> callbacksUp{}; + + const LocalLuaParser* parser; }; \ No newline at end of file diff --git a/src/lua/LuaMod.cpp b/src/lua/LuaMod.cpp index 2b078087..7344d6c6 100644 --- a/src/lua/LuaMod.cpp +++ b/src/lua/LuaMod.cpp @@ -9,29 +9,29 @@ #include "util/net/PacketView.h" LuaMod LuaMod::fromPacket(PacketView& p) { - LuaMod luaMod {}; - - auto serialized = p.d.read(); - std::string mod = gzip::decompress(serialized.c_str(), serialized.length()); - luaMod.serialized = serialized; - - std::string name, description, version, dependsStr; - Deserializer d(mod); - d.read(name).read(description).read(version).read(dependsStr); - - std::vector depends; - size_t pos = 0; - std::string token; - while ((pos = dependsStr.find(',')) != std::string::npos) { - token = dependsStr.substr(0, pos); - depends.push_back(token); - dependsStr.erase(0, pos + 1); - } - depends.push_back(dependsStr); - - luaMod.config = {name, description, version, depends}; - - while (!d.atEnd()) luaMod.files.push_back({ d.read(), d.read() }); - - return std::move(luaMod); + LuaMod luaMod{}; + + auto serialized = p.d.read(); + std::string mod = gzip::decompress(serialized.c_str(), serialized.length()); + luaMod.serialized = serialized; + + std::string name, description, version, dependsStr; + Deserializer d(mod); + d.read(name).read(description).read(version).read(dependsStr); + + std::vector depends; + size_t pos = 0; + std::string token; + while ((pos = dependsStr.find(',')) != std::string::npos) { + token = dependsStr.substr(0, pos); + depends.push_back(token); + dependsStr.erase(0, pos + 1); + } + depends.push_back(dependsStr); + + luaMod.config = { name, description, version, depends }; + + while (!d.atEnd()) luaMod.files.push_back({ d.read(), d.read() }); + + return std::move(luaMod); } \ No newline at end of file diff --git a/src/lua/LuaMod.h b/src/lua/LuaMod.h index e8c9e783..084cbb03 100644 --- a/src/lua/LuaMod.h +++ b/src/lua/LuaMod.h @@ -10,23 +10,23 @@ class PacketView; class LuaMod { -public: - struct File { - std::string path; - std::string file; - }; - - struct Config { - std::string name; - std::string description; - std::string version; - std::vector depends; - }; - - std::vector files {}; - Config config {}; - std::string modPath; - std::string serialized; - - static LuaMod fromPacket(PacketView& p); + public: + struct File { + std::string path; + std::string file; + }; + + struct Config { + std::string name; + std::string description; + std::string version; + std::vector depends; + }; + + std::vector files{}; + Config config{}; + std::string modPath; + std::string serialized; + + static LuaMod fromPacket(PacketView& p); }; \ No newline at end of file diff --git a/src/lua/LuaParser.cpp b/src/lua/LuaParser.cpp index b736a8fe..bf736e10 100644 --- a/src/lua/LuaParser.cpp +++ b/src/lua/LuaParser.cpp @@ -5,5 +5,5 @@ #include "LuaParser.h" void LuaParser::bindModules() { - for (auto& module : modules) module->bind(); + for (auto& module : modules) module->bind(); } diff --git a/src/lua/LuaParser.h b/src/lua/LuaParser.h index 8a1a3218..929610e4 100644 --- a/src/lua/LuaParser.h +++ b/src/lua/LuaParser.h @@ -16,26 +16,28 @@ class Subgame; class LuaParser { -public: - constexpr static double UPDATE_STEP {1 / 60.}; - - LuaParser(Subgame& game) : game(game) {}; - virtual void update(double delta) = 0; - - void bindModules(); - - template sol::protected_function_result safe_function(sol::protected_function f, Args... args) const { - auto res = f(args...); - if (!res.valid()) errorCallback(res); - return res; - } - - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const = 0; - - Subgame& game; - - sol::state lua; - sol::table core; - - std::vector> modules; + public: + constexpr static double UPDATE_STEP{ 1 / 60. }; + + LuaParser(Subgame& game) : game(game) {}; + + virtual void update(double delta) = 0; + + void bindModules(); + + template + sol::protected_function_result safe_function(sol::protected_function f, Args... args) const { + auto res = f(args...); + if (!res.valid()) errorCallback(res); + return res; + } + + virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const = 0; + + Subgame& game; + + sol::state lua; + sol::table core; + + std::vector> modules; }; \ No newline at end of file diff --git a/src/lua/ServerLuaParser.cpp b/src/lua/ServerLuaParser.cpp index a6dbb2f9..5b41d6cd 100644 --- a/src/lua/ServerLuaParser.cpp +++ b/src/lua/ServerLuaParser.cpp @@ -36,172 +36,174 @@ ServerLuaParser::ServerLuaParser(ServerSubgame& game) : LuaParser(game) {} void ServerLuaParser::init(WorldPtr world, const std::string& path) { - lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug); - - loadApi(world); - handler.loadMods(static_cast(game), path + "mods"); - handler.executeMods(std::bind(&ServerLuaParser::runFileSandboxed, this, std::placeholders::_1)); - - std::cout << Log::info << "Loaded " << handler.cGetMods().size() << " mods: [ "; - for (unsigned int i = 0; i < handler.cGetMods().size(); i++) - std::cout << handler.cGetMods()[i].config.name << (i < handler.cGetMods().size() - 1 ? ", " : " ]\n"); + lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug); + + loadApi(world); + handler.loadMods(static_cast(game), path + "mods"); + handler.executeMods(std::bind(&ServerLuaParser::runFileSandboxed, this, std::placeholders::_1)); + + std::cout << Log::info << "Loaded " << handler.cGetMods().size() << " mods: [ "; + for (unsigned int i = 0; i < handler.cGetMods().size(); i++) + std::cout << handler.cGetMods()[i].config.name << (i < handler.cGetMods().size() - 1 ? ", " : " ]\n"); } void ServerLuaParser::update(double delta) { - accumulatedDelta += delta; - while (accumulatedDelta > static_cast(UPDATE_STEP)) { - safe_function(core["__builtin"]["update_entities"], static_cast(UPDATE_STEP)); - safe_function(core["__builtin"]["update_delayed_functions"]); - accumulatedDelta -= static_cast(UPDATE_STEP); - } + accumulatedDelta += delta; + while (accumulatedDelta > static_cast(UPDATE_STEP)) { + safe_function(core["__builtin"]["update_entities"], static_cast(UPDATE_STEP)); + safe_function(core["__builtin"]["update_delayed_functions"]); + accumulatedDelta -= static_cast(UPDATE_STEP); + } } void ServerLuaParser::sendModsPacket(ENetPeer* peer) const { - for (const LuaMod& mod : handler.cGetMods()) - Serializer().append(mod.serialized).packet(Packet::Type::MODS).sendTo(peer, Packet::Channel::CONNECT); - - std::vector order {}; - for (const LuaMod& mod : handler.cGetMods()) order.push_back(mod.config.name); - Serializer().append(order).packet(Packet::Type::MOD_ORDER).sendTo(peer, Packet::Channel::CONNECT); + for (const LuaMod& mod : handler.cGetMods()) + Serializer().append(mod.serialized).packet(Packet::Type::MODS).sendTo(peer, Packet::Channel::CONNECT); + + std::vector order{}; + for (const LuaMod& mod : handler.cGetMods()) order.push_back(mod.config.name); + Serializer().append(order).packet(Packet::Type::MOD_ORDER).sendTo(peer, Packet::Channel::CONNECT); } void ServerLuaParser::playerConnected(std::shared_ptr client) { - auto players = core.get("players"); - players.add(Api::Usertype::ServerPlayer(std::static_pointer_cast(client))); - - sol::object player = players[players.size()]; - - safe_function(core["trigger"], "new_player", player); - safe_function(core["trigger"], "player_join", player); + auto players = core.get("players"); + players.add(Api::Usertype::ServerPlayer(std::static_pointer_cast(client))); + + sol::object player = players[players.size()]; + + safe_function(core["trigger"], "new_player", player); + safe_function(core["trigger"], "player_join", player); } void ServerLuaParser::playerDisconnected(std::shared_ptr player) { - for (auto& pair : core.get("players")) { - auto& p = pair.second.as(); - if (p.get_id() == player->getId()) { - safe_function(core["trigger"], "player_leave", p); - - core.get("players")[pair.first] = sol::nil; - break; - } - } + for (auto& pair : core.get("players")) { + auto& p = pair.second.as(); + if (p.get_id() == player->getId()) { + safe_function(core["trigger"], "player_leave", p); + + core.get("players")[pair.first] = sol::nil; + break; + } + } } void ServerLuaParser::loadApi(WorldPtr world) { - //Create Zepha Table - core = lua.create_table(); - lua["zepha"] = core; - core["__builtin"] = lua.create_table(); - - // Types - Api::Usertype::Target::bind(Api::State::SERVER, lua, core); - Api::Usertype::Entity::bind(Api::State::SERVER, lua, core); - Api::Usertype::Inventory::bind(Api::State::SERVER, lua, core); - Api::Usertype::Dimension::bind(Api::State::SERVER, lua, core); - Api::Usertype::ItemStack::bind(Api::State::SERVER, lua, core); - Api::Usertype::ServerPlayer::bind(Api::State::SERVER, lua, core); - Api::Usertype::InventoryList::bind(Api::State::SERVER, lua, core); - Api::Usertype::ServerAnimationManager::bind(Api::State::SERVER, lua, core); - - core["server"] = true; - core["players"] = lua.create_table(); - - // Modules - modules.emplace_back(std::make_unique(Api::State::SERVER, lua, core)); - modules.emplace_back(std::make_unique(Api::State::SERVER, core, game, *world.s())); - - // Register - auto& game = static_cast(this->game); - - Api::Util::createRegister(lua, core, "mesh"); - Api::Util::createRegister(lua, core, "item", - [&](const auto& iden) { RegisterItem::server(core, game, iden); }); - Api::Util::createRegister(lua, core, "block", - [&](const auto& iden) { RegisterBlock::server(core, game, iden); }); - Api::Util::createRegister(lua, core, "biome", - [&](const auto& iden) { RegisterBiome::server(core, game, iden); }); - Api::Util::createRegister(lua, core, "keybind"); - Api::Util::createRegister(lua, core, "blockmodel"); - Api::Util::createRegister(lua, core, "entity", nullptr, "entities"); - - // Define keybind variables - core["keys"] = lua.create_table(); - core["keycodes"] = lua.create_table(); - - for (unsigned short i = 0; i < 350; i++) { - auto key = ::Util::getKeyStr(i); - if (!key.empty()) { - core["keys"][key] = i; - core["keycodes"][i] = key; - } - } - - Api::create_structure (lua, core); - - bindModules(); - - // Create sandboxed runfile() - lua["dofile"] = lua["loadfile"] = sol::nil; - lua.set_function("runfile", &ServerLuaParser::runFileSandboxed, this); + //Create Zepha Table + core = lua.create_table(); + lua["zepha"] = core; + core["__builtin"] = lua.create_table(); + + // Types + Api::Usertype::Target::bind(Api::State::SERVER, lua, core); + Api::Usertype::Entity::bind(Api::State::SERVER, lua, core); + Api::Usertype::Inventory::bind(Api::State::SERVER, lua, core); + Api::Usertype::Dimension::bind(Api::State::SERVER, lua, core); + Api::Usertype::ItemStack::bind(Api::State::SERVER, lua, core); + Api::Usertype::ServerPlayer::bind(Api::State::SERVER, lua, core); + Api::Usertype::InventoryList::bind(Api::State::SERVER, lua, core); + Api::Usertype::ServerAnimationManager::bind(Api::State::SERVER, lua, core); + + core["server"] = true; + core["players"] = lua.create_table(); + + // Modules + modules.emplace_back(std::make_unique(Api::State::SERVER, lua, core)); + modules.emplace_back(std::make_unique(Api::State::SERVER, core, game, *world.s())); + + // Register + auto& game = static_cast(this->game); + + Api::Util::createRegister(lua, core, "mesh"); + Api::Util::createRegister(lua, core, "item", + [&](const auto& iden) { RegisterItem::server(core, game, iden); }); + Api::Util::createRegister(lua, core, "block", + [&](const auto& iden) { RegisterBlock::server(core, game, iden); }); + Api::Util::createRegister(lua, core, "biome", + [&](const auto& iden) { RegisterBiome::server(core, game, iden); }); + Api::Util::createRegister(lua, core, "keybind"); + Api::Util::createRegister(lua, core, "blockmodel"); + Api::Util::createRegister(lua, core, "entity", nullptr, "entities"); + + // Define keybind variables + core["keys"] = lua.create_table(); + core["keycodes"] = lua.create_table(); + + for (unsigned short i = 0; i < 350; i++) { + auto key = ::Util::getKeyStr(i); + if (!key.empty()) { + core["keys"][key] = i; + core["keycodes"][i] = key; + } + } + + Api::create_structure(lua, core); + + bindModules(); + + // Create sandboxed runfile() + lua["dofile"] = lua["loadfile"] = sol::nil; + lua.set_function("runfile", &ServerLuaParser::runFileSandboxed, this); } sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result r) const { - sol::error err = r; - std::string errString = err.what(); - - try { - std::string::size_type slash = errString.find_first_of("/"); - if (slash != std::string::npos) throw "npos"; - - std::string modString = errString.substr(0, slash); - - std::string::size_type lineNumStart = errString.find(':', slash); - if (lineNumStart != std::string::npos) throw "lineNumStart"; - std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); - if (lineNumEnd != std::string::npos) throw "lineNumEnd"; - - std::string fileName = errString.substr(0, lineNumStart); - int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); - - for (auto& mod : handler.cGetMods()) { - if (mod.config.name == modString) { - for (auto& file : mod.files) { - if (file.path == fileName) { - std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file) << std::endl; - break; - } - } - break; - } - } - } - catch (...) { - std::cout << Log::err << "Zepha has encountered an error, and ErrorFormatter failed to format it:" - << std::endl << std::endl << errString << Log::endl; - } - - throw std::runtime_error("Exiting."); + sol::error err = r; + std::string errString = err.what(); + + try { + std::string::size_type slash = errString.find_first_of("/"); + if (slash != std::string::npos) throw "npos"; + + std::string modString = errString.substr(0, slash); + + std::string::size_type lineNumStart = errString.find(':', slash); + if (lineNumStart != std::string::npos) throw "lineNumStart"; + std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1); + if (lineNumEnd != std::string::npos) throw "lineNumEnd"; + + std::string fileName = errString.substr(0, lineNumStart); + int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)); + + for (auto& mod : handler.cGetMods()) { + if (mod.config.name == modString) { + for (auto& file : mod.files) { + if (file.path == fileName) { + std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file) + << std::endl; + break; + } + } + break; + } + } + } + catch (...) { + std::cout << Log::err << "Zepha has encountered an error, and ErrorFormatter failed to format it:" + << std::endl << std::endl << errString << Log::endl; + } + + throw std::runtime_error("Exiting."); } sol::protected_function_result ServerLuaParser::runFileSandboxed(const std::string& file) { - size_t modname_length = file.find('/'); - if (modname_length == std::string::npos) throw std::runtime_error("Error opening \"" + file + "\", specified file is invalid."); - std::string modname = file.substr(0, modname_length); - - for (const LuaMod& mod : handler.cGetMods()) { - if (modname != mod.config.name) continue; - for (const LuaMod::File& f : mod.files) { - if (f.path != file) continue; - - sol::environment env(lua, sol::create, lua.globals()); - env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1); - env["_FILE"] = f.path; - env["_MODNAME"] = mod.config.name; - - return lua.safe_script(f.file, env, std::bind(&ServerLuaParser::errorCallback, this, - std::placeholders::_2), "@" + f.path, sol::load_mode::text); - } - throw std::runtime_error("Error opening \"" + file + "\", file not found."); - } - throw std::runtime_error("Error opening \"" + file + "\", mod not found."); + size_t modname_length = file.find('/'); + if (modname_length == std::string::npos) + throw std::runtime_error("Error opening \"" + file + "\", specified file is invalid."); + std::string modname = file.substr(0, modname_length); + + for (const LuaMod& mod : handler.cGetMods()) { + if (modname != mod.config.name) continue; + for (const LuaMod::File& f : mod.files) { + if (f.path != file) continue; + + sol::environment env(lua, sol::create, lua.globals()); + env["_PATH"] = f.path.substr(0, f.path.find_last_of('/') + 1); + env["_FILE"] = f.path; + env["_MODNAME"] = mod.config.name; + + return lua.safe_script(f.file, env, std::bind(&ServerLuaParser::errorCallback, this, + std::placeholders::_2), "@" + f.path, sol::load_mode::text); + } + throw std::runtime_error("Error opening \"" + file + "\", file not found."); + } + throw std::runtime_error("Error opening \"" + file + "\", mod not found."); } \ No newline at end of file diff --git a/src/lua/ServerLuaParser.h b/src/lua/ServerLuaParser.h index 27e41685..34688090 100644 --- a/src/lua/ServerLuaParser.h +++ b/src/lua/ServerLuaParser.h @@ -11,28 +11,33 @@ #include "ServerModHandler.h" class ServerWorld; + class ServerPlayer; + class ServerSubgame; class ServerLuaParser : public LuaParser { -public: - explicit ServerLuaParser(ServerSubgame& game); - void init(WorldPtr world, const std::string& rootPath); - - virtual void update(double delta) override; - - void sendModsPacket(ENetPeer* peer) const; - - void playerConnected(std::shared_ptr client); - void playerDisconnected(std::shared_ptr client); - -private: - void loadApi(WorldPtr world); - - virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override; - sol::protected_function_result runFileSandboxed(const std::string& file); - - ServerModHandler handler; - double accumulatedDelta = 0; + public: + explicit ServerLuaParser(ServerSubgame& game); + + void init(WorldPtr world, const std::string& rootPath); + + virtual void update(double delta) override; + + void sendModsPacket(ENetPeer* peer) const; + + void playerConnected(std::shared_ptr client); + + void playerDisconnected(std::shared_ptr client); + + private: + void loadApi(WorldPtr world); + + virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override; + + sol::protected_function_result runFileSandboxed(const std::string& file); + + ServerModHandler handler; + double accumulatedDelta = 0; }; diff --git a/src/lua/ServerModHandler.cpp b/src/lua/ServerModHandler.cpp index 84d7440d..3d6d22d6 100644 --- a/src/lua/ServerModHandler.cpp +++ b/src/lua/ServerModHandler.cpp @@ -14,290 +14,294 @@ #include "game/ServerSubgame.h" #include "util/net/Serializer.h" -void ServerModHandler::loadMods(ServerSubgame& defs, const std::string &path) { - auto modDirs = findModDirectories(path); - mods = initializeLuaMods(modDirs); - - loadTextures(defs, mods); - loadModels(defs, mods); - - organizeDependencies(mods); - serializeMods(mods); +void ServerModHandler::loadMods(ServerSubgame& defs, const std::string& path) { + auto modDirs = findModDirectories(path); + mods = initializeLuaMods(modDirs); + + loadTextures(defs, mods); + loadModels(defs, mods); + + organizeDependencies(mods); + serializeMods(mods); } void ServerModHandler::executeMods(std::function run) { - for (LuaMod& mod : mods) { - if (mod.config.name == "base") { - run(mod.config.name + "/init"); - break; - } - } - - for (LuaMod& mod : mods) { - if (mod.config.name != "base") run(mod.config.name + "/init"); - } + for (LuaMod& mod : mods) { + if (mod.config.name == "base") { + run(mod.config.name + "/init"); + break; + } + } + + for (LuaMod& mod : mods) { + if (mod.config.name != "base") run(mod.config.name + "/init"); + } } const std::vector& ServerModHandler::cGetMods() const { - return mods; + return mods; } std::list ServerModHandler::findModDirectories(const std::string& path) { - std::list modDirs {path + "/../../../assets/base"}; - std::list dirsToScan {path}; - - cf_dir_t dir; - - while (!dirsToScan.empty()) { - std::string dirStr = *dirsToScan.begin(); - dirsToScan.erase(dirsToScan.begin()); - bool isModFolder = false; - - cf_dir_open(&dir, dirStr.c_str()); - - std::list subDirs; - - while (dir.has_next) { - cf_file_t scannedFile; - cf_read_file(&dir, &scannedFile); - - if (strncmp(scannedFile.name, ".", 1) == 0) { - cf_dir_next(&dir); - continue; - } - - if (scannedFile.is_dir) subDirs.emplace_back(scannedFile.path); - else if (std::string_view(scannedFile.name).size() == 9 && - std::string_view(scannedFile.name).rfind("conf.json") == 0) { - - isModFolder = true; - break; - } - - cf_dir_next(&dir); - } - - cf_dir_close(&dir); - - if (isModFolder) modDirs.push_back(dirStr); - else for (const std::string& s : subDirs) dirsToScan.push_back(s); - } - - return std::move(modDirs); + std::list modDirs{ path + "/../../../assets/base" }; + std::list dirsToScan{ path }; + + cf_dir_t dir; + + while (!dirsToScan.empty()) { + std::string dirStr = *dirsToScan.begin(); + dirsToScan.erase(dirsToScan.begin()); + bool isModFolder = false; + + cf_dir_open(&dir, dirStr.c_str()); + + std::list subDirs; + + while (dir.has_next) { + cf_file_t scannedFile; + cf_read_file(&dir, &scannedFile); + + if (strncmp(scannedFile.name, ".", 1) == 0) { + cf_dir_next(&dir); + continue; + } + + if (scannedFile.is_dir) subDirs.emplace_back(scannedFile.path); + else if (std::string_view(scannedFile.name).size() == 9 && + std::string_view(scannedFile.name).rfind("conf.json") == 0) { + + isModFolder = true; + break; + } + + cf_dir_next(&dir); + } + + cf_dir_close(&dir); + + if (isModFolder) modDirs.push_back(dirStr); + else for (const std::string& s : subDirs) dirsToScan.push_back(s); + } + + return std::move(modDirs); } std::vector ServerModHandler::initializeLuaMods(const std::list& modDirs) { - using nlohmann::json; - - std::vector mods {}; - cf_dir_t dir; - - for (const std::string& modDir : modDirs) { - std::string root = modDir + "/script"; - - std::list dirsToScan {root}; - std::list luaFiles {}; - - while (!dirsToScan.empty()) { - std::string dirStr = *dirsToScan.begin(); - dirsToScan.erase(dirsToScan.begin()); - - cf_dir_open(&dir, dirStr.c_str()); - - while (dir.has_next) { - cf_file_t scannedFile; - cf_read_file(&dir, &scannedFile); - - if (strncmp(scannedFile.name, ".", 1) != 0) { - if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); - else { - char *dot = strrchr(scannedFile.path, '.'); - if (dot && (strncmp(dot, ".lua", 4) == 0)) luaFiles.emplace_back(scannedFile.path); - } - } - cf_dir_next(&dir); - } - cf_dir_close(&dir); - } - - LuaMod mod {}; - mod.modPath = modDir; - auto& conf = mod.config; - - std::ifstream i(modDir + "/conf.json"); - json j {}; - i >> j; - - auto depends = j["depends"]; - if (strncmp(depends.type_name(), "array", 5) == 0) { - for (auto &it : depends) { - if (strncmp(it.type_name(), "string", 6) == 0) { - conf.depends.push_back(static_cast(it)); - } - } - } - - conf.name = j["name"]; - conf.description = j["description"]; - conf.version = j["version"]; - - for (std::string& file : luaFiles) { - size_t rootPos = file.find(root); - std::string modPath = file; - assert(rootPos != std::string::npos); - - std::ifstream t(file); - std::string fileStr = std::string((std::istreambuf_iterator(t)), std::istreambuf_iterator()); - - modPath.erase(rootPos, root.length()); - modPath.insert(0, conf.name); - modPath.resize(modPath.size() - 4); - - LuaMod::File f {modPath, fileStr}; - mod.files.push_back(f); - } - mods.push_back(mod); - } - return mods; + using nlohmann::json; + + std::vector mods{}; + cf_dir_t dir; + + for (const std::string& modDir : modDirs) { + std::string root = modDir + "/script"; + + std::list dirsToScan{ root }; + std::list luaFiles{}; + + while (!dirsToScan.empty()) { + std::string dirStr = *dirsToScan.begin(); + dirsToScan.erase(dirsToScan.begin()); + + cf_dir_open(&dir, dirStr.c_str()); + + while (dir.has_next) { + cf_file_t scannedFile; + cf_read_file(&dir, &scannedFile); + + if (strncmp(scannedFile.name, ".", 1) != 0) { + if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); + else { + char* dot = strrchr(scannedFile.path, '.'); + if (dot && (strncmp(dot, ".lua", 4) == 0)) luaFiles.emplace_back(scannedFile.path); + } + } + cf_dir_next(&dir); + } + cf_dir_close(&dir); + } + + LuaMod mod{}; + mod.modPath = modDir; + auto& conf = mod.config; + + std::ifstream i(modDir + "/conf.json"); + json j{}; + i >> j; + + auto depends = j["depends"]; + if (strncmp(depends.type_name(), "array", 5) == 0) { + for (auto& it : depends) { + if (strncmp(it.type_name(), "string", 6) == 0) { + conf.depends.push_back(static_cast(it)); + } + } + } + + conf.name = j["name"]; + conf.description = j["description"]; + conf.version = j["version"]; + + for (std::string& file : luaFiles) { + size_t rootPos = file.find(root); + std::string modPath = file; + assert(rootPos != std::string::npos); + + std::ifstream t(file); + std::string fileStr = std::string((std::istreambuf_iterator(t)), std::istreambuf_iterator()); + + modPath.erase(rootPos, root.length()); + modPath.insert(0, conf.name); + modPath.resize(modPath.size() - 4); + + LuaMod::File f{ modPath, fileStr }; + mod.files.push_back(f); + } + mods.push_back(mod); + } + return mods; } -void ServerModHandler::loadTextures(ServerSubgame &defs, const std::vector& mods) { - cf_dir_t dir; - for (const LuaMod& mod : mods) { - std::string root = mod.modPath + "/textures"; - - std::list dirsToScan {root}; - - while (!dirsToScan.empty()) { - std::string dirStr = *dirsToScan.begin(); - dirsToScan.erase(dirsToScan.begin()); - - if (!cf_file_exists(dirStr.c_str())) continue; - cf_dir_open(&dir, dirStr.c_str()); - - while (dir.has_next) { - cf_file_t scannedFile; - cf_read_file(&dir, &scannedFile); - - if (strncmp(scannedFile.name, ".", 1) != 0) { - if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); - else { - char *dot = strrchr(scannedFile.path, '.'); - if (dot && strncmp(dot, ".png", 4) == 0) { - - std::string name = std::string(scannedFile.name).substr(0, std::string(scannedFile.name).size() - 4); - name.insert(0, mod.config.name + ":"); - - int width, height; - unsigned char* data = stbi_load(scannedFile.path, &width, &height, nullptr, 4); - std::string str(reinterpret_cast(data), static_cast(width * height * 4)); - std::string comp = gzip::compress(str.data(), str.length()); - free(data); - - defs.assets.textures.push_back({std::move(name), comp, static_cast(width), static_cast(height)}); - } - } - } - - cf_dir_next(&dir); - } - cf_dir_close(&dir); - } - } +void ServerModHandler::loadTextures(ServerSubgame& defs, const std::vector& mods) { + cf_dir_t dir; + for (const LuaMod& mod : mods) { + std::string root = mod.modPath + "/textures"; + + std::list dirsToScan{ root }; + + while (!dirsToScan.empty()) { + std::string dirStr = *dirsToScan.begin(); + dirsToScan.erase(dirsToScan.begin()); + + if (!cf_file_exists(dirStr.c_str())) continue; + cf_dir_open(&dir, dirStr.c_str()); + + while (dir.has_next) { + cf_file_t scannedFile; + cf_read_file(&dir, &scannedFile); + + if (strncmp(scannedFile.name, ".", 1) != 0) { + if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); + else { + char* dot = strrchr(scannedFile.path, '.'); + if (dot && strncmp(dot, ".png", 4) == 0) { + + std::string name = std::string(scannedFile.name).substr(0, + std::string(scannedFile.name).size() - 4); + name.insert(0, mod.config.name + ":"); + + int width, height; + unsigned char* data = stbi_load(scannedFile.path, &width, &height, nullptr, 4); + std::string str(reinterpret_cast(data), + static_cast(width * height * 4)); + std::string comp = gzip::compress(str.data(), str.length()); + free(data); + + defs.assets.textures.push_back({ std::move(name), comp, static_cast(width), + static_cast(height) }); + } + } + } + + cf_dir_next(&dir); + } + cf_dir_close(&dir); + } + } } -void ServerModHandler::loadModels(ServerSubgame &defs, const std::vector& mods) { - cf_dir_t dir; - for (const LuaMod& mod : mods) { - std::string root = mod.modPath + "/models"; - - std::list dirsToScan {root}; - - while (!dirsToScan.empty()) { - std::string dirStr = *dirsToScan.begin(); - dirsToScan.erase(dirsToScan.begin()); - - if (!cf_file_exists(dirStr.c_str())) continue; - cf_dir_open(&dir, dirStr.c_str()); - - while (dir.has_next) { - cf_file_t scannedFile; - cf_read_file(&dir, &scannedFile); - - if (strncmp(scannedFile.name, ".", 1) != 0) { - if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); - else { - char *dot = strrchr(scannedFile.path, '.'); - if (dot && strncmp(dot, ".b3d", 4) == 0) { - - std::string name = std::string(scannedFile.name).substr(0, std::string(scannedFile.name).size() - 4); - name.insert(0, mod.config.name + ":"); - - std::ifstream t(scannedFile.path); - std::stringstream buffer; - buffer << t.rdbuf(); - - defs.assets.models.push_back({std::move(name), buffer.str(), "b3d"}); - } - } - } - - cf_dir_next(&dir); - } - cf_dir_close(&dir); - } - } +void ServerModHandler::loadModels(ServerSubgame& defs, const std::vector& mods) { + cf_dir_t dir; + for (const LuaMod& mod : mods) { + std::string root = mod.modPath + "/models"; + + std::list dirsToScan{ root }; + + while (!dirsToScan.empty()) { + std::string dirStr = *dirsToScan.begin(); + dirsToScan.erase(dirsToScan.begin()); + + if (!cf_file_exists(dirStr.c_str())) continue; + cf_dir_open(&dir, dirStr.c_str()); + + while (dir.has_next) { + cf_file_t scannedFile; + cf_read_file(&dir, &scannedFile); + + if (strncmp(scannedFile.name, ".", 1) != 0) { + if (scannedFile.is_dir) dirsToScan.emplace_back(scannedFile.path); + else { + char* dot = strrchr(scannedFile.path, '.'); + if (dot && strncmp(dot, ".b3d", 4) == 0) { + + std::string name = std::string(scannedFile.name).substr(0, + std::string(scannedFile.name).size() - 4); + name.insert(0, mod.config.name + ":"); + + std::ifstream t(scannedFile.path); + std::stringstream buffer; + buffer << t.rdbuf(); + + defs.assets.models.push_back({ std::move(name), buffer.str(), "b3d" }); + } + } + } + + cf_dir_next(&dir); + } + cf_dir_close(&dir); + } + } } void ServerModHandler::organizeDependencies(std::vector& mods) { - for (int i = 0; i < mods.size(); i++) { - LuaMod& mod = mods[i]; - auto& deps = mod.config.depends; - - bool modifiedList = false; - - for (std::string& dep : deps) { - for (int j = 0; j < mods.size(); j++) { - LuaMod& otherMod = mods[j]; - if (otherMod.config.name == dep) { - if (j > i) { - LuaMod copy = otherMod; - mods.erase(mods.begin() + j); - mods.insert(mods.begin() + i, copy); - i++; - modifiedList = true; - break; - } - } - } - } - - if (modifiedList) i = -1; - } + for (int i = 0; i < mods.size(); i++) { + LuaMod& mod = mods[i]; + auto& deps = mod.config.depends; + + bool modifiedList = false; + + for (std::string& dep : deps) { + for (int j = 0; j < mods.size(); j++) { + LuaMod& otherMod = mods[j]; + if (otherMod.config.name == dep) { + if (j > i) { + LuaMod copy = otherMod; + mods.erase(mods.begin() + j); + mods.insert(mods.begin() + i, copy); + i++; + modifiedList = true; + break; + } + } + } + } + + if (modifiedList) i = -1; + } } void ServerModHandler::serializeMods(std::vector& mods) { - for (LuaMod& mod : mods) { - Serializer s = {}; - s.append(mod.config.name) - .append(mod.config.description) - .append(mod.config.version); - - std::string depends; - bool delimiter = false; - for (const std::string& dep : mod.config.depends) { - if (delimiter) depends.append(","); - else delimiter = true; - depends.append(dep); - } - - s.append(depends); - - for (LuaMod::File& file : mod.files) { - s.append(file.path).append(file.file); - } - - std::string comp = gzip::compress(s.data.c_str(), s.data.length()); - mod.serialized = comp; - } + for (LuaMod& mod : mods) { + Serializer s = {}; + s.append(mod.config.name) + .append(mod.config.description) + .append(mod.config.version); + + std::string depends; + bool delimiter = false; + for (const std::string& dep : mod.config.depends) { + if (delimiter) depends.append(","); + else delimiter = true; + depends.append(dep); + } + + s.append(depends); + + for (LuaMod::File& file : mod.files) { + s.append(file.path).append(file.file); + } + + std::string comp = gzip::compress(s.data.c_str(), s.data.length()); + mod.serialized = comp; + } } diff --git a/src/lua/ServerModHandler.h b/src/lua/ServerModHandler.h index c2847e3d..ce4e5930 100644 --- a/src/lua/ServerModHandler.h +++ b/src/lua/ServerModHandler.h @@ -12,17 +12,25 @@ class ServerSubgame; class ServerModHandler { -public: - void loadMods(ServerSubgame& defs, const std::string& path); - void executeMods(std::function run); - const std::vector& cGetMods() const; -private: - static std::list findModDirectories(const std::string& path); - static std::vector initializeLuaMods(const std::list& modDirs); - static void loadTextures(ServerSubgame &defs, const std::vector& mods); - static void loadModels(ServerSubgame &defs, const std::vector& mods); - static void organizeDependencies(std::vector& mods); - static void serializeMods(std::vector& mods); - - std::vector mods {}; + public: + void loadMods(ServerSubgame& defs, const std::string& path); + + void executeMods(std::function run); + + const std::vector& cGetMods() const; + + private: + static std::list findModDirectories(const std::string& path); + + static std::vector initializeLuaMods(const std::list& modDirs); + + static void loadTextures(ServerSubgame& defs, const std::vector& mods); + + static void loadModels(ServerSubgame& defs, const std::vector& mods); + + static void organizeDependencies(std::vector& mods); + + static void serializeMods(std::vector& mods); + + std::vector mods{}; }; diff --git a/src/lua/customization/vec3.hpp b/src/lua/customization/vec3.hpp index db168750..42c850f8 100644 --- a/src/lua/customization/vec3.hpp +++ b/src/lua/customization/vec3.hpp @@ -15,115 +15,123 @@ #include "../../util/Util.h" namespace sol { - - // Float - - template <> - struct lua_size : std::integral_constant {}; - - template <> - struct lua_type_of : std::integral_constant {}; - - template - inline bool sol_lua_check(types, lua_State* L, int index, Handler&& handler, stack::record& tracking) { - int absoluteIndex = lua_absindex(L, index); - if (!stack::check(L, absoluteIndex, handler)) { - tracking.use(1); - return false; - } - - stack::get_field(L, 1, absoluteIndex); - bool x = stack::check(L, -1); - - stack::get_field(L, 2, absoluteIndex); - bool y = stack::check(L, -1); - - stack::get_field(L, 3, absoluteIndex); - bool z = stack::check(L, -1); - - stack::pop_n(L, 3); - tracking.use(1); - return x && y && z; - } - - inline glm::vec3 sol_lua_get(types, lua_State* L, int index, stack::record& tracking) { - int absoluteIndex = lua_absindex(L, index); - - sol::table table = stack::get(L, absoluteIndex); - float x = table[1]; - float y = table[2]; - float z = table[3]; - - tracking.use(1); - return glm::vec3 { x, y, z }; - } - - - inline int sol_lua_push(sol::types, lua_State* L, const glm::vec3& vec) { - sol::state_view lua(L); - - lua_createtable(L, 3, 0); - sol::stack_table tbl(L, -1); - tbl[1] = vec.x; tbl[2] = vec.y; tbl[3] = vec.z; - tbl[sol::metatable_key] = lua["vector"]; - - return 1; - } - - // Float - - template <> - struct lua_size : std::integral_constant {}; - - template <> - struct lua_type_of : std::integral_constant {}; - - template - inline bool sol_lua_check(types, lua_State* L, int index, Handler&& handler, stack::record& tracking) { - int absoluteIndex = lua_absindex(L, index); - if (!stack::check
(L, absoluteIndex, handler)) { - tracking.use(1); - return false; - } - - stack::get_field(L, 1, absoluteIndex); - bool x = stack::check(L, -1); - - stack::get_field(L, 2, absoluteIndex); - bool y = stack::check(L, -1); - - stack::get_field(L, 3, absoluteIndex); - bool z = stack::check(L, -1); - - stack::pop_n(L, 3); - tracking.use(1); - return x && y && z; - } - - inline glm::ivec3 sol_lua_get(types, lua_State* L, int index, stack::record& tracking) { - int absoluteIndex = lua_absindex(L, index); - - sol::table table = stack::get(L, absoluteIndex); - int x = table[1]; - int y = table[2]; - int z = table[3]; - - tracking.use(1); - return glm::ivec3 { x, y, z }; - } - - - inline int sol_lua_push(sol::types, lua_State* L, const glm::ivec3& vec) { - sol::state_view lua(L); - - lua_createtable(L, 3, 0); - sol::stack_table tbl(L, -1); - tbl[1] = vec.x; tbl[2] = vec.y; tbl[3] = vec.z; - tbl[sol::metatable_key] = lua["vector"]; - - return 1; - } - + + // Float + + template<> + struct lua_size : std::integral_constant { + }; + + template<> + struct lua_type_of : std::integral_constant { + }; + + template + inline bool sol_lua_check(types , lua_State* L, int index, Handler&& handler, stack::record& tracking) { + int absoluteIndex = lua_absindex(L, index); + if (!stack::check
(L, absoluteIndex, handler)) { + tracking.use(1); + return false; + } + + stack::get_field(L, 1, absoluteIndex); + bool x = stack::check(L, -1); + + stack::get_field(L, 2, absoluteIndex); + bool y = stack::check(L, -1); + + stack::get_field(L, 3, absoluteIndex); + bool z = stack::check(L, -1); + + stack::pop_n(L, 3); + tracking.use(1); + return x && y && z; + } + + inline glm::vec3 sol_lua_get(types , lua_State* L, int index, stack::record& tracking) { + int absoluteIndex = lua_absindex(L, index); + + sol::table table = stack::get(L, absoluteIndex); + float x = table[1]; + float y = table[2]; + float z = table[3]; + + tracking.use(1); + return glm::vec3{ x, y, z }; + } + + + inline int sol_lua_push(sol::types, lua_State* L, const glm::vec3& vec) { + sol::state_view lua(L); + + lua_createtable(L, 3, 0); + sol::stack_table tbl(L, -1); + tbl[1] = vec.x; + tbl[2] = vec.y; + tbl[3] = vec.z; + tbl[sol::metatable_key] = lua["vector"]; + + return 1; + } + + // Float + + template<> + struct lua_size : std::integral_constant { + }; + + template<> + struct lua_type_of : std::integral_constant { + }; + + template + inline bool sol_lua_check(types , lua_State* L, int index, Handler&& handler, stack::record& tracking) { + int absoluteIndex = lua_absindex(L, index); + if (!stack::check
(L, absoluteIndex, handler)) { + tracking.use(1); + return false; + } + + stack::get_field(L, 1, absoluteIndex); + bool x = stack::check(L, -1); + + stack::get_field(L, 2, absoluteIndex); + bool y = stack::check(L, -1); + + stack::get_field(L, 3, absoluteIndex); + bool z = stack::check(L, -1); + + stack::pop_n(L, 3); + tracking.use(1); + return x && y && z; + } + + inline glm::ivec3 sol_lua_get(types , lua_State* L, int index, stack::record& tracking) { + int absoluteIndex = lua_absindex(L, index); + + sol::table table = stack::get(L, absoluteIndex); + int x = table[1]; + int y = table[2]; + int z = table[3]; + + tracking.use(1); + return glm::ivec3{ x, y, z }; + } + + + inline int sol_lua_push(sol::types, lua_State* L, const glm::ivec3& vec) { + sol::state_view lua(L); + + lua_createtable(L, 3, 0); + sol::stack_table tbl(L, -1); + tbl[1] = vec.x; + tbl[2] = vec.y; + tbl[3] = vec.z; + tbl[sol::metatable_key] = lua["vector"]; + + return 1; + } + } #pragma clang diagnostic pop \ No newline at end of file diff --git a/src/lua/modules/BaseModule.h b/src/lua/modules/BaseModule.h index 42c62904..5d921067 100644 --- a/src/lua/modules/BaseModule.h +++ b/src/lua/modules/BaseModule.h @@ -7,21 +7,23 @@ #include "sol/forward.hpp" namespace Api { - enum class State { CLIENT, SERVER }; - - namespace Module { - class BaseModule { - public: - BaseModule(State state, sol::state& lua, sol::table& core) : - state(state), lua(lua), core(core) {} - - virtual void bind() = 0; - - protected: - State state; - - sol::state& lua; - sol::table& core; - }; - } + enum class State { + CLIENT, SERVER + }; + + namespace Module { + class BaseModule { + public: + BaseModule(State state, sol::state& lua, sol::table& core) : + state(state), lua(lua), core(core) {} + + virtual void bind() = 0; + + protected: + State state; + + sol::state& lua; + sol::table& core; + }; + } } \ No newline at end of file diff --git a/src/lua/modules/Dimension.cpp b/src/lua/modules/Dimension.cpp index 218ff35a..907f2437 100644 --- a/src/lua/modules/Dimension.cpp +++ b/src/lua/modules/Dimension.cpp @@ -11,38 +11,38 @@ #include "world/ServerWorld.h" void Api::Module::Dimension::bind() { - core.set_function("create_dimension", Util::bind_this(this, &Dimension::createDimension)); - core.set_function("get_dimension", Util::bind_this(this, &Dimension::getDimension)); - core.set_function("get_default_dimension", Util::bind_this(this, &Dimension::getDefaultDimension)); - core.set_function("set_default_dimension", Util::bind_this(this, &Dimension::setDefaultDimension)); + core.set_function("create_dimension", Util::bind_this(this, &Dimension::createDimension)); + core.set_function("get_dimension", Util::bind_this(this, &Dimension::getDimension)); + core.set_function("get_default_dimension", Util::bind_this(this, &Dimension::getDefaultDimension)); + core.set_function("set_default_dimension", Util::bind_this(this, &Dimension::setDefaultDimension)); } Api::Usertype::Dimension Api::Module::Dimension::createDimension(const std::string& identifier, sol::table data) { - std::unordered_set biomes {}; - auto biomesTbl = data.get>("biomes"); - - if (biomesTbl) { - for (auto &entry : *biomesTbl) { - if (entry.second.is()) biomes.insert(entry.second.as()); - } - } - else biomes.insert("*"); - - return Api::Usertype::Dimension(world.createDimension(identifier, biomes)); + std::unordered_set biomes{}; + auto biomesTbl = data.get>("biomes"); + + if (biomesTbl) { + for (auto& entry : *biomesTbl) { + if (entry.second.is()) biomes.insert(entry.second.as()); + } + } + else biomes.insert("*"); + + return Api::Usertype::Dimension(world.createDimension(identifier, biomes)); } void Api::Module::Dimension::setDefaultDimension(const std::string& identifier) { - world.setDefaultDimension(identifier); + world.setDefaultDimension(identifier); } sol::object Api::Module::Dimension::getDefaultDimension(const sol::this_state s) { - auto dim = world.getDefaultDimension(); - if (!dim) return sol::nil; - return sol::make_object(s, Api::Usertype::Dimension(dim)); + auto dim = world.getDefaultDimension(); + if (!dim) return sol::nil; + return sol::make_object(s, Api::Usertype::Dimension(dim)); } sol::object Api::Module::Dimension::getDimension(sol::this_state s, const std::string& identifier) { - auto dim = world.getDimension(identifier); - if (!dim) return sol::nil; - return sol::make_object(s, Api::Usertype::Dimension(dim)); + auto dim = world.getDimension(identifier); + if (!dim) return sol::nil; + return sol::make_object(s, Api::Usertype::Dimension(dim)); } \ No newline at end of file diff --git a/src/lua/modules/Dimension.h b/src/lua/modules/Dimension.h index d7343630..22cd2906 100644 --- a/src/lua/modules/Dimension.h +++ b/src/lua/modules/Dimension.h @@ -9,16 +9,19 @@ #include "../usertype/Dimension.h" namespace Api::Module { - class Dimension : public Api::Module::SubgameModule { - public: - using SubgameModule::SubgameModule; - void bind() override; - - protected: - Api::Usertype::Dimension createDimension(const std::string& identifier, sol::table data); - sol::object getDimension(sol::this_state s, const std::string& identifier); - - sol::object getDefaultDimension(const sol::this_state s); - void setDefaultDimension(const std::string& identifier); - }; + class Dimension : public Api::Module::SubgameModule { + public: + using SubgameModule::SubgameModule; + + void bind() override; + + protected: + Api::Usertype::Dimension createDimension(const std::string& identifier, sol::table data); + + sol::object getDimension(sol::this_state s, const std::string& identifier); + + sol::object getDefaultDimension(const sol::this_state s); + + void setDefaultDimension(const std::string& identifier); + }; } \ No newline at end of file diff --git a/src/lua/modules/SubgameModule.cpp b/src/lua/modules/SubgameModule.cpp index 14173d0c..1273de0e 100644 --- a/src/lua/modules/SubgameModule.cpp +++ b/src/lua/modules/SubgameModule.cpp @@ -8,4 +8,4 @@ #include "lua/LuaParser.h" Api::Module::SubgameModule::SubgameModule(State state, sol::table& core, Subgame& game, World& world) : - BaseModule(state, game.getParser().lua, core), state(state), game(game), world(world) {} \ No newline at end of file + BaseModule(state, game.getParser().lua, core), state(state), game(game), world(world) {} \ No newline at end of file diff --git a/src/lua/modules/SubgameModule.h b/src/lua/modules/SubgameModule.h index 7ea0f3bc..c3b73b30 100644 --- a/src/lua/modules/SubgameModule.h +++ b/src/lua/modules/SubgameModule.h @@ -7,20 +7,22 @@ #include "BaseModule.h" class World; + class Subgame; namespace Api { - namespace Module { - class SubgameModule : public BaseModule { - public: - SubgameModule(State state, sol::table& core, Subgame& game, World& world); - virtual void bind() = 0; - - protected: - State state; - - World& world; - Subgame& game; - }; - } + namespace Module { + class SubgameModule : public BaseModule { + public: + SubgameModule(State state, sol::table& core, Subgame& game, World& world); + + virtual void bind() = 0; + + protected: + State state; + + World& world; + Subgame& game; + }; + } } \ No newline at end of file diff --git a/src/lua/modules/Time.cpp b/src/lua/modules/Time.cpp index c07a386f..7d1ca9e5 100644 --- a/src/lua/modules/Time.cpp +++ b/src/lua/modules/Time.cpp @@ -7,22 +7,22 @@ #include "../Lua.h" void Api::Module::Time::bind() { - auto time = lua.create_table(); - core["time"] = time; - - time.set_function("ns", Util::bind_this(this, &Time::ns)); - time.set_function("ms", Util::bind_this(this, &Time::ms)); - time.set_function("s", Util::bind_this(this, &Time::s)); + auto time = lua.create_table(); + core["time"] = time; + + time.set_function("ns", Util::bind_this(this, &Time::ns)); + time.set_function("ms", Util::bind_this(this, &Time::ms)); + time.set_function("s", Util::bind_this(this, &Time::s)); } float Api::Module::Time::ns() { - return timer.elapsedNs(); + return timer.elapsedNs(); } float Api::Module::Time::ms() { - return timer.elapsedNs() / 1000000.f; + return timer.elapsedNs() / 1000000.f; } float Api::Module::Time::s() { - return timer.elapsedNs() / 1000000.f / 1000.f; + return timer.elapsedNs() / 1000000.f / 1000.f; } diff --git a/src/lua/modules/Time.h b/src/lua/modules/Time.h index 72bb5efb..864078cb 100644 --- a/src/lua/modules/Time.h +++ b/src/lua/modules/Time.h @@ -10,16 +10,19 @@ #include "../../util/Timer.h" namespace Api::Module { - class Time : public Api::Module::BaseModule { - public: - using BaseModule::BaseModule; - void bind() override; - - protected: - float ns(); - float ms(); - float s(); - - Timer timer {}; - }; + class Time : public Api::Module::BaseModule { + public: + using BaseModule::BaseModule; + + void bind() override; + + protected: + float ns(); + + float ms(); + + float s(); + + Timer timer{}; + }; } \ No newline at end of file diff --git a/src/lua/modules/create_structure.h b/src/lua/modules/create_structure.h index 46b67f41..92017de6 100644 --- a/src/lua/modules/create_structure.h +++ b/src/lua/modules/create_structure.h @@ -7,37 +7,37 @@ #include "util/Schematic.h" namespace Api { - static void create_structure(sol::state& lua, sol::table& core) { - core.set_function("create_structure", [&](sol::optional data) { - if (!data) throw "expected a table as the first argument."; - - auto origin = data->get>("origin"); - auto schematic = data->get>("schematic"); - - if (!origin) throw std::runtime_error("expected a table as the first argument."); - if (!schematic) throw std::runtime_error("expected a table as the first argument."); - - auto s = std::make_shared(); - - unsigned int yWid = schematic->size(); - unsigned int zWid = (*schematic).get(1).size(); - unsigned int xWid = (*schematic).get(1).get(1).size(); - - s->dimensions = {xWid, yWid, zWid}; - s->stringData.resize(xWid * yWid * zWid); - - s->origin = origin ? glm::ivec3{*origin} : glm::ivec3 {}; - - for (unsigned int y = 1; y <= yWid; y++) { - for (unsigned int z = 1; z <= zWid; z++) { - for (unsigned int x = 1; x <= xWid; x++) { - s->stringData[s->index({x - 1, y - 1, z - 1})] = - schematic->get(y).get(z).get_or(x, ""); - } - } - } - - return s; - }); - } + static void create_structure(sol::state& lua, sol::table& core) { + core.set_function("create_structure", [&](sol::optional data) { + if (!data) throw "expected a table as the first argument."; + + auto origin = data->get>("origin"); + auto schematic = data->get>("schematic"); + + if (!origin) throw std::runtime_error("expected a table as the first argument."); + if (!schematic) throw std::runtime_error("expected a table as the first argument."); + + auto s = std::make_shared(); + + unsigned int yWid = schematic->size(); + unsigned int zWid = (*schematic).get(1).size(); + unsigned int xWid = (*schematic).get(1).get(1).size(); + + s->dimensions = { xWid, yWid, zWid }; + s->stringData.resize(xWid * yWid * zWid); + + s->origin = origin ? glm::ivec3{ *origin } : glm::ivec3{}; + + for (unsigned int y = 1; y <= yWid; y++) { + for (unsigned int z = 1; z <= zWid; z++) { + for (unsigned int x = 1; x <= xWid; x++) { + s->stringData[s->index({ x - 1, y - 1, z - 1 })] = + schematic->get(y).get(z).get_or(x, ""); + } + } + } + + return s; + }); + } } diff --git a/src/lua/modules/mSetGui.h b/src/lua/modules/mSetGui.h index 09bb46dd..62f99f79 100644 --- a/src/lua/modules/mSetGui.h +++ b/src/lua/modules/mSetGui.h @@ -10,10 +10,10 @@ class LuaGuiElement; namespace MenuApi { - void set_gui(GuiBuilder& builder, glm::ivec2& win, sol::state& lua, sol::table& core) { - core.set_function("set_gui", [&](std::shared_ptr gui) { - builder.setGuiRoot(gui); - builder.build(win); - }); - } + void set_gui(GuiBuilder& builder, glm::ivec2& win, sol::state& lua, sol::table& core) { + core.set_function("set_gui", [&](std::shared_ptr gui) { + builder.setGuiRoot(gui); + builder.build(win); + }); + } } diff --git a/src/lua/modules/mStartGame.h b/src/lua/modules/mStartGame.h index 9d6493c2..17fd2c38 100644 --- a/src/lua/modules/mStartGame.h +++ b/src/lua/modules/mStartGame.h @@ -10,15 +10,15 @@ #include "client/scene/ConnectScene.h" namespace MenuApi { - void start_game(Client& client, sol::table& core) { - core.set_function("game_connect", [&](std::string address) { - client.scene.setScene(std::make_unique(client, Address::fromString(address))); - }); - - core.set_function("game_host", [&](sol::this_state s) { - sol::state_view state(s); - const auto subgame = state.get("zepha.__builtin.subgame"); - client.startLocalServer(subgame); - }); - } + void start_game(Client& client, sol::table& core) { + core.set_function("game_connect", [&](std::string address) { + client.scene.setScene(std::make_unique(client, Address::fromString(address))); + }); + + core.set_function("game_host", [&](sol::this_state s) { + sol::state_view state(s); + const auto subgame = state.get("zepha.__builtin.subgame"); + client.startLocalServer(subgame); + }); + } } \ No newline at end of file diff --git a/src/lua/register/CreateRegister.h b/src/lua/register/CreateRegister.h index 8ed955df..a9612476 100644 --- a/src/lua/register/CreateRegister.h +++ b/src/lua/register/CreateRegister.h @@ -11,6 +11,6 @@ #include namespace Api::Util { - void createRegister(sol::state& lua, sol::table& core, const std::string& name, - std::function after = nullptr, const std::string& table = ""); + void createRegister(sol::state& lua, sol::table& core, const std::string& name, + std::function after = nullptr, const std::string& table = ""); } \ No newline at end of file diff --git a/src/lua/register/RegisterBiome.h b/src/lua/register/RegisterBiome.h index 672705ff..407d6fe6 100644 --- a/src/lua/register/RegisterBiome.h +++ b/src/lua/register/RegisterBiome.h @@ -75,7 +75,7 @@ namespace RegisterBiome { modules.push_back(module); return module; } - // Combiner Modules + // Combiner Modules else if (type == "add") { auto module = new noise::module::Add(); sol::table sources = noise["sources"]; @@ -136,7 +136,7 @@ namespace RegisterBiome { modules.push_back(module); return module; } - // Generator modules + // Generator modules else if (type == "billow") { auto module = new noise::module::Billow(); @@ -212,7 +212,7 @@ namespace RegisterBiome { modules.push_back(module); return module; } - // Selector Modules + // Selector Modules else if (type == "blend") { auto module = new noise::module::Blend(); sol::table sources = noise["sources"]; @@ -274,10 +274,11 @@ namespace RegisterBiome { sol::table biomeTable = biomes[identifier]; // Tags - std::unordered_map tags {}; + std::unordered_map tags{}; auto tagsTbl = biomeTable.get>("tags"); - if (tagsTbl) for (auto& tag : *tagsTbl) - tags.insert({ tag.first.as(), tag.second.as() }); + if (tagsTbl) + for (auto& tag : *tagsTbl) + tags.insert({ tag.first.as(), tag.second.as() }); // Environment Properties for Voronoi Diagram auto environment = biomeTable.get>("environment"); diff --git a/src/lua/register/RegisterKeybind.h b/src/lua/register/RegisterKeybind.h index cd00529e..ea9465ef 100644 --- a/src/lua/register/RegisterKeybind.h +++ b/src/lua/register/RegisterKeybind.h @@ -19,7 +19,7 @@ namespace RegisterKeybind { * @param identifier - The identifier of the keybind in the table. * @param handler - The keybind handler to add the keybind to. */ - + static void registerKeybind(sol::table keybinds, const std::string& identifier, LuaKeybindHandler& handler) { sol::table keybindTbl = keybinds[identifier]; unsigned short def = keybindTbl.get("default"); @@ -42,8 +42,8 @@ namespace RegisterKeybind { * @param game - The keybind handler to add the keybind to. * @param identifier - The identifier of the keybind to add. */ - - static void client(sol::table& core, LuaKeybindHandler& handler, const std::string& identifier) { - registerKeybind(core.get("registered_keybinds"), identifier, handler); - } + + static void client(sol::table& core, LuaKeybindHandler& handler, const std::string& identifier) { + registerKeybind(core.get("registered_keybinds"), identifier, handler); + } }; \ No newline at end of file diff --git a/src/lua/usertype/AnimationManager.cpp b/src/lua/usertype/AnimationManager.cpp index e30f56a2..d972e0a0 100644 --- a/src/lua/usertype/AnimationManager.cpp +++ b/src/lua/usertype/AnimationManager.cpp @@ -12,67 +12,71 @@ Api::Usertype::AnimationManager::AnimationManager(EntityPtr entity) : entity(entity) {} Api::Usertype::AnimationManager Api::Usertype::AnimationManager::define(sol::table anims) { - std::vector animations; - for (auto& ref : anims) { - std::string n = ref.first.as(); - sol::table t = ref.second.as(); - animations.push_back({n, {static_cast(t.get(1)), static_cast(t.get(2))}}); - } - entity->animation.setAnimations(animations); - return *this; + std::vector animations; + for (auto& ref : anims) { + std::string n = ref.first.as(); + sol::table t = ref.second.as(); + animations.push_back( + { n, { static_cast(t.get(1)), static_cast(t.get(2)) }}); + } + entity->animation.setAnimations(animations); + return *this; } Api::Usertype::AnimationManager Api::Usertype::AnimationManager::set_anim(sol::object anim, sol::optional loop) { - if (anim.is()) entity->animation.setAnim(anim.as(), 0, loop.value_or(true)); - else if (anim.is()) entity->animation.setAnim( - glm::ivec2 {anim.as().get(1), anim.as().get(2)}, 0, loop.value_or(true)); - return *this; + if (anim.is()) entity->animation.setAnim(anim.as(), 0, loop.value_or(true)); + else if (anim.is()) + entity->animation.setAnim( + glm::ivec2{ anim.as().get(1), anim.as().get(2) }, 0, + loop.value_or(true)); + return *this; } Api::Usertype::AnimationManager Api::Usertype::AnimationManager::play(sol::optional offset) { - entity->animation.setPlaying(true); - if (offset) entity->animation.setFrame(entity->animation.getFrame() + *offset); - return *this; + entity->animation.setPlaying(true); + if (offset) entity->animation.setFrame(entity->animation.getFrame() + *offset); + return *this; } Api::Usertype::AnimationManager Api::Usertype::AnimationManager::pause(sol::optional offset) { - entity->animation.setPlaying(false); - if (offset) entity->animation.setFrame(entity->animation.getFrame() + *offset); - return *this; + entity->animation.setPlaying(false); + if (offset) entity->animation.setFrame(entity->animation.getFrame() + *offset); + return *this; } -void Api::Usertype::LocalAnimationManager::bind(State, sol::state &lua, sol::table &core) { - lua.new_usertype("AnimationManager", - "define", &LocalAnimationManager::define, - "set_anim", &LocalAnimationManager::set_anim, - "play", &LocalAnimationManager::play, - "pause", &LocalAnimationManager::pause - ); +void Api::Usertype::LocalAnimationManager::bind(State, sol::state& lua, sol::table& core) { + lua.new_usertype("AnimationManager", + "define", &LocalAnimationManager::define, + "set_anim", &LocalAnimationManager::set_anim, + "play", &LocalAnimationManager::play, + "pause", &LocalAnimationManager::pause + ); } -Api::Usertype::AnimationManager Api::Usertype::ServerAnimationManager::set_anim(sol::object anim, sol::optional loop) { - AnimationManager::set_anim(anim, loop); - entity.s()->dirtyField(NetField::ANIM_RANGE); - return *this; +Api::Usertype::AnimationManager +Api::Usertype::ServerAnimationManager::set_anim(sol::object anim, sol::optional loop) { + AnimationManager::set_anim(anim, loop); + entity.s()->dirtyField(NetField::ANIM_RANGE); + return *this; } Api::Usertype::AnimationManager Api::Usertype::ServerAnimationManager::play(sol::optional offset) { - AnimationManager::play(offset); - entity.s()->dirtyField(NetField::ANIM_STATE); - return *this; + AnimationManager::play(offset); + entity.s()->dirtyField(NetField::ANIM_STATE); + return *this; } Api::Usertype::AnimationManager Api::Usertype::ServerAnimationManager::pause(sol::optional offset) { - AnimationManager::pause(offset); - entity.s()->dirtyField(NetField::ANIM_STATE); - return *this; + AnimationManager::pause(offset); + entity.s()->dirtyField(NetField::ANIM_STATE); + return *this; } -void Api::Usertype::ServerAnimationManager::bind(State, sol::state &lua, sol::table &core) { - lua.new_usertype("AnimationManager", - "define", &ServerAnimationManager::define, - "set_anim", &ServerAnimationManager::set_anim, - "play", &ServerAnimationManager::play, - "pause", &ServerAnimationManager::pause - ); +void Api::Usertype::ServerAnimationManager::bind(State, sol::state& lua, sol::table& core) { + lua.new_usertype("AnimationManager", + "define", &ServerAnimationManager::define, + "set_anim", &ServerAnimationManager::set_anim, + "play", &ServerAnimationManager::play, + "pause", &ServerAnimationManager::pause + ); } diff --git a/src/lua/usertype/AnimationManager.h b/src/lua/usertype/AnimationManager.h index 3eeabb8e..089a11e3 100644 --- a/src/lua/usertype/AnimationManager.h +++ b/src/lua/usertype/AnimationManager.h @@ -10,33 +10,38 @@ #include "SubgameUsertype.h" namespace Api::Usertype { - class AnimationManager : public SubgameUsertype { - public: - AnimationManager(EntityPtr entity); - - EntityPtr entity; - - virtual AnimationManager define(sol::table anims); - virtual AnimationManager set_anim(sol::object anim, sol::optional loop); - virtual AnimationManager play(sol::optional offset); - virtual AnimationManager pause(sol::optional offset); - }; - - class LocalAnimationManager : public AnimationManager { - public: - using AnimationManager::AnimationManager; - - static void bind(State state, sol::state& lua, sol::table& core); - }; - - class ServerAnimationManager : public AnimationManager { - public: - using AnimationManager::AnimationManager; - - virtual AnimationManager set_anim(sol::object anim, sol::optional loop) override; - virtual AnimationManager play(sol::optional offset) override; - virtual AnimationManager pause(sol::optional offset) override; - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class AnimationManager : public SubgameUsertype { + public: + AnimationManager(EntityPtr entity); + + EntityPtr entity; + + virtual AnimationManager define(sol::table anims); + + virtual AnimationManager set_anim(sol::object anim, sol::optional loop); + + virtual AnimationManager play(sol::optional offset); + + virtual AnimationManager pause(sol::optional offset); + }; + + class LocalAnimationManager : public AnimationManager { + public: + using AnimationManager::AnimationManager; + + static void bind(State state, sol::state& lua, sol::table& core); + }; + + class ServerAnimationManager : public AnimationManager { + public: + using AnimationManager::AnimationManager; + + virtual AnimationManager set_anim(sol::object anim, sol::optional loop) override; + + virtual AnimationManager play(sol::optional offset) override; + + virtual AnimationManager pause(sol::optional offset) override; + + static void bind(State state, sol::state& lua, sol::table& core); + }; } \ No newline at end of file diff --git a/src/lua/usertype/BaseUsertype.h b/src/lua/usertype/BaseUsertype.h index 0c98a812..5e5c5925 100644 --- a/src/lua/usertype/BaseUsertype.h +++ b/src/lua/usertype/BaseUsertype.h @@ -9,11 +9,12 @@ #include "../modules/BaseModule.h" namespace Api { - namespace Usertype { - class BaseUsertype { - public: - BaseUsertype() = default; - static void bind(State state, sol::state& lua, sol::table& core) {}; - }; - } + namespace Usertype { + class BaseUsertype { + public: + BaseUsertype() = default; + + static void bind(State state, sol::state& lua, sol::table& core) {}; + }; + } } \ No newline at end of file diff --git a/src/lua/usertype/Dimension.cpp b/src/lua/usertype/Dimension.cpp index 59047416..609052a4 100644 --- a/src/lua/usertype/Dimension.cpp +++ b/src/lua/usertype/Dimension.cpp @@ -13,169 +13,173 @@ #include "world/dim/ent/ServerLuaEntity.h" std::string Api::Usertype::Dimension::get_identifier() { - return dim->getIdentifier(); + return dim->getIdentifier(); } std::string Api::Usertype::Dimension::get_block(glm::ivec3 pos) { - return dim->getGame()->getDefs().fromId(dim->getBlock(pos)).identifier; + return dim->getGame()->getDefs().fromId(dim->getBlock(pos)).identifier; } -void Api::Usertype::Dimension::set_block(glm::ivec3 pos, const std::string &block) { - dim->setBlock(pos, dim->getGame()->getDefs().fromStr(block).index); +void Api::Usertype::Dimension::set_block(glm::ivec3 pos, const std::string& block) { + dim->setBlock(pos, dim->getGame()->getDefs().fromStr(block).index); } void Api::Usertype::Dimension::remove_block(glm::ivec3 pos) { - dim->setBlock(pos, DefinitionAtlas::AIR); + dim->setBlock(pos, DefinitionAtlas::AIR); } double Api::Usertype::Dimension::get_block_damage(glm::ivec3 pos) { - return dim->getBlockDamage(pos); + return dim->getBlockDamage(pos); } double Api::Usertype::Dimension::set_block_damage(glm::ivec3 pos, double damage) { - return dim->setBlockDamage(pos, damage); + return dim->setBlockDamage(pos, damage); } double Api::Usertype::Dimension::add_block_damage(glm::ivec3 pos, double damage) { - return dim->setBlockDamage(pos, dim->getBlockDamage(pos) + damage); + return dim->setBlockDamage(pos, dim->getBlockDamage(pos) + damage); } std::string Api::Usertype::Dimension::get_biome(glm::ivec3 pos) { - return dim->getGame()->getBiomes().biomeFromId(dim->getBiome(pos)).identifier; + return dim->getGame()->getBiomes().biomeFromId(dim->getBiome(pos)).identifier; } -void Api::Usertype::Dimension::set_biome(glm::ivec3 pos, const std::string &biome) { - dim->setBiome(pos, dim->getGame()->getBiomes().biomeFromStr(biome).index); +void Api::Usertype::Dimension::set_biome(glm::ivec3 pos, const std::string& biome) { + dim->setBiome(pos, dim->getGame()->getBiomes().biomeFromStr(biome).index); } sol::table Api::Usertype::Dimension::add_entity_c(sol::this_state s, glm::vec3 pos, - const std::string &identifier, sol::optional staticData) { - sol::state_view lua = sol::state_view(s); - sol::table core = lua.get("zepha"); - - if (core["registered_entities"][identifier] == sol::nil) throw std::runtime_error(identifier + " is not a valid entity identifier."); - sol::table def = core["registered_entities"][identifier]; - def["__index"] = def; - - sol::table luaEntity = lua.create_table(); - luaEntity[sol::metatable_key] = def; - luaEntity["name"] = identifier; - - auto displayType = luaEntity.get>("display"); - if (!displayType) throw std::runtime_error("entity '" + identifier + "' is missing the display property."); - - auto displayObject = luaEntity.get>("display_object"); - if (!displayObject) throw std::runtime_error("entity '" + identifier + "' is missing the display_object property."); - - auto displayTexture = luaEntity.get>("display_texture"); - if (strncmp(displayType->data(), "model", 5) == 0 && !displayTexture) throw std::runtime_error("entity '" + identifier + "' is missing the display_texture property."); - - auto entity = std::make_shared<::LocalLuaEntity>(dim->getGame(), dim); - entity->setId(dim->nextEntityInd()); - entity->setPos(pos); - Entity ref(entity); - - luaEntity["object"] = ref; - ref.set_display_type(*displayType, *displayObject, displayTexture); - core.get("entities")[entity->getId()] = luaEntity; - - auto on_create = def.get>("on_create"); - if (on_create) (*on_create)(luaEntity, staticData); - - dim.l()->addLocalEntity(ref); - return luaEntity; + const std::string& identifier, sol::optional staticData) { + sol::state_view lua = sol::state_view(s); + sol::table core = lua.get("zepha"); + + if (core["registered_entities"][identifier] == sol::nil) + throw std::runtime_error(identifier + " is not a valid entity identifier."); + sol::table def = core["registered_entities"][identifier]; + def["__index"] = def; + + sol::table luaEntity = lua.create_table(); + luaEntity[sol::metatable_key] = def; + luaEntity["name"] = identifier; + + auto displayType = luaEntity.get>("display"); + if (!displayType) throw std::runtime_error("entity '" + identifier + "' is missing the display property."); + + auto displayObject = luaEntity.get>("display_object"); + if (!displayObject) throw std::runtime_error("entity '" + identifier + "' is missing the display_object property."); + + auto displayTexture = luaEntity.get>("display_texture"); + if (strncmp(displayType->data(), "model", 5) == 0 && !displayTexture) + throw std::runtime_error("entity '" + identifier + "' is missing the display_texture property."); + + auto entity = std::make_shared<::LocalLuaEntity>(dim->getGame(), dim); + entity->setId(dim->nextEntityInd()); + entity->setPos(pos); + Entity ref(entity); + + luaEntity["object"] = ref; + ref.set_display_type(*displayType, *displayObject, displayTexture); + core.get("entities")[entity->getId()] = luaEntity; + + auto on_create = def.get>("on_create"); + if (on_create) (*on_create)(luaEntity, staticData); + + dim.l()->addLocalEntity(ref); + return luaEntity; } sol::table Api::Usertype::Dimension::add_entity_s(sol::this_state s, glm::vec3 pos, - const std::string &identifier, sol::optional staticData) { - sol::state_view lua = sol::state_view(s); - sol::table core = lua.get("zepha"); - - if (core["registered_entities"][identifier] == sol::nil) throw std::runtime_error(identifier + " is not a valid entity identifier."); - sol::table def = core["registered_entities"][identifier]; - def["__index"] = def; - - sol::table luaEntity = lua.create_table(); - luaEntity[sol::metatable_key] = def; - luaEntity["name"] = identifier; - - auto displayType = luaEntity.get>("display"); - if (!displayType) throw std::runtime_error("entity '" + identifier + "' is missing the display property."); - - auto displayObject = luaEntity.get>("display_object"); - if (!displayObject) throw std::runtime_error("entity '" + identifier + "' is missing the display_object property."); - - auto displayTexture = luaEntity.get>("display_texture"); - if (strncmp(displayType->data(), "model", 5) == 0 && !displayTexture) throw std::runtime_error("entity '" + identifier + "' is missing the display_texture property."); - - unsigned int ind = dim->nextEntityInd(); - auto entity = std::make_shared(dim->getGame(), dim, ind); - entity->setPos(pos); - entity->setId(ind); - Entity ref(entity); - - luaEntity["object"] = ref; - ref.set_display_type(*displayType, *displayObject, displayTexture); - core.get("entities")[entity->getId()] = luaEntity; - - auto on_create = def.get>("on_create"); - if (on_create) (*on_create)(luaEntity, staticData); - - dim.s()->addLuaEntity(ref); - return luaEntity; + const std::string& identifier, sol::optional staticData) { + sol::state_view lua = sol::state_view(s); + sol::table core = lua.get("zepha"); + + if (core["registered_entities"][identifier] == sol::nil) + throw std::runtime_error(identifier + " is not a valid entity identifier."); + sol::table def = core["registered_entities"][identifier]; + def["__index"] = def; + + sol::table luaEntity = lua.create_table(); + luaEntity[sol::metatable_key] = def; + luaEntity["name"] = identifier; + + auto displayType = luaEntity.get>("display"); + if (!displayType) throw std::runtime_error("entity '" + identifier + "' is missing the display property."); + + auto displayObject = luaEntity.get>("display_object"); + if (!displayObject) throw std::runtime_error("entity '" + identifier + "' is missing the display_object property."); + + auto displayTexture = luaEntity.get>("display_texture"); + if (strncmp(displayType->data(), "model", 5) == 0 && !displayTexture) + throw std::runtime_error("entity '" + identifier + "' is missing the display_texture property."); + + unsigned int ind = dim->nextEntityInd(); + auto entity = std::make_shared(dim->getGame(), dim, ind); + entity->setPos(pos); + entity->setId(ind); + Entity ref(entity); + + luaEntity["object"] = ref; + ref.set_display_type(*displayType, *displayObject, displayTexture); + core.get("entities")[entity->getId()] = luaEntity; + + auto on_create = def.get>("on_create"); + if (on_create) (*on_create)(luaEntity, staticData); + + dim.s()->addLuaEntity(ref); + return luaEntity; } void Api::Usertype::Dimension::remove_entity_c(sol::this_state s, sol::table entity) { - sol::state_view lua = sol::state_view(s); - sol::table core = lua.get("zepha"); - - auto object = entity.get>("object"); - if (!object) throw std::runtime_error("Attempting to remove an invalid entity."); - - sol::optional entityTable = core["entities"][object->get_id()]; - if (!entityTable) return; - - sol::optional onDestroy = (*entityTable)["on_destroy"]; - if (onDestroy) (*onDestroy)(); - - core["entities"][object->get_id()] = sol::nil; - dim.l()->removeLocalEntity(*object); + sol::state_view lua = sol::state_view(s); + sol::table core = lua.get("zepha"); + + auto object = entity.get>("object"); + if (!object) throw std::runtime_error("Attempting to remove an invalid entity."); + + sol::optional entityTable = core["entities"][object->get_id()]; + if (!entityTable) return; + + sol::optional onDestroy = (*entityTable)["on_destroy"]; + if (onDestroy) (*onDestroy)(); + + core["entities"][object->get_id()] = sol::nil; + dim.l()->removeLocalEntity(*object); } void Api::Usertype::Dimension::remove_entity_s(sol::this_state s, sol::table entity) { - sol::state_view lua = sol::state_view(s); - sol::table core = lua.get("zepha"); - - auto object = entity.get>("object"); - if (!object) throw std::runtime_error("Attempting to rmeove an invalid entity."); - - sol::optional entityTable = core["entities"][object->get_id()]; - if (!entityTable) return; - - sol::optional onDestroy = (*entityTable)["on_destroy"]; - if (onDestroy) (*onDestroy)(); - - core["entities"][object->get_id()] = sol::nil; - dim.s()->removeLuaEntity(*object); + sol::state_view lua = sol::state_view(s); + sol::table core = lua.get("zepha"); + + auto object = entity.get>("object"); + if (!object) throw std::runtime_error("Attempting to rmeove an invalid entity."); + + sol::optional entityTable = core["entities"][object->get_id()]; + if (!entityTable) return; + + sol::optional onDestroy = (*entityTable)["on_destroy"]; + if (onDestroy) (*onDestroy)(); + + core["entities"][object->get_id()] = sol::nil; + dim.s()->removeLuaEntity(*object); } -void Api::Usertype::Dimension::bind(State state, sol::state &lua, sol::table &core) { - lua.new_usertype("LocalDimension", - "identifier", sol::property(&Dimension::get_identifier), - "get_identifier", &Dimension::get_identifier, - - "get_block", &Dimension::get_block, - "set_block", &Dimension::set_block, - "remove_block", &Dimension::remove_block, - - "get_block_damage", &Dimension::get_block_damage, - "set_block_damage", &Dimension::set_block_damage, - "add_block_damage", &Dimension::add_block_damage, - - "get_biome", &Dimension::get_block, - "set_biome", &Dimension::set_block, - - "add_entity", (state == State::CLIENT ? &Dimension::add_entity_c : &Dimension::add_entity_s), - "remove_entity", (state == State::CLIENT ? &Dimension::remove_entity_c : &Dimension::remove_entity_s) - ); +void Api::Usertype::Dimension::bind(State state, sol::state& lua, sol::table& core) { + lua.new_usertype("LocalDimension", + "identifier", sol::property(&Dimension::get_identifier), + "get_identifier", &Dimension::get_identifier, + + "get_block", &Dimension::get_block, + "set_block", &Dimension::set_block, + "remove_block", &Dimension::remove_block, + + "get_block_damage", &Dimension::get_block_damage, + "set_block_damage", &Dimension::set_block_damage, + "add_block_damage", &Dimension::add_block_damage, + + "get_biome", &Dimension::get_block, + "set_biome", &Dimension::set_block, + + "add_entity", (state == State::CLIENT ? &Dimension::add_entity_c : &Dimension::add_entity_s), + "remove_entity", (state == State::CLIENT ? &Dimension::remove_entity_c : &Dimension::remove_entity_s) + ); } \ No newline at end of file diff --git a/src/lua/usertype/Dimension.h b/src/lua/usertype/Dimension.h index f9607e76..9d555fb9 100644 --- a/src/lua/usertype/Dimension.h +++ b/src/lua/usertype/Dimension.h @@ -13,33 +13,40 @@ class Dimension; namespace Api::Usertype { - class Dimension : public SubgameUsertype { - public: - Dimension(DimensionPtr dim) : dim(dim) {} - - DimensionPtr dim; - - std::string get_identifier(); - - std::string get_block(glm::ivec3 pos); - void set_block(glm::ivec3 pos, const std::string& block); - void remove_block(glm::ivec3 pos); - - double get_block_damage(glm::ivec3 pos); - double set_block_damage(glm::ivec3 pos, double damage); - double add_block_damage(glm::ivec3 pos, double damage); - - std::string get_biome(glm::ivec3 pos); - void set_biome(glm::ivec3 pos, const std::string& biome); - - sol::table add_entity_c(sol::this_state s, glm::vec3 pos, - const std::string &identifier, sol::optional staticData); - sol::table add_entity_s(sol::this_state s, glm::vec3 pos, - const std::string &identifier, sol::optional staticData); - - void remove_entity_c(sol::this_state s, sol::table entity); - void remove_entity_s(sol::this_state s, sol::table entity); - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class Dimension : public SubgameUsertype { + public: + Dimension(DimensionPtr dim) : dim(dim) {} + + DimensionPtr dim; + + std::string get_identifier(); + + std::string get_block(glm::ivec3 pos); + + void set_block(glm::ivec3 pos, const std::string& block); + + void remove_block(glm::ivec3 pos); + + double get_block_damage(glm::ivec3 pos); + + double set_block_damage(glm::ivec3 pos, double damage); + + double add_block_damage(glm::ivec3 pos, double damage); + + std::string get_biome(glm::ivec3 pos); + + void set_biome(glm::ivec3 pos, const std::string& biome); + + sol::table add_entity_c(sol::this_state s, glm::vec3 pos, + const std::string& identifier, sol::optional staticData); + + sol::table add_entity_s(sol::this_state s, glm::vec3 pos, + const std::string& identifier, sol::optional staticData); + + void remove_entity_c(sol::this_state s, sol::table entity); + + void remove_entity_s(sol::this_state s, sol::table entity); + + static void bind(State state, sol::state& lua, sol::table& core); + }; } \ No newline at end of file diff --git a/src/lua/usertype/Entity.cpp b/src/lua/usertype/Entity.cpp index a0a33196..276554b3 100644 --- a/src/lua/usertype/Entity.cpp +++ b/src/lua/usertype/Entity.cpp @@ -13,139 +13,140 @@ #include "world/dim/ent/ServerLuaEntity.h" sol::object Api::Usertype::Entity::get_animation_manager(sol::this_state s) { - if (entity.isL()) return sol::make_object(s, std::static_pointer_cast(animation)); - else return sol::make_object(s, std::static_pointer_cast(animation)); + if (entity.isL()) return sol::make_object(s, std::static_pointer_cast(animation)); + else return sol::make_object(s, std::static_pointer_cast(animation)); } unsigned int Api::Usertype::Entity::get_id() { - return entity->getId(); + return entity->getId(); } void Api::Usertype::Entity::snap_pos(glm::vec3 pos) { - entity->setPos(pos); + entity->setPos(pos); } void Api::Usertype::Entity::set_pos(glm::vec3 pos) { - entity->setPos(pos); + entity->setPos(pos); } glm::vec3 Api::Usertype::Entity::get_pos() { - return entity->getPos(); + return entity->getPos(); } void Api::Usertype::Entity::snap_visual_offset(glm::vec3 vs) { - entity->setVisualOffset(vs); + entity->setVisualOffset(vs); } void Api::Usertype::Entity::set_visual_offset(glm::vec3 vs) { - entity->setVisualOffset(vs); + entity->setVisualOffset(vs); } glm::vec3 Api::Usertype::Entity::get_visual_offset() { - return entity->getVisualOffset(); + return entity->getVisualOffset(); } void Api::Usertype::Entity::snap_pitch(float rot) { - entity->setRotateX(rot); + entity->setRotateX(rot); } void Api::Usertype::Entity::set_pitch(float rot) { - entity->setRotateX(rot); + entity->setRotateX(rot); } float Api::Usertype::Entity::get_pitch() { - return entity->getRotateX(); + return entity->getRotateX(); } void Api::Usertype::Entity::snap_yaw(float rot) { - entity->setRotateY(rot); + entity->setRotateY(rot); } void Api::Usertype::Entity::set_yaw(float rot) { - entity->setRotateY(rot); + entity->setRotateY(rot); } float Api::Usertype::Entity::get_yaw() { - return entity->getRotateY(); + return entity->getRotateY(); } void Api::Usertype::Entity::snap_roll(float rot) { - entity->setRotateZ(rot); + entity->setRotateZ(rot); } void Api::Usertype::Entity::set_roll(float rot) { - entity->setRotateZ(rot); + entity->setRotateZ(rot); } float Api::Usertype::Entity::get_roll() { - return entity->getRotateZ(); + return entity->getRotateZ(); } void Api::Usertype::Entity::snap_scale(float scale) { - entity->setScale(scale); + entity->setScale(scale); } void Api::Usertype::Entity::set_scale(float scale) { - entity->setScale(scale); + entity->setScale(scale); } float Api::Usertype::Entity::get_scale() { - return entity->getScale().x; + return entity->getScale().x; } Api::Usertype::Dimension Api::Usertype::Entity::get_dimension() { - return Dimension(entity->getDim()); + return Dimension(entity->getDim()); } void Api::Usertype::Entity::set_dimension(const std::string& identifier) { - entity->setDim(entity->getDim()->getWorld().getDimension(identifier)); + entity->setDim(entity->getDim()->getWorld().getDimension(identifier)); } -void Api::Usertype::Entity::set_display_type(const std::string &type, const std::string &arg, sol::optional arg2) { - if (strncmp(type.data(), "gameobject", 10) == 0) { - ItemDef& def = entity->getGame()->getDefs().fromStr(arg); - if (def.type == ItemDef::Type::BLOCK) entity->setAppearance("gameobject", "block", arg); - else if (def.type == ItemDef::Type::CRAFTITEM) entity->setAppearance("gameobject", "craftitem", arg); - } - else if (strncmp(type.data(), "model", 5) == 0 && arg2 && !arg2->empty()) { - entity->setAppearance("model", arg, *arg2); - } - else throw std::runtime_error("Invalid display type parameters."); +void Api::Usertype::Entity::set_display_type(const std::string& type, const std::string& arg, + sol::optional arg2) { + if (strncmp(type.data(), "gameobject", 10) == 0) { + ItemDef& def = entity->getGame()->getDefs().fromStr(arg); + if (def.type == ItemDef::Type::BLOCK) entity->setAppearance("gameobject", "block", arg); + else if (def.type == ItemDef::Type::CRAFTITEM) entity->setAppearance("gameobject", "craftitem", arg); + } + else if (strncmp(type.data(), "model", 5) == 0 && arg2 && !arg2->empty()) { + entity->setAppearance("model", arg, *arg2); + } + else throw std::runtime_error("Invalid display type parameters."); } -void Api::Usertype::Entity::bind(State, sol::state &lua, sol::table &core) { - lua.new_usertype("Entity", - "get_id", &Entity::get_id, - "snap_pos", &Entity::snap_pos, - "set_pos", &Entity::set_pos, - "get_pos", &Entity::get_pos, - "snap_visual_offset", &Entity::snap_visual_offset, - "set_visual_offset", &Entity::set_visual_offset, - "get_visual_offset", &Entity::get_visual_offset, - "snap_pitch", &Entity::snap_pitch, - "set_pitch", &Entity::set_pitch, - "get_pitch", &Entity::get_pitch, - "snap_yaw", &Entity::snap_yaw, - "set_yaw", &Entity::set_yaw, - "get_yaw", &Entity::get_yaw, - "snap_roll", &Entity::snap_roll, - "set_roll", &Entity::set_roll, - "get_roll", &Entity::get_roll, - "snap_scale", &Entity::snap_scale, - "set_scale", &Entity::set_scale, - "get_scale", &Entity::get_scale, - - "set_display_type", &Entity::set_display_type, - - "id", sol::property(&Entity::get_id), - "pos", sol::property(&Entity::get_pos, &Entity::set_pos), - "visual_offset", sol::property(&Entity::get_visual_offset, &Entity::set_visual_offset), - "pitch", sol::property(&Entity::get_pitch, &Entity::set_pitch), - "yaw", sol::property(&Entity::get_yaw, &Entity::set_yaw), - "roll", sol::property(&Entity::get_roll, &Entity::set_roll), - "scale", sol::property(&Entity::get_scale, &Entity::set_scale), - "dim", sol::property(&Entity::get_dimension), - - "anims", sol::property(&Entity::get_animation_manager) - ); +void Api::Usertype::Entity::bind(State, sol::state& lua, sol::table& core) { + lua.new_usertype("Entity", + "get_id", &Entity::get_id, + "snap_pos", &Entity::snap_pos, + "set_pos", &Entity::set_pos, + "get_pos", &Entity::get_pos, + "snap_visual_offset", &Entity::snap_visual_offset, + "set_visual_offset", &Entity::set_visual_offset, + "get_visual_offset", &Entity::get_visual_offset, + "snap_pitch", &Entity::snap_pitch, + "set_pitch", &Entity::set_pitch, + "get_pitch", &Entity::get_pitch, + "snap_yaw", &Entity::snap_yaw, + "set_yaw", &Entity::set_yaw, + "get_yaw", &Entity::get_yaw, + "snap_roll", &Entity::snap_roll, + "set_roll", &Entity::set_roll, + "get_roll", &Entity::get_roll, + "snap_scale", &Entity::snap_scale, + "set_scale", &Entity::set_scale, + "get_scale", &Entity::get_scale, + + "set_display_type", &Entity::set_display_type, + + "id", sol::property(&Entity::get_id), + "pos", sol::property(&Entity::get_pos, &Entity::set_pos), + "visual_offset", sol::property(&Entity::get_visual_offset, &Entity::set_visual_offset), + "pitch", sol::property(&Entity::get_pitch, &Entity::set_pitch), + "yaw", sol::property(&Entity::get_yaw, &Entity::set_yaw), + "roll", sol::property(&Entity::get_roll, &Entity::set_roll), + "scale", sol::property(&Entity::get_scale, &Entity::set_scale), + "dim", sol::property(&Entity::get_dimension), + + "anims", sol::property(&Entity::get_animation_manager) + ); } \ No newline at end of file diff --git a/src/lua/usertype/Entity.h b/src/lua/usertype/Entity.h index 32796945..7d32edff 100644 --- a/src/lua/usertype/Entity.h +++ b/src/lua/usertype/Entity.h @@ -14,48 +14,63 @@ #include "world/dim/ent/LocalLuaEntity.h" namespace Api::Usertype { - class Entity : public SubgameUsertype { - public: - Entity(EntityPtr entity) : entity(entity), animation(entity.isL() ? - std::static_pointer_cast(std::make_shared(entity)) : - std::static_pointer_cast(std::make_shared(entity))) {} - - EntityPtr entity; - std::shared_ptr animation; - - sol::object get_animation_manager(sol::this_state s); - - unsigned int get_id(); - - void snap_pos(glm::vec3 pos); - void set_pos(glm::vec3 pos); - glm::vec3 get_pos(); - - void snap_visual_offset(glm::vec3 vs); - void set_visual_offset(glm::vec3 vs); - glm::vec3 get_visual_offset(); - - void snap_pitch(float rot); - void set_pitch(float rot); - float get_pitch(); - - void snap_yaw(float rot); - void set_yaw(float rot); - float get_yaw(); - - void snap_roll(float rot); - void set_roll(float rot); - float get_roll(); - - void snap_scale(float scale); - void set_scale(float scale); - float get_scale(); - - Dimension get_dimension(); - void set_dimension(const std::string& identifier); - - void set_display_type(const std::string& type, const std::string& arg, sol::optional arg2); - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class Entity : public SubgameUsertype { + public: + Entity(EntityPtr entity) : entity(entity), animation(entity.isL() ? + std::static_pointer_cast( + std::make_shared(entity)) : + std::static_pointer_cast( + std::make_shared(entity))) {} + + EntityPtr entity; + std::shared_ptr animation; + + sol::object get_animation_manager(sol::this_state s); + + unsigned int get_id(); + + void snap_pos(glm::vec3 pos); + + void set_pos(glm::vec3 pos); + + glm::vec3 get_pos(); + + void snap_visual_offset(glm::vec3 vs); + + void set_visual_offset(glm::vec3 vs); + + glm::vec3 get_visual_offset(); + + void snap_pitch(float rot); + + void set_pitch(float rot); + + float get_pitch(); + + void snap_yaw(float rot); + + void set_yaw(float rot); + + float get_yaw(); + + void snap_roll(float rot); + + void set_roll(float rot); + + float get_roll(); + + void snap_scale(float scale); + + void set_scale(float scale); + + float get_scale(); + + Dimension get_dimension(); + + void set_dimension(const std::string& identifier); + + void set_display_type(const std::string& type, const std::string& arg, sol::optional arg2); + + static void bind(State state, sol::state& lua, sol::table& core); + }; } \ No newline at end of file diff --git a/src/lua/usertype/Inventory.cpp b/src/lua/usertype/Inventory.cpp index 3a11dda8..5559b102 100644 --- a/src/lua/usertype/Inventory.cpp +++ b/src/lua/usertype/Inventory.cpp @@ -9,17 +9,17 @@ #include "lua/usertype/InventoryList.h" sol::object Api::Usertype::Inventory::add_list(sol::this_state s, std::string name, int size, int width) { - inventory->createList(name, size, width); - return sol::make_object(s, InventoryList(inventory->getList(name))); + inventory->createList(name, size, width); + return sol::make_object(s, InventoryList(inventory->getList(name))); } sol::object Api::Usertype::Inventory::get_list(sol::this_state s, std::string name) { - if (!inventory->hasList(name)) return sol::nil; - return sol::make_object(s, InventoryList(inventory->getList(name))); + if (!inventory->hasList(name)) return sol::nil; + return sol::make_object(s, InventoryList(inventory->getList(name))); } void Api::Usertype::Inventory::remove_list(std::string name) { - inventory->removeList(name); + inventory->removeList(name); } void Api::Usertype::Inventory::set_default_list(sol::object list) { @@ -28,21 +28,23 @@ void Api::Usertype::Inventory::set_default_list(sol::object list) { } sol::object Api::Usertype::Inventory::get_default_list(sol::this_state s) { - return sol::nil; + return sol::nil; // if (inventory.getDefaultList() == "") return sol::nil; // else return get_list(s, inventory.getDefaultList()); } -void Api::Usertype::Inventory::bind(State state, sol::state &lua, sol::table &core) { - if (state == State::SERVER) lua.new_usertype("Inventory", - "get_list", &Inventory::get_list, - "add_list", &Inventory::add_list, - "remove_list", &Inventory::remove_list, - - "set_default_list", &Inventory::set_default_list, - "get_default_list", &Inventory::get_default_list - ); - else lua.new_usertype("Inventory", - "get_list", &Inventory::get_list - ); +void Api::Usertype::Inventory::bind(State state, sol::state& lua, sol::table& core) { + if (state == State::SERVER) + lua.new_usertype("Inventory", + "get_list", &Inventory::get_list, + "add_list", &Inventory::add_list, + "remove_list", &Inventory::remove_list, + + "set_default_list", &Inventory::set_default_list, + "get_default_list", &Inventory::get_default_list + ); + else + lua.new_usertype("Inventory", + "get_list", &Inventory::get_list + ); } diff --git a/src/lua/usertype/Inventory.h b/src/lua/usertype/Inventory.h index eeba7236..64047cad 100644 --- a/src/lua/usertype/Inventory.h +++ b/src/lua/usertype/Inventory.h @@ -11,19 +11,22 @@ #include "../../util/CovariantPtr.h" namespace Api::Usertype { - class Inventory : public SubgameUsertype { - public: - Inventory(InventoryPtr inventory) : inventory(inventory) {} - - InventoryPtr inventory; - - sol::object add_list(sol::this_state s, std::string name, int size, int width); - sol::object get_list(sol::this_state s, std::string name); - void remove_list(std::string name); - - void set_default_list(sol::object list); - sol::object get_default_list(sol::this_state s); - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class Inventory : public SubgameUsertype { + public: + Inventory(InventoryPtr inventory) : inventory(inventory) {} + + InventoryPtr inventory; + + sol::object add_list(sol::this_state s, std::string name, int size, int width); + + sol::object get_list(sol::this_state s, std::string name); + + void remove_list(std::string name); + + void set_default_list(sol::object list); + + sol::object get_default_list(sol::this_state s); + + static void bind(State state, sol::state& lua, sol::table& core); + }; } \ No newline at end of file diff --git a/src/lua/usertype/InventoryList.cpp b/src/lua/usertype/InventoryList.cpp index 1f2fd1e4..f7188d47 100644 --- a/src/lua/usertype/InventoryList.cpp +++ b/src/lua/usertype/InventoryList.cpp @@ -9,87 +9,90 @@ #include "game/atlas/DefinitionAtlas.h" void Api::Usertype::InventoryList::set_length(int length) { - list->setLength(length); + list->setLength(length); } int Api::Usertype::InventoryList::get_length() { - return list->getLength(); + return list->getLength(); } void Api::Usertype::InventoryList::set_width(int width) { - list->setWidth(width); + list->setWidth(width); } int Api::Usertype::InventoryList::get_width() { - return list->getWidth(); + return list->getWidth(); } void Api::Usertype::InventoryList::resize(int length, int width) { - list->setLength(length); - list->setWidth(width); + list->setLength(length); + list->setWidth(width); } std::string Api::Usertype::InventoryList::get_name() { - return list->getName(); + return list->getName(); } Api::Usertype::ItemStack Api::Usertype::InventoryList::get_stack(unsigned short i) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - return ItemStack(list->getStack(i - 1), list->getGame()); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + return ItemStack(list->getStack(i - 1), list->getGame()); } void Api::Usertype::InventoryList::set_stack(unsigned short i, ItemStack stack) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - list->setStack(i - 1, ::ItemStack(stack, list->getGame())); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + list->setStack(i - 1, ::ItemStack(stack, list->getGame())); } void Api::Usertype::InventoryList::set_stack(unsigned short i, sol::table stack) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - list->setStack(i - 1, ::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + list->setStack(i - 1, ::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])); } Api::Usertype::ItemStack Api::Usertype::InventoryList::place_stack(unsigned short i, ItemStack stack) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - return ItemStack(list->placeStack(i - 1, ::ItemStack(stack, list->getGame())), list->getGame()); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + return ItemStack(list->placeStack(i - 1, ::ItemStack(stack, list->getGame())), list->getGame()); } Api::Usertype::ItemStack Api::Usertype::InventoryList::place_stack(unsigned short i, sol::table stack) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - return ItemStack(list->placeStack(i - 1, ::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])), list->getGame()); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + return ItemStack(list->placeStack(i - 1, ::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])), + list->getGame()); } Api::Usertype::ItemStack Api::Usertype::InventoryList::split_stack(unsigned short i) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - return ItemStack(list->splitStack(i - 1), list->getGame()); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + return ItemStack(list->splitStack(i - 1), list->getGame()); } Api::Usertype::ItemStack Api::Usertype::InventoryList::add_stack(ItemStack stack) { - return ItemStack(list->addStack(::ItemStack(stack, list->getGame())), list->getGame()); + return ItemStack(list->addStack(::ItemStack(stack, list->getGame())), list->getGame()); } Api::Usertype::ItemStack Api::Usertype::InventoryList::add_stack(sol::table stack) { - return ItemStack(list->addStack(::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])), list->getGame()); + return ItemStack(list->addStack(::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])), + list->getGame()); } int Api::Usertype::InventoryList::stack_fits(ItemStack stack) { - return list->stackFits(::ItemStack(stack, list->getGame())); + return list->stackFits(::ItemStack(stack, list->getGame())); } int Api::Usertype::InventoryList::stack_fits(sol::table stack) { - return list->stackFits(::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])); + return list->stackFits(::ItemStack(list->getGame()->getDefs().fromStr(stack[1]).index, stack[2])); } Api::Usertype::ItemStack Api::Usertype::InventoryList::take_stack(ItemStack request) { - return ItemStack(list->takeStack(::ItemStack(request, list->getGame())), list->getGame()); + return ItemStack(list->takeStack(::ItemStack(request, list->getGame())), list->getGame()); } Api::Usertype::ItemStack Api::Usertype::InventoryList::take_stack(sol::table request) { - return ItemStack(list->takeStack(::ItemStack(list->getGame()->getDefs().fromStr(request[1]).index, request[2])), list->getGame()); + return ItemStack(list->takeStack(::ItemStack(list->getGame()->getDefs().fromStr(request[1]).index, request[2])), + list->getGame()); } Api::Usertype::ItemStack Api::Usertype::InventoryList::remove_stack(unsigned short i, unsigned short count) { - if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; - return ItemStack(list->removeStack(i - 1, count), list->getGame()); + if (i < 1 || i > list->getLength()) throw "index is outside of list bounds."; + return ItemStack(list->removeStack(i - 1, count), list->getGame()); } //void LuaInventoryList::set_callback(ServerInventoryList::Callback t, sol::safe_function fun) { @@ -100,55 +103,57 @@ Api::Usertype::ItemStack Api::Usertype::InventoryList::remove_stack(unsigned sho // return list->getLuaCallback(t); //} -void Api::Usertype::InventoryList::bind(State state, sol::state &lua, sol::table &core) { - if (state == State::SERVER) lua.new_usertype("InventoryListRef", - "length", sol::property(&InventoryList::get_length, &InventoryList::set_length), - "width", sol::property(&InventoryList::get_width, &InventoryList::set_width), - "name", sol::property(&InventoryList::get_name), - - "resize", &InventoryList::resize, - - "get_stack", &InventoryList::get_stack, - "set_stack", sol::overload( - sol::resolve(&InventoryList::set_stack), - sol::resolve(&InventoryList::set_stack)), - "place_stack", sol::overload( - sol::resolve(&InventoryList::place_stack), - sol::resolve(&InventoryList::place_stack)), - "split_stack", &InventoryList::split_stack, - "add_stack", sol::overload( - sol::resolve(&InventoryList::add_stack), - sol::resolve(&InventoryList::add_stack)), - "stack_fits", sol::overload( - sol::resolve(&InventoryList::stack_fits), - sol::resolve(&InventoryList::stack_fits)), - "take_stack", sol::overload( - sol::resolve(&InventoryList::take_stack), - sol::resolve(&InventoryList::take_stack)), - "remove_stack", &InventoryList::remove_stack - ); - else lua.new_usertype("InventoryListRef", - "length", sol::property(&InventoryList::get_length), - "width", sol::property(&InventoryList::get_width), - "name", sol::property(&InventoryList::get_name), - - "get_stack", &InventoryList::get_stack, - "set_stack", sol::overload( - sol::resolve(&InventoryList::set_stack), - sol::resolve(&InventoryList::set_stack)), - "place_stack", sol::overload( - sol::resolve(&InventoryList::place_stack), - sol::resolve(&InventoryList::place_stack)), - "split_stack", &InventoryList::split_stack, - "add_stack", sol::overload( - sol::resolve(&InventoryList::add_stack), - sol::resolve(&InventoryList::add_stack)), - "stack_fits", sol::overload( - sol::resolve(&InventoryList::stack_fits), - sol::resolve(&InventoryList::stack_fits)), - "take_stack", sol::overload( - sol::resolve(&InventoryList::take_stack), - sol::resolve(&InventoryList::take_stack)), - "remove_stack", &InventoryList::remove_stack - ); +void Api::Usertype::InventoryList::bind(State state, sol::state& lua, sol::table& core) { + if (state == State::SERVER) + lua.new_usertype("InventoryListRef", + "length", sol::property(&InventoryList::get_length, &InventoryList::set_length), + "width", sol::property(&InventoryList::get_width, &InventoryList::set_width), + "name", sol::property(&InventoryList::get_name), + + "resize", &InventoryList::resize, + + "get_stack", &InventoryList::get_stack, + "set_stack", sol::overload( + sol::resolve(&InventoryList::set_stack), + sol::resolve(&InventoryList::set_stack)), + "place_stack", sol::overload( + sol::resolve(&InventoryList::place_stack), + sol::resolve(&InventoryList::place_stack)), + "split_stack", &InventoryList::split_stack, + "add_stack", sol::overload( + sol::resolve(&InventoryList::add_stack), + sol::resolve(&InventoryList::add_stack)), + "stack_fits", sol::overload( + sol::resolve(&InventoryList::stack_fits), + sol::resolve(&InventoryList::stack_fits)), + "take_stack", sol::overload( + sol::resolve(&InventoryList::take_stack), + sol::resolve(&InventoryList::take_stack)), + "remove_stack", &InventoryList::remove_stack + ); + else + lua.new_usertype("InventoryListRef", + "length", sol::property(&InventoryList::get_length), + "width", sol::property(&InventoryList::get_width), + "name", sol::property(&InventoryList::get_name), + + "get_stack", &InventoryList::get_stack, + "set_stack", sol::overload( + sol::resolve(&InventoryList::set_stack), + sol::resolve(&InventoryList::set_stack)), + "place_stack", sol::overload( + sol::resolve(&InventoryList::place_stack), + sol::resolve(&InventoryList::place_stack)), + "split_stack", &InventoryList::split_stack, + "add_stack", sol::overload( + sol::resolve(&InventoryList::add_stack), + sol::resolve(&InventoryList::add_stack)), + "stack_fits", sol::overload( + sol::resolve(&InventoryList::stack_fits), + sol::resolve(&InventoryList::stack_fits)), + "take_stack", sol::overload( + sol::resolve(&InventoryList::take_stack), + sol::resolve(&InventoryList::take_stack)), + "remove_stack", &InventoryList::remove_stack + ); } \ No newline at end of file diff --git a/src/lua/usertype/InventoryList.h b/src/lua/usertype/InventoryList.h index e0257cab..650afc1f 100644 --- a/src/lua/usertype/InventoryList.h +++ b/src/lua/usertype/InventoryList.h @@ -12,46 +12,53 @@ #include "../../util/CovariantPtr.h" namespace Api::Usertype { - class InventoryList : public SubgameUsertype { - public: - InventoryList(InventoryListPtr list) : list(list) {} - - InventoryListPtr list; - - void set_length(int length); - int get_length(); - - void set_width(int width); - int get_width(); - - void resize(int length, int width); - - std::string get_name(); - - ItemStack get_stack(unsigned short i); - - void set_stack(unsigned short i, ItemStack stack); - void set_stack(unsigned short i, sol::table stack); - - ItemStack place_stack(unsigned short i, ItemStack stack); - ItemStack place_stack(unsigned short i, sol::table stack); - - ItemStack split_stack(unsigned short i); - - ItemStack add_stack(ItemStack stack); - ItemStack add_stack(sol::table stack); - - int stack_fits(ItemStack stack); - int stack_fits(sol::table stack); - - ItemStack take_stack(ItemStack request); - ItemStack take_stack(sol::table request); - - ItemStack remove_stack(unsigned short ind, unsigned short count); - - // void set_callback(ServerInventoryList::Callback t, sol::safe_function fun); - // sol::safe_function get_callback(ServerInventoryList::Callback t); - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class InventoryList : public SubgameUsertype { + public: + InventoryList(InventoryListPtr list) : list(list) {} + + InventoryListPtr list; + + void set_length(int length); + + int get_length(); + + void set_width(int width); + + int get_width(); + + void resize(int length, int width); + + std::string get_name(); + + ItemStack get_stack(unsigned short i); + + void set_stack(unsigned short i, ItemStack stack); + + void set_stack(unsigned short i, sol::table stack); + + ItemStack place_stack(unsigned short i, ItemStack stack); + + ItemStack place_stack(unsigned short i, sol::table stack); + + ItemStack split_stack(unsigned short i); + + ItemStack add_stack(ItemStack stack); + + ItemStack add_stack(sol::table stack); + + int stack_fits(ItemStack stack); + + int stack_fits(sol::table stack); + + ItemStack take_stack(ItemStack request); + + ItemStack take_stack(sol::table request); + + ItemStack remove_stack(unsigned short ind, unsigned short count); + + // void set_callback(ServerInventoryList::Callback t, sol::safe_function fun); + // sol::safe_function get_callback(ServerInventoryList::Callback t); + + static void bind(State state, sol::state& lua, sol::table& core); + }; } \ No newline at end of file diff --git a/src/lua/usertype/ItemStack.cpp b/src/lua/usertype/ItemStack.cpp index 007880d1..77654552 100644 --- a/src/lua/usertype/ItemStack.cpp +++ b/src/lua/usertype/ItemStack.cpp @@ -11,42 +11,42 @@ #include "game/atlas/DefinitionAtlas.h" Api::Usertype::ItemStack::ItemStack(const ::ItemStack& stack, SubgamePtr game) : - name((stack.count == 0 ? "" : game->getDefs().fromId(stack.id).identifier)), - count(stack.count) {} + name((stack.count == 0 ? "" : game->getDefs().fromId(stack.id).identifier)), + count(stack.count) {} Api::Usertype::ItemStack::ItemStack(const std::string& name, unsigned short count) : - name(name), count(count) {} + name(name), count(count) {} Api::Usertype::ItemStack::ItemStack(sol::table tbl) : - name(tbl.get(1)), count(tbl.get(2)) {} + name(tbl.get(1)), count(tbl.get(2)) {} std::string Api::Usertype::ItemStack::get_name() { - return name; + return name; } void Api::Usertype::ItemStack::set_name(const std::string& newName) { - name = newName; + name = newName; } int Api::Usertype::ItemStack::get_count() { - return count; + return count; } void Api::Usertype::ItemStack::set_count(int newCount) { - count = newCount; + count = newCount; } bool Api::Usertype::ItemStack::is_empty() { - return count == 0; + return count == 0; } -void Api::Usertype::ItemStack::bind(State state, sol::state &lua, sol::table &core) { - lua.new_usertype("ItemStack", - sol::constructors(), - - "name", sol::property(&ItemStack::get_name, &ItemStack::set_name), - "count", sol::property(&ItemStack::get_count, &ItemStack::set_count), - - "is_empty", &ItemStack::is_empty - ); +void Api::Usertype::ItemStack::bind(State state, sol::state& lua, sol::table& core) { + lua.new_usertype("ItemStack", + sol::constructors(), + + "name", sol::property(&ItemStack::get_name, &ItemStack::set_name), + "count", sol::property(&ItemStack::get_count, &ItemStack::set_count), + + "is_empty", &ItemStack::is_empty + ); } \ No newline at end of file diff --git a/src/lua/usertype/ItemStack.h b/src/lua/usertype/ItemStack.h index 75b98f7f..0ac38135 100644 --- a/src/lua/usertype/ItemStack.h +++ b/src/lua/usertype/ItemStack.h @@ -12,27 +12,34 @@ #include "../../util/CovariantPtr.h" class Subgame; + class ItemStack; namespace Api::Usertype { - class ItemStack : SubgameUsertype { - public: - ItemStack() = default; - explicit ItemStack(sol::table tbl); - ItemStack(const ::ItemStack& stack, SubgamePtr game); - ItemStack(const std::string& name, unsigned short count); - - std::string get_name(); - void set_name(const std::string& newName); - - int get_count(); - void set_count(int newCount); - - bool is_empty(); - - static void bind(State state, sol::state &lua, sol::table &core); - private: - std::string name; - unsigned short count; - }; + class ItemStack : SubgameUsertype { + public: + ItemStack() = default; + + explicit ItemStack(sol::table tbl); + + ItemStack(const ::ItemStack& stack, SubgamePtr game); + + ItemStack(const std::string& name, unsigned short count); + + std::string get_name(); + + void set_name(const std::string& newName); + + int get_count(); + + void set_count(int newCount); + + bool is_empty(); + + static void bind(State state, sol::state& lua, sol::table& core); + + private: + std::string name; + unsigned short count; + }; } \ No newline at end of file diff --git a/src/lua/usertype/LuaGuiElement.cpp b/src/lua/usertype/LuaGuiElement.cpp index 8104d128..6ce1abb0 100644 --- a/src/lua/usertype/LuaGuiElement.cpp +++ b/src/lua/usertype/LuaGuiElement.cpp @@ -10,159 +10,163 @@ #include "client/gui/SerialGui.h" std::shared_ptr LuaGuiElement::create(const std::string& type, sol::table data) { - auto elem = std::make_shared(); - elem->type = type; - - for (const auto& pair : data) { - if (pair.first.is()) { - if (!pair.second.is>()) throw std::runtime_error("Child is not a GuiElement."); - elem->children.push_back(pair.second.as>()); - elem->children.back()->parent = elem.get(); - } - else if (pair.first.is()) elem->set_trait(pair.first.as(), pair.second); - } - - return elem; + auto elem = std::make_shared(); + elem->type = type; + + for (const auto& pair : data) { + if (pair.first.is()) { + if (!pair.second.is>()) + throw std::runtime_error("Child is not a GuiElement."); + elem->children.push_back(pair.second.as>()); + elem->children.back()->parent = elem.get(); + } + else if (pair.first.is()) elem->set_trait(pair.first.as(), pair.second); + } + + return elem; } sol::object LuaGuiElement::get_trait(sol::this_state s, const std::string& key) { - if (key == "key") return sol::make_object(s, this->key); - if (key == "type") return sol::make_object(s, this->type); - - if (traits.count(key)) return traits.at(key); - return sol::nil; + if (key == "key") return sol::make_object(s, this->key); + if (key == "type") return sol::make_object(s, this->type); + + if (traits.count(key)) return traits.at(key); + return sol::nil; } sol::object LuaGuiElement::set_trait(const std::string& key, sol::object val) { - if (key == "callbacks") { - callbacks.clear(); - for (auto pair : val.as()) callbacks[pair.first.as()] = pair.second.as(); - } - else if (key == "key") { - this->key = val.as(); - } - else { - traits.erase(key); - traits.emplace(key, val); - } - - if (updateFunction) updateFunction(); - return val; + if (key == "callbacks") { + callbacks.clear(); + for (auto pair : val.as()) callbacks[pair.first.as()] = pair.second.as(); + } + else if (key == "key") { + this->key = val.as(); + } + else { + traits.erase(key); + traits.emplace(key, val); + } + + if (updateFunction) updateFunction(); + return val; } sol::object LuaGuiElement::call(sol::this_state s, sol::protected_function fun) { - sol::table tbl = sol::state_view(s)["zepha"]["__builtin"]["gui_env"]; - sol::environment env(s, sol::create, tbl); - - sol::set_environment(env, fun); - return fun(this); + sol::table tbl = sol::state_view(s)["zepha"]["__builtin"]["gui_env"]; + sol::environment env(s, sol::create, tbl); + + sol::set_environment(env, fun); + return fun(this); } sol::object LuaGuiElement::get_child(sol::this_state s, sol::object key) { - if (key.is() && key.as() <= children.size()) { - auto begin = children.begin(); - std::advance(begin, key.as() - 1); - return sol::make_object>(s, *begin); - } - else if (key.is()) { - for (auto &child : children) { - if (child->key == key.as()) return sol::make_object>(s, child); - } - - for (auto &child : children) { - auto recurse = child->get_child(s, key); - if (recurse) return recurse; - } - } - - return sol::nil; + if (key.is() && key.as() <= children.size()) { + auto begin = children.begin(); + std::advance(begin, key.as() - 1); + return sol::make_object>(s, *begin); + } + else if (key.is()) { + for (auto& child : children) { + if (child->key == key.as()) return sol::make_object>(s, child); + } + + for (auto& child : children) { + auto recurse = child->get_child(s, key); + if (recurse) return recurse; + } + } + + return sol::nil; } void LuaGuiElement::append(sol::this_state s, sol::object elem) { - if (elem.is>()) children.push_back(elem.as>()); - else if (elem.is()) children.push_back(call(s, elem.as()).as>()); - else throw std::runtime_error("Append arg is not an element or a function to generate one."); - - children.back()->parent = this; - if (updateFunction) updateFunction(); + if (elem.is>()) children.push_back(elem.as>()); + else if (elem.is()) + children.push_back(call(s, elem.as()).as>()); + else throw std::runtime_error("Append arg is not an element or a function to generate one."); + + children.back()->parent = this; + if (updateFunction) updateFunction(); } void LuaGuiElement::prepend(sol::this_state s, sol::object elem) { - if (elem.is>()) children.insert(children.begin(), elem.as>()); - else if (elem.is()) children.insert(children.begin(), call(s, elem.as()).as>()); - else throw std::runtime_error("Append arg is not an element or a function to generate one."); - - children.front()->parent = this; - if (updateFunction) updateFunction(); + if (elem.is>()) + children.insert(children.begin(), elem.as>()); + else if (elem.is()) + children.insert(children.begin(), call(s, elem.as()).as>()); + else throw std::runtime_error("Append arg is not an element or a function to generate one."); + + children.front()->parent = this; + if (updateFunction) updateFunction(); } void LuaGuiElement::remove(sol::this_state s, sol::object elem) { - if (!elem) { - if (parent != nullptr) parent->remove(s, sol::make_object(s, key)); - else throw std::runtime_error("Tried to remove self from nil parent."); - } - else if (elem.is()) { - auto child = this->get_child(s, sol::make_object(s, elem.as())); - if (!child) throw std::runtime_error("Can't find child of key " + elem.as()); - remove(s, child); - } - else if (elem.is>()) { - auto parent = elem.as>()->parent; - - for (auto it = parent->children.cbegin(); it != parent->children.cend(); it++) { - if ((*it)->key == elem.as>()->key) { - (*it)->parent = nullptr; - (*it)->updateFunction = nullptr; - - parent->children.erase(it); - if (parent->updateFunction) parent->updateFunction(); - return; - } - } - } + if (!elem) { + if (parent != nullptr) parent->remove(s, sol::make_object(s, key)); + else throw std::runtime_error("Tried to remove self from nil parent."); + } + else if (elem.is()) { + auto child = this->get_child(s, sol::make_object(s, elem.as())); + if (!child) throw std::runtime_error("Can't find child of key " + elem.as()); + remove(s, child); + } + else if (elem.is>()) { + auto parent = elem.as>()->parent; + + for (auto it = parent->children.cbegin(); it != parent->children.cend(); it++) { + if ((*it)->key == elem.as>()->key) { + (*it)->parent = nullptr; + (*it)->updateFunction = nullptr; + + parent->children.erase(it); + if (parent->updateFunction) parent->updateFunction(); + return; + } + } + } } -Any LuaGuiElement::getAsAny(const std::string &key) const { - if (!traits.count(key)) return Any(); - auto object = traits.at(key); - - if (object.is()) return Any::from(object.as()); - else if (object.is()) return Any::from(object.as()); - else if (object.is()) return Any::from(object.as()); - else if (object.is()) { - auto table = object.as(); - - if (table.size() == 2) { - auto x = table.get(1); - auto y = table.get(2); - - glm::vec2 values = {}; - if (x.is()) values.x = x.as(); - else if (x.is()) values.x = SerialGui::toDouble(x.as()); - if (y.is()) values.y = y.as(); - else if (y.is()) values.y = SerialGui::toDouble(y.as()); - - return Any::from(values); - } - else if (table.size() == 4) { - auto x = table.get(1); - auto y = table.get(2); - auto z = table.get(3); - auto w = table.get(4); - - glm::vec4 values = {}; - if (x.is()) values.x = x.as(); - else if (x.is()) values.x = SerialGui::toDouble(x.as()); - if (y.is()) values.y = y.as(); - else if (y.is()) values.y = SerialGui::toDouble(y.as()); - if (z.is()) values.z = z.as(); - else if (z.is()) values.z = SerialGui::toDouble(z.as()); - if (w.is()) values.w = w.as(); - else if (w.is()) values.w = SerialGui::toDouble(w.as()); - - return Any::from(values); - } - } - - throw std::runtime_error("Invalid type requested in getAsAny"); +Any LuaGuiElement::getAsAny(const std::string& key) const { + if (!traits.count(key)) return Any(); + auto object = traits.at(key); + + if (object.is()) return Any::from(object.as()); + else if (object.is()) return Any::from(object.as()); + else if (object.is()) return Any::from(object.as()); + else if (object.is()) { + auto table = object.as(); + + if (table.size() == 2) { + auto x = table.get(1); + auto y = table.get(2); + + glm::vec2 values = {}; + if (x.is()) values.x = x.as(); + else if (x.is()) values.x = SerialGui::toDouble(x.as()); + if (y.is()) values.y = y.as(); + else if (y.is()) values.y = SerialGui::toDouble(y.as()); + + return Any::from(values); + } + else if (table.size() == 4) { + auto x = table.get(1); + auto y = table.get(2); + auto z = table.get(3); + auto w = table.get(4); + + glm::vec4 values = {}; + if (x.is()) values.x = x.as(); + else if (x.is()) values.x = SerialGui::toDouble(x.as()); + if (y.is()) values.y = y.as(); + else if (y.is()) values.y = SerialGui::toDouble(y.as()); + if (z.is()) values.z = z.as(); + else if (z.is()) values.z = SerialGui::toDouble(z.as()); + if (w.is()) values.w = w.as(); + else if (w.is()) values.w = SerialGui::toDouble(w.as()); + + return Any::from(values); + } + } + + throw std::runtime_error("Invalid type requested in getAsAny"); } diff --git a/src/lua/usertype/LuaGuiElement.h b/src/lua/usertype/LuaGuiElement.h index 4960e160..0e28e663 100644 --- a/src/lua/usertype/LuaGuiElement.h +++ b/src/lua/usertype/LuaGuiElement.h @@ -10,65 +10,72 @@ #include "../../util/Any.h" class LuaGuiElement { -public: - LuaGuiElement() = default; - - // Lua Functions and Properties - static std::shared_ptr create(const std::string& type, sol::table data); - - sol::object get_trait(sol::this_state s, const std::string& key); - sol::object set_trait(const std::string& key, sol::object val); - - sol::object call(sol::this_state s, sol::protected_function fun); - sol::object get_child(sol::this_state s, sol::object key); - - void append(sol::this_state s, sol::object elem); - void prepend(sol::this_state s, sol::object elem); - void remove(sol::this_state s, sol::object elem); - - std::string type {}, key {}; - - LuaGuiElement* parent = nullptr; - std::list> children {}; - - std::unordered_map callbacks {}; - std::unordered_map traits {}; - - // C++ Functions and Properties - Any getAsAny(const std::string& key) const; - - template const T& get(const std::string& key) const { - return getAsAny(key).get(); - } - - template const T& get_or(const std::string& key, const T& other) const noexcept { - Any a = getAsAny(key); - if (a.empty() || !a.is()) return other; - return a.get(); - } - - template const bool has(const std::string& key) const noexcept { - Any a = getAsAny(key); - return !a.empty() && a.is(); - } - - std::function updateFunction = nullptr; + public: + LuaGuiElement() = default; + + // Lua Functions and Properties + static std::shared_ptr create(const std::string& type, sol::table data); + + sol::object get_trait(sol::this_state s, const std::string& key); + + sol::object set_trait(const std::string& key, sol::object val); + + sol::object call(sol::this_state s, sol::protected_function fun); + + sol::object get_child(sol::this_state s, sol::object key); + + void append(sol::this_state s, sol::object elem); + + void prepend(sol::this_state s, sol::object elem); + + void remove(sol::this_state s, sol::object elem); + + std::string type{}, key{}; + + LuaGuiElement* parent = nullptr; + std::list> children{}; + + std::unordered_map callbacks{}; + std::unordered_map traits{}; + + // C++ Functions and Properties + Any getAsAny(const std::string& key) const; + + template + const T& get(const std::string& key) const { + return getAsAny(key).get(); + } + + template + const T& get_or(const std::string& key, const T& other) const noexcept { + Any a = getAsAny(key); + if (a.empty() || !a.is()) return other; + return a.get(); + } + + template + const bool has(const std::string& key) const noexcept { + Any a = getAsAny(key); + return !a.empty() && a.is(); + } + + std::function updateFunction = nullptr; }; namespace ClientApi { - static void gui_element(sol::state& lua) { - lua.new_usertype("GuiElement", - sol::meta_function::construct, sol::factories(&LuaGuiElement::create), - - sol::meta_function::index, &LuaGuiElement::get_trait, - sol::meta_function::new_index, &LuaGuiElement::set_trait, - - sol::meta_function::call, &LuaGuiElement::call, - - "get", &LuaGuiElement::get_child, - "append", &LuaGuiElement::append, - "prepend", &LuaGuiElement::prepend, - "remove", &LuaGuiElement::remove - ); - } + static void gui_element(sol::state& lua) { + lua.new_usertype("GuiElement", + sol::meta_function::construct, sol::factories(&LuaGuiElement::create), + + sol::meta_function::index, &LuaGuiElement::get_trait, + sol::meta_function::new_index, &LuaGuiElement::set_trait, + + sol::meta_function::call, &LuaGuiElement::call, + + "get", &LuaGuiElement::get_child, + "append", &LuaGuiElement::append, + "prepend", &LuaGuiElement::prepend, + "remove", &LuaGuiElement::remove + ); + } } diff --git a/src/lua/usertype/Player.cpp b/src/lua/usertype/Player.cpp index b8089d1a..18b32462 100644 --- a/src/lua/usertype/Player.cpp +++ b/src/lua/usertype/Player.cpp @@ -13,208 +13,208 @@ #include "world/player/LocalPlayer.h" unsigned int Api::Usertype::ServerPlayer::get_id() { - return player->getId(); + return player->getId(); } glm::vec3 Api::Usertype::ServerPlayer::get_pos() { - return player->getPos(); + return player->getPos(); } glm::vec3 Api::Usertype::ServerPlayer::get_block_pos() { - return glm::floor(player->getPos()); + return glm::floor(player->getPos()); } void Api::Usertype::ServerPlayer::set_pos(glm::vec3 pos) { - player->setPos(pos, true); + player->setPos(pos, true); } glm::vec3 Api::Usertype::ServerPlayer::get_vel() { - return player->getVel(); + return player->getVel(); } void Api::Usertype::ServerPlayer::set_vel(glm::vec3 vel) { - player->setVel(vel, true); + player->setVel(vel, true); } float Api::Usertype::ServerPlayer::get_look_yaw() { - return player->getYaw(); + return player->getYaw(); } void Api::Usertype::ServerPlayer::set_look_yaw(float rot) { - player->setYaw(rot, true); + player->setYaw(rot, true); } float Api::Usertype::ServerPlayer::get_look_pitch() { - return player->getPitch(); + return player->getPitch(); } void Api::Usertype::ServerPlayer::set_look_pitch(float rot) { - player->setPitch(rot, true); + player->setPitch(rot, true); } Api::Usertype::Inventory Api::Usertype::ServerPlayer::get_inventory() { - return Inventory(player->getInventory()); + return Inventory(player->getInventory()); } Api::Usertype::Dimension Api::Usertype::ServerPlayer::get_dimension() { - return Dimension(player->getDim()); + return Dimension(player->getDim()); } void Api::Usertype::ServerPlayer::set_dimension(const std::string& identifier) { - player->setDim(player->getDim()->getWorld().getDimension(identifier), true); + player->setDim(player->getDim()->getWorld().getDimension(identifier), true); } sol::object Api::Usertype::ServerPlayer::get_hand_list(sol::this_state s) { - auto listStr = player->getHandList(); - if (listStr.empty()) return sol::nil; - return sol::make_object(s, InventoryList(player->getInventory()->getList(listStr))); + auto listStr = player->getHandList(); + if (listStr.empty()) return sol::nil; + return sol::make_object(s, InventoryList(player->getInventory()->getList(listStr))); } sol::object Api::Usertype::ServerPlayer::get_hand_stack(sol::this_state s) { - auto listStr = player->getHandList(); - if (listStr.empty()) return sol::nil; - return sol::make_object(s, InventoryList(player->getInventory()->getList(listStr)).get_stack(1)); + auto listStr = player->getHandList(); + if (listStr.empty()) return sol::nil; + return sol::make_object(s, InventoryList(player->getInventory()->getList(listStr)).get_stack(1)); } void Api::Usertype::ServerPlayer::set_hand_list(sol::optional list) { - if (!list) player->setHandList("", true); - else if (list->is()) player->setHandList(list->as(), true); - else if (list->is()) player->setHandList(list->as().get_name(), true); - else throw "Attempted to set hand list to nil."; + if (!list) player->setHandList("", true); + else if (list->is()) player->setHandList(list->as(), true); + else if (list->is()) player->setHandList(list->as().get_name(), true); + else throw "Attempted to set hand list to nil."; } sol::object Api::Usertype::ServerPlayer::get_wield_list(sol::this_state s) { - auto listStr = player->getWieldList(); - if (listStr.empty()) return sol::nil; - return sol::make_object(s, InventoryList(player->getInventory()->getList(listStr))); + auto listStr = player->getWieldList(); + if (listStr.empty()) return sol::nil; + return sol::make_object(s, InventoryList(player->getInventory()->getList(listStr))); } void Api::Usertype::ServerPlayer::set_wield_list(sol::optional list) { - if (!list) player->setWieldList("", true); - else if (list->is()) player->setWieldList(list->as(), true); - else if (list->is()) player->setWieldList(list->as().get_name(), true); - else throw "Attempted to set wield list to nil."; + if (!list) player->setWieldList("", true); + else if (list->is()) player->setWieldList(list->as(), true); + else if (list->is()) player->setWieldList(list->as().get_name(), true); + else throw "Attempted to set wield list to nil."; } unsigned int Api::Usertype::ServerPlayer::get_wield_index() { - return player->getWieldIndex() + 1; + return player->getWieldIndex() + 1; } void Api::Usertype::ServerPlayer::set_wield_index(unsigned int index) { - player->setWieldIndex(index - 1, true); + player->setWieldIndex(index - 1, true); } sol::object Api::Usertype::ServerPlayer::get_wield_stack(sol::this_state s) { - auto listStr = player->getWieldList(); - if (listStr.empty()) return sol::nil; - return sol::make_object(s, InventoryList(player->getInventory() - ->getList(listStr)).get_stack(player->getWieldIndex() + 1)); + auto listStr = player->getWieldList(); + if (listStr.empty()) return sol::nil; + return sol::make_object(s, InventoryList(player->getInventory() + ->getList(listStr)).get_stack(player->getWieldIndex() + 1)); } void Api::Usertype::ServerPlayer::set_flying(bool shouldFly) { - player->setFlying(shouldFly, true); + player->setFlying(shouldFly, true); } bool Api::Usertype::ServerPlayer::get_flying() { - return player->isFlying(); + return player->isFlying(); } -void Api::Usertype::ServerPlayer::bind(State, sol::state &lua, sol::table &core) { - lua.new_usertype("Player", - "get_id", &ServerPlayer::get_id, - "get_pos", &ServerPlayer::get_pos, - "get_block_pos", &ServerPlayer::get_block_pos, - "set_pos", &ServerPlayer::set_pos, - "get_vel", &ServerPlayer::get_vel, - "set_vel", &ServerPlayer::set_vel, - "get_look_yaw", &ServerPlayer::get_look_yaw, - "set_look_yaw", &ServerPlayer::set_look_yaw, - "get_look_pitch", &ServerPlayer::get_look_pitch, - "set_look_pitch", &ServerPlayer::set_look_pitch, - - "get_inventory", &ServerPlayer::get_inventory, - "get_hand_list", &ServerPlayer::get_hand_list, - "set_hand_list", &ServerPlayer::set_hand_list, - "get_hand_stack", &ServerPlayer::get_hand_stack, - "get_wield_list", &ServerPlayer::get_wield_list, - "set_wield_list", &ServerPlayer::set_wield_list, - "get_wield_index", &ServerPlayer::get_wield_index, - "set_wield_index", &ServerPlayer::set_wield_index, - "get_wield_stack", &ServerPlayer::get_wield_stack, - - "get_dimension", &ServerPlayer::get_dimension, - "set_dimension", &ServerPlayer::set_dimension, - - "id", sol::property(&ServerPlayer::get_id), - "pos", sol::property(&ServerPlayer::get_pos, &ServerPlayer::set_pos), - "block_pos", sol::property(&ServerPlayer::get_block_pos, &ServerPlayer::set_pos), - "vel", sol::property(&ServerPlayer::get_vel, &ServerPlayer::set_vel), - "look_yaw", sol::property(&ServerPlayer::get_look_yaw, &ServerPlayer::set_look_yaw), - "look_pitch", sol::property(&ServerPlayer::get_look_pitch, &ServerPlayer::set_look_pitch), - "dim", sol::property(&ServerPlayer::get_dimension), - - "flying", sol::property(&ServerPlayer::set_flying, &ServerPlayer::get_flying) - ); +void Api::Usertype::ServerPlayer::bind(State, sol::state& lua, sol::table& core) { + lua.new_usertype("Player", + "get_id", &ServerPlayer::get_id, + "get_pos", &ServerPlayer::get_pos, + "get_block_pos", &ServerPlayer::get_block_pos, + "set_pos", &ServerPlayer::set_pos, + "get_vel", &ServerPlayer::get_vel, + "set_vel", &ServerPlayer::set_vel, + "get_look_yaw", &ServerPlayer::get_look_yaw, + "set_look_yaw", &ServerPlayer::set_look_yaw, + "get_look_pitch", &ServerPlayer::get_look_pitch, + "set_look_pitch", &ServerPlayer::set_look_pitch, + + "get_inventory", &ServerPlayer::get_inventory, + "get_hand_list", &ServerPlayer::get_hand_list, + "set_hand_list", &ServerPlayer::set_hand_list, + "get_hand_stack", &ServerPlayer::get_hand_stack, + "get_wield_list", &ServerPlayer::get_wield_list, + "set_wield_list", &ServerPlayer::set_wield_list, + "get_wield_index", &ServerPlayer::get_wield_index, + "set_wield_index", &ServerPlayer::set_wield_index, + "get_wield_stack", &ServerPlayer::get_wield_stack, + + "get_dimension", &ServerPlayer::get_dimension, + "set_dimension", &ServerPlayer::set_dimension, + + "id", sol::property(&ServerPlayer::get_id), + "pos", sol::property(&ServerPlayer::get_pos, &ServerPlayer::set_pos), + "block_pos", sol::property(&ServerPlayer::get_block_pos, &ServerPlayer::set_pos), + "vel", sol::property(&ServerPlayer::get_vel, &ServerPlayer::set_vel), + "look_yaw", sol::property(&ServerPlayer::get_look_yaw, &ServerPlayer::set_look_yaw), + "look_pitch", sol::property(&ServerPlayer::get_look_pitch, &ServerPlayer::set_look_pitch), + "dim", sol::property(&ServerPlayer::get_dimension), + + "flying", sol::property(&ServerPlayer::set_flying, &ServerPlayer::get_flying) + ); } bool Api::Usertype::LocalPlayer::is_in_menu() { - return player.l()->isInMenu(); + return player.l()->isInMenu(); } void Api::Usertype::LocalPlayer::show_menu(std::shared_ptr root) { - return player.l()->showMenu(root); + return player.l()->showMenu(root); } void Api::Usertype::LocalPlayer::close_menu() { - return player.l()->closeMenu(); + return player.l()->closeMenu(); } std::shared_ptr Api::Usertype::LocalPlayer::get_hud() { - return player.l()->getHud(); + return player.l()->getHud(); } void Api::Usertype::LocalPlayer::set_hud(std::shared_ptr hud) { - player.l()->setHud(hud); + player.l()->setHud(hud); } -void Api::Usertype::LocalPlayer::bind(State, sol::state &lua, sol::table &core) { - lua.new_usertype("Player", - "get_id", &LocalPlayer::get_id, - "get_pos", &LocalPlayer::get_pos, - "get_block_pos", &LocalPlayer::get_block_pos, - "set_pos", &LocalPlayer::set_pos, - "get_vel", &LocalPlayer::get_vel, - "set_vel", &LocalPlayer::set_vel, - "get_look_yaw", &LocalPlayer::get_look_yaw, - "set_look_yaw", &LocalPlayer::set_look_yaw, - "get_look_pitch", &LocalPlayer::get_look_pitch, - "set_look_pitch", &LocalPlayer::set_look_pitch, - - "get_inventory", &LocalPlayer::get_inventory, - "get_hand_list", &LocalPlayer::get_hand_list, - "get_hand_stack", &LocalPlayer::get_hand_stack, - "get_wield_list", &LocalPlayer::get_wield_list, - "set_wield_list", &LocalPlayer::set_wield_list, - "get_wield_index", &LocalPlayer::get_wield_index, - "set_wield_index", &LocalPlayer::set_wield_index, - "get_wield_stack", &LocalPlayer::get_wield_stack, - - "get_dimension", &LocalPlayer::get_dimension, - - "show_menu", &LocalPlayer::show_menu, - "close_menu", &LocalPlayer::close_menu, - "set_hud", &LocalPlayer::set_hud, - "get_hud", &LocalPlayer::get_hud, - - "pos", sol::property(&LocalPlayer::get_pos, &LocalPlayer::set_pos), - "block_pos", sol::property(&LocalPlayer::get_block_pos, &LocalPlayer::set_pos), - "vel", sol::property(&LocalPlayer::get_vel, &LocalPlayer::set_vel), - "look_yaw", sol::property(&LocalPlayer::get_look_yaw, &LocalPlayer::set_look_yaw), - "look_pitch", sol::property(&LocalPlayer::get_look_pitch, &LocalPlayer::set_look_pitch), - "dim", sol::property(&LocalPlayer::get_dimension), - - "flying", sol::property(&LocalPlayer::set_flying, &LocalPlayer::get_flying), - - "in_menu", sol::property(&LocalPlayer::is_in_menu) - ); +void Api::Usertype::LocalPlayer::bind(State, sol::state& lua, sol::table& core) { + lua.new_usertype("Player", + "get_id", &LocalPlayer::get_id, + "get_pos", &LocalPlayer::get_pos, + "get_block_pos", &LocalPlayer::get_block_pos, + "set_pos", &LocalPlayer::set_pos, + "get_vel", &LocalPlayer::get_vel, + "set_vel", &LocalPlayer::set_vel, + "get_look_yaw", &LocalPlayer::get_look_yaw, + "set_look_yaw", &LocalPlayer::set_look_yaw, + "get_look_pitch", &LocalPlayer::get_look_pitch, + "set_look_pitch", &LocalPlayer::set_look_pitch, + + "get_inventory", &LocalPlayer::get_inventory, + "get_hand_list", &LocalPlayer::get_hand_list, + "get_hand_stack", &LocalPlayer::get_hand_stack, + "get_wield_list", &LocalPlayer::get_wield_list, + "set_wield_list", &LocalPlayer::set_wield_list, + "get_wield_index", &LocalPlayer::get_wield_index, + "set_wield_index", &LocalPlayer::set_wield_index, + "get_wield_stack", &LocalPlayer::get_wield_stack, + + "get_dimension", &LocalPlayer::get_dimension, + + "show_menu", &LocalPlayer::show_menu, + "close_menu", &LocalPlayer::close_menu, + "set_hud", &LocalPlayer::set_hud, + "get_hud", &LocalPlayer::get_hud, + + "pos", sol::property(&LocalPlayer::get_pos, &LocalPlayer::set_pos), + "block_pos", sol::property(&LocalPlayer::get_block_pos, &LocalPlayer::set_pos), + "vel", sol::property(&LocalPlayer::get_vel, &LocalPlayer::set_vel), + "look_yaw", sol::property(&LocalPlayer::get_look_yaw, &LocalPlayer::set_look_yaw), + "look_pitch", sol::property(&LocalPlayer::get_look_pitch, &LocalPlayer::set_look_pitch), + "dim", sol::property(&LocalPlayer::get_dimension), + + "flying", sol::property(&LocalPlayer::set_flying, &LocalPlayer::get_flying), + + "in_menu", sol::property(&LocalPlayer::is_in_menu) + ); } \ No newline at end of file diff --git a/src/lua/usertype/Player.h b/src/lua/usertype/Player.h index 3acca805..34e60c09 100644 --- a/src/lua/usertype/Player.h +++ b/src/lua/usertype/Player.h @@ -15,60 +15,75 @@ class LuaGuiElement; namespace Api::Usertype { - class ServerPlayer : public SubgameUsertype { - public: - ServerPlayer(PlayerPtr player) : player(player) {} - - PlayerPtr player; - - unsigned int get_id(); - - glm::vec3 get_pos(); - glm::vec3 get_block_pos(); - void set_pos(glm::vec3 pos); - - glm::vec3 get_vel(); - void set_vel(glm::vec3 vel); - - float get_look_yaw(); - void set_look_yaw(float rot); - - float get_look_pitch(); - void set_look_pitch(float rot); - - sol::object get_hand_list(sol::this_state s); - sol::object get_hand_stack(sol::this_state s); - void set_hand_list(sol::optional list); - - sol::object get_wield_list(sol::this_state s); - sol::object get_wield_stack(sol::this_state s); - void set_wield_list(sol::optional list); - - Inventory get_inventory(); - - Dimension get_dimension(); - void set_dimension(const std::string& identifier); - - unsigned int get_wield_index(); - void set_wield_index(unsigned int index); - - void set_flying(bool shouldFly); - bool get_flying(); - - static void bind(State state, sol::state& lua, sol::table& core); - }; - - class LocalPlayer : public ServerPlayer { - public: - LocalPlayer(PlayerPtr player) : ServerPlayer(player) {} - - bool is_in_menu(); - void show_menu(std::shared_ptr root); - void close_menu(); - - std::shared_ptr get_hud(); - void set_hud(std::shared_ptr hud); - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class ServerPlayer : public SubgameUsertype { + public: + ServerPlayer(PlayerPtr player) : player(player) {} + + PlayerPtr player; + + unsigned int get_id(); + + glm::vec3 get_pos(); + + glm::vec3 get_block_pos(); + + void set_pos(glm::vec3 pos); + + glm::vec3 get_vel(); + + void set_vel(glm::vec3 vel); + + float get_look_yaw(); + + void set_look_yaw(float rot); + + float get_look_pitch(); + + void set_look_pitch(float rot); + + sol::object get_hand_list(sol::this_state s); + + sol::object get_hand_stack(sol::this_state s); + + void set_hand_list(sol::optional list); + + sol::object get_wield_list(sol::this_state s); + + sol::object get_wield_stack(sol::this_state s); + + void set_wield_list(sol::optional list); + + Inventory get_inventory(); + + Dimension get_dimension(); + + void set_dimension(const std::string& identifier); + + unsigned int get_wield_index(); + + void set_wield_index(unsigned int index); + + void set_flying(bool shouldFly); + + bool get_flying(); + + static void bind(State state, sol::state& lua, sol::table& core); + }; + + class LocalPlayer : public ServerPlayer { + public: + LocalPlayer(PlayerPtr player) : ServerPlayer(player) {} + + bool is_in_menu(); + + void show_menu(std::shared_ptr root); + + void close_menu(); + + std::shared_ptr get_hud(); + + void set_hud(std::shared_ptr hud); + + static void bind(State state, sol::state& lua, sol::table& core); + }; } \ No newline at end of file diff --git a/src/lua/usertype/SubgameUsertype.h b/src/lua/usertype/SubgameUsertype.h index e96cf3d3..45aa19f1 100644 --- a/src/lua/usertype/SubgameUsertype.h +++ b/src/lua/usertype/SubgameUsertype.h @@ -9,11 +9,12 @@ class State; namespace Api { - namespace Usertype { - class SubgameUsertype : public BaseUsertype { - public: - SubgameUsertype() = default; - static void bind(State state, sol::state& lua, sol::table& core) {}; - }; - } + namespace Usertype { + class SubgameUsertype : public BaseUsertype { + public: + SubgameUsertype() = default; + + static void bind(State state, sol::state& lua, sol::table& core) {}; + }; + } } \ No newline at end of file diff --git a/src/lua/usertype/Target.cpp b/src/lua/usertype/Target.cpp index 093f06a0..62cbbbae 100644 --- a/src/lua/usertype/Target.cpp +++ b/src/lua/usertype/Target.cpp @@ -6,24 +6,24 @@ #include "../Lua.h" -Api::Usertype::Target::Target(const ::Target &target) : - pos(target.pos), - type(target.type), - dim(Dimension(target.dim)), - pos_above(target.getAbovePos()) {} +Api::Usertype::Target::Target(const ::Target& target) : + pos(target.pos), + type(target.type), + dim(Dimension(target.dim)), + pos_above(target.getAbovePos()) {} std::string Api::Usertype::Target::getType() { - return type == ::Target::Type::BLOCK ? "block" : - type == ::Target::Type::ENTITY ? "entity" : - "nothing"; + return type == ::Target::Type::BLOCK ? "block" : + type == ::Target::Type::ENTITY ? "entity" : + "nothing"; } -void Api::Usertype::Target::bind(State, sol::state &lua, sol::table &core) { - lua.new_usertype("Target", - "type", sol::property(&Target::getType), - - "pos", sol::readonly(&Target::pos), - "dim", sol::readonly(&Target::dim), - "pos_above", sol::readonly(&Target::pos_above) - ); +void Api::Usertype::Target::bind(State, sol::state& lua, sol::table& core) { + lua.new_usertype("Target", + "type", sol::property(&Target::getType), + + "pos", sol::readonly(&Target::pos), + "dim", sol::readonly(&Target::dim), + "pos_above", sol::readonly(&Target::pos_above) + ); } \ No newline at end of file diff --git a/src/lua/usertype/Target.h b/src/lua/usertype/Target.h index 858e631f..94318cac 100644 --- a/src/lua/usertype/Target.h +++ b/src/lua/usertype/Target.h @@ -12,18 +12,18 @@ #include "util/Target.h" namespace Api::Usertype { - class Target : public SubgameUsertype { - public: - Target(const ::Target& target); - - std::string getType(); - - ::Target::Type type; - - Dimension dim; - glm::ivec3 pos; - glm::ivec3 pos_above; - - static void bind(State state, sol::state& lua, sol::table& core); - }; + class Target : public SubgameUsertype { + public: + Target(const ::Target& target); + + std::string getType(); + + ::Target::Type type; + + Dimension dim; + glm::ivec3 pos; + glm::ivec3 pos_above; + + static void bind(State state, sol::state& lua, sol::table& core); + }; } diff --git a/src/server/Server.cpp b/src/server/Server.cpp index 04646122..7fa4770c 100644 --- a/src/server/Server.cpp +++ b/src/server/Server.cpp @@ -16,101 +16,102 @@ #include "world/player/ServerPlayer.h" Server::Server(unsigned short port, const std::string& subgame) : - seed(69), - port(port), - config(game), - clients(game), - handler(port, 32), - game(std::make_shared(subgame, seed)), - world(std::make_shared(seed, game, clients)) { - - game.s()->init(world); - world.s()->init("world"); - config.init(); - - std::cout << Log::info << "Server started successfully, listening for clients." << Log::endl; - while (alive) update(); + seed(69), + port(port), + config(game), + clients(game), + handler(port, 32), + game(std::make_shared(subgame, seed)), + world(std::make_shared(seed, game, clients)) { + + game.s()->init(world); + world.s()->init("world"); + config.init(); + + std::cout << Log::info << "Server started successfully, listening for clients." << Log::endl; + while (alive) update(); } void Server::update() { - const static long interval_ns = static_cast((1000 / 60.f) * 1000000L); - Timer loop(""); - - world->update(delta); - game.s()->update(delta); - - ENetEvent event; - while (handler.update(&event) && loop.elapsedNs() < interval_ns) { - switch (event.type) { - default: - case ENET_EVENT_TYPE_NONE: - throw std::runtime_error("Unknown packet type " + std::to_string(event.type) + " received."); break; - - case ENET_EVENT_TYPE_CONNECT: - clients.handleConnect(event); break; - - case ENET_EVENT_TYPE_DISCONNECT: - clients.handleDisconnect(event); break; - - case ENET_EVENT_TYPE_RECEIVE: - packetReceived(event); break; - } - } - - for (auto& id : playersUpdated) { - auto player = clients.getPlayer(id); - if (!player) continue; - - Packet p = Serializer() - .appendE(NetField::ID).append(player->getId()) - .appendE(NetField::POS).append(player->getPos()) - .appendE(NetField::LOOK_YAW).append(player->getYaw()) - .appendE(NetField::LOOK_PITCH).append(player->getPitch()) - .packet(Packet::Type::PLAYER_ENT_INFO, false); - - for (auto& iter : clients.players) - if (iter->getId() != id && glm::distance(player->getPos(), iter->getPos()) < 200) - p.sendTo(iter->getPeer(), Packet::Channel::ENTITY); - } - - playersUpdated.clear(); - - long sleep_for = interval_ns - loop.elapsedNs(); - if (sleep_for > 0) std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_for)); - - delta = loop.elapsedNs() / 1000000.f / 1000.f; - elapsed += delta; + const static long interval_ns = static_cast((1000 / 60.f) * 1000000L); + Timer loop(""); + + world->update(delta); + game.s()->update(delta); + + ENetEvent event; + while (handler.update(&event) && loop.elapsedNs() < interval_ns) { + switch (event.type) { + default: + case ENET_EVENT_TYPE_NONE: + throw std::runtime_error("Unknown packet type " + std::to_string(event.type) + " received."); + break; + + case ENET_EVENT_TYPE_CONNECT:clients.handleConnect(event); + break; + + case ENET_EVENT_TYPE_DISCONNECT:clients.handleDisconnect(event); + break; + + case ENET_EVENT_TYPE_RECEIVE:packetReceived(event); + break; + } + } + + for (auto& id : playersUpdated) { + auto player = clients.getPlayer(id); + if (!player) continue; + + Packet p = Serializer() + .appendE(NetField::ID).append(player->getId()) + .appendE(NetField::POS).append(player->getPos()) + .appendE(NetField::LOOK_YAW).append(player->getYaw()) + .appendE(NetField::LOOK_PITCH).append(player->getPitch()) + .packet(Packet::Type::PLAYER_ENT_INFO, false); + + for (auto& iter : clients.players) + if (iter->getId() != id && glm::distance(player->getPos(), iter->getPos()) < 200) + p.sendTo(iter->getPeer(), Packet::Channel::ENTITY); + } + + playersUpdated.clear(); + + long sleep_for = interval_ns - loop.elapsedNs(); + if (sleep_for > 0) std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_for)); + + delta = loop.elapsedNs() / 1000000.f / 1000.f; + elapsed += delta; } void Server::packetReceived(ENetEvent& e) { - PacketView p(e.packet); - auto client = static_cast(e.peer->data); - auto player = PlayerPtr(clients.getPlayer(client->id)); - - // Handle the packet as a player and then return. - if (client->player) return playerPacketReceived(p, player); - - // Function returns true if a player is to be created. - if (config.handlePacket(*client, p)) { - auto clientShared = clients.getClient(client->id); - if (clientShared) clients.createPlayer(clientShared, world->getDefaultDimension()); - } + PacketView p(e.packet); + auto client = static_cast(e.peer->data); + auto player = PlayerPtr(clients.getPlayer(client->id)); + + // Handle the packet as a player and then return. + if (client->player) return playerPacketReceived(p, player); + + // Function returns true if a player is to be created. + if (config.handlePacket(*client, p)) { + auto clientShared = clients.getClient(client->id); + if (clientShared) clients.createPlayer(clientShared, world->getDefaultDimension()); + } } void Server::playerPacketReceived(PacketView& p, PlayerPtr player) { - // Pre-initialization because switch statements suck. - glm::ivec3 pos; - EVec face = EVec::NONE; - std::string source, list; - unsigned short a, ind; - - switch (p.type) { - default: - throw std::runtime_error("Unknown packet type " + std::to_string(static_cast(p.type)) + " received."); break; - - case Packet::Type::THIS_PLAYER_INFO: - player->handleAssertion(p.d); - playersUpdated.emplace(player->getId()); break; + // Pre-initialization because switch statements suck. + glm::ivec3 pos; + EVec face = EVec::NONE; + std::string source, list; + unsigned short a, ind; + + switch (p.type) { + default:throw std::runtime_error("Unknown packet type " + std::to_string(static_cast(p.type)) + " received."); + break; + + case Packet::Type::THIS_PLAYER_INFO:player->handleAssertion(p.d); + playersUpdated.emplace(player->getId()); + break; // case Packet::Type::BLOCK_SET: // glm::ivec3 pos = p.d.read(); @@ -144,45 +145,46 @@ void Server::playerPacketReceived(PacketView& p, PlayerPtr player) { // game.lua->safe_function(game.lua->core["trigger"], "after_place", pos, ServerLuaPlayer(client)); // } // break; } - - case Packet::Type::BLOCK_HIT: - p.d.read(pos).readE(face); - player->getDim()->blockHit(Target(player->getDim(), pos, face), player); break; - - case Packet::Type::BLOCK_PLACE: - p.d.read(pos).readE(face); - player->getDim()->blockPlace(Target(player->getDim(), pos, face), player); break; - - case Packet::Type::BLOCK_INTERACT: - p.d.read(pos).readE(face); - player->getDim()->blockInteract(Target(player->getDim(), pos, face), player); break; - - case Packet::Type::BLOCK_PLACE_OR_INTERACT: - p.d.read(pos).readE(face); - player->getDim()->blockPlaceOrInteract(Target(player->getDim(), pos, face), player); break; - - case Packet::Type::INV_WATCH: - p.d.read(source).read(list); - if (!world->getRefs().s()->addWatcher(source, list, player->getId())) - Serializer().append(source).append(list).packet(Packet::Type::INV_INVALID) - .sendTo(player.s()->getPeer(), Packet::Channel::INTERACT); break; - - case Packet::Type::INV_UNWATCH: - p.d.read(source).read(list); - if (!world->getRefs().s()->removeWatcher(source, list, player->getId())) - Serializer().append(source).append(list).packet(Packet::Type::INV_INVALID) - .sendTo(player.s()->getPeer(), Packet::Channel::INTERACT); break; - - case Packet::Type::INV_INTERACT: - p.d.read(a).read(source).read(list).read(ind); - world->getRefs().s()->interact(a, source, list, ind, player->getId()); break; - } + + case Packet::Type::BLOCK_HIT:p.d.read(pos).readE(face); + player->getDim()->blockHit(Target(player->getDim(), pos, face), player); + break; + + case Packet::Type::BLOCK_PLACE:p.d.read(pos).readE(face); + player->getDim()->blockPlace(Target(player->getDim(), pos, face), player); + break; + + case Packet::Type::BLOCK_INTERACT:p.d.read(pos).readE(face); + player->getDim()->blockInteract(Target(player->getDim(), pos, face), player); + break; + + case Packet::Type::BLOCK_PLACE_OR_INTERACT:p.d.read(pos).readE(face); + player->getDim()->blockPlaceOrInteract(Target(player->getDim(), pos, face), player); + break; + + case Packet::Type::INV_WATCH:p.d.read(source).read(list); + if (!world->getRefs().s()->addWatcher(source, list, player->getId())) + Serializer().append(source).append(list).packet(Packet::Type::INV_INVALID) + .sendTo(player.s()->getPeer(), Packet::Channel::INTERACT); + break; + + case Packet::Type::INV_UNWATCH:p.d.read(source).read(list); + if (!world->getRefs().s()->removeWatcher(source, list, player->getId())) + Serializer().append(source).append(list).packet(Packet::Type::INV_INVALID) + .sendTo(player.s()->getPeer(), Packet::Channel::INTERACT); + break; + + case Packet::Type::INV_INTERACT: + p.d.read(a).read(source).read(list).read(ind); + world->getRefs().s()->interact(a, source, list, ind, player->getId()); + break; + } } void Server::cleanup() { - alive = false; + alive = false; } Server::~Server() { - cleanup(); + cleanup(); } \ No newline at end of file diff --git a/src/server/Server.h b/src/server/Server.h index f7fdb13f..91aa6eb3 100644 --- a/src/server/Server.h +++ b/src/server/Server.h @@ -12,34 +12,38 @@ #include "world/inv/ServerInventoryRefs.h" class ServerPlayer; + class Packet; class Server { -public: - explicit Server(unsigned short port, const std::string& subgame); - - void update(); - - void cleanup(); - ~Server(); -private: - void packetReceived(ENetEvent& e); - void playerPacketReceived(PacketView& p, PlayerPtr player); - - unsigned short port = 0; - unsigned int seed = 0; - - SubgamePtr game; - ServerClients clients; - WorldPtr world; - NetHandler handler; - ServerConfig config; - - std::unordered_set playersUpdated {}; - - double elapsed = 0; - double delta = 0; - - bool alive = true; + public: + explicit Server(unsigned short port, const std::string& subgame); + + void update(); + + void cleanup(); + + ~Server(); + + private: + void packetReceived(ENetEvent& e); + + void playerPacketReceived(PacketView& p, PlayerPtr player); + + unsigned short port = 0; + unsigned int seed = 0; + + SubgamePtr game; + ServerClients clients; + WorldPtr world; + NetHandler handler; + ServerConfig config; + + std::unordered_set playersUpdated{}; + + double elapsed = 0; + double delta = 0; + + bool alive = true; }; diff --git a/src/server/ServerClient.h b/src/server/ServerClient.h index a807974e..23634879 100644 --- a/src/server/ServerClient.h +++ b/src/server/ServerClient.h @@ -11,15 +11,15 @@ class ServerPlayer; class ServerClient { -public: - ServerClient(const std::string& username, ENetPeer* peer) : - username(username), peer(peer), address(peer->address), id(peer->connectID) {} - - std::string username; - unsigned int id = 0; - - ENetPeer* peer; - ENetAddress address; - - std::shared_ptr player = nullptr; + public: + ServerClient(const std::string& username, ENetPeer* peer) : + username(username), peer(peer), address(peer->address), id(peer->connectID) {} + + std::string username; + unsigned int id = 0; + + ENetPeer* peer; + ENetAddress address; + + std::shared_ptr player = nullptr; }; diff --git a/src/server/ServerClients.cpp b/src/server/ServerClients.cpp index 24487f03..54c42cf7 100644 --- a/src/server/ServerClients.cpp +++ b/src/server/ServerClients.cpp @@ -14,65 +14,68 @@ #include "world/player/ServerPlayer.h" ServerClients::ServerClients(SubgamePtr game) : - game(game) {} + game(game) {} -void ServerClients::init(ServerWorld *world) { - this->world = world; +void ServerClients::init(ServerWorld* world) { + this->world = world; } void ServerClients::handleConnect(ENetEvent e) { - auto client = std::make_shared("TEMPORARY", e.peer); - client->peer->data = client.get(); - clients.push_back(client); - - std::cout << Log::info << NetHandler::intToIPString(client->address.host) - << ":" << client->address.port << " connected." << Log::endl; + auto client = std::make_shared("TEMPORARY", e.peer); + client->peer->data = client.get(); + clients.push_back(client); + + std::cout << Log::info << NetHandler::intToIPString(client->address.host) + << ":" << client->address.port << " connected." << Log::endl; } void ServerClients::handleDisconnect(ENetEvent e) { - unsigned int id = static_cast(e.peer->data)->id; - - ENetAddress& addr = e.peer->address; - std::cout << Log::info << NetHandler::intToIPString(addr.host) << ":" << addr.port << " disconnected." << Log::endl; - - // Disconnect the player, if it exists. - for (auto it = players.begin(); it != players.end();) { - if ((*it)->getId() == id) { - game.s()->getParser().playerDisconnected(*it); - players.erase(it); - break; - } - } - - for (auto it = clients.begin(); it != clients.end();) { - if ((*it)->id == id) { clients.erase(it); break; } - } + unsigned int id = static_cast(e.peer->data)->id; + + ENetAddress& addr = e.peer->address; + std::cout << Log::info << NetHandler::intToIPString(addr.host) << ":" << addr.port << " disconnected." << Log::endl; + + // Disconnect the player, if it exists. + for (auto it = players.begin(); it != players.end();) { + if ((*it)->getId() == id) { + game.s()->getParser().playerDisconnected(*it); + players.erase(it); + break; + } + } + + for (auto it = clients.begin(); it != clients.end();) { + if ((*it)->id == id) { + clients.erase(it); + break; + } + } } void ServerClients::createPlayer(std::shared_ptr client, DimensionPtr dimension) { - auto player = std::make_shared(*client, dimension->getWorld(), game, dimension); - player->getInventory()->createList("cursor", 1, 1); - client->player = player; - players.push_back(player); - game.s()->getParser().playerConnected(player); - - player->setPos({0, -37, 0}, true); - - Serializer() - .appendE(NetField::ID).append(player->getId()) - .appendE(NetField::POS).append(player->getPos()) - .appendE(NetField::LOOK_PITCH).append(player->getPitch()) - .appendE(NetField::LOOK_YAW).append(player->getYaw()) - .packet(Packet::Type::THIS_PLAYER_INFO).sendTo(player->getPeer(), Packet::Channel::INTERACT); + auto player = std::make_shared(*client, dimension->getWorld(), game, dimension); + player->getInventory()->createList("cursor", 1, 1); + client->player = player; + players.push_back(player); + game.s()->getParser().playerConnected(player); + + player->setPos({ 0, -37, 0 }, true); + + Serializer() + .appendE(NetField::ID).append(player->getId()) + .appendE(NetField::POS).append(player->getPos()) + .appendE(NetField::LOOK_PITCH).append(player->getPitch()) + .appendE(NetField::LOOK_YAW).append(player->getYaw()) + .packet(Packet::Type::THIS_PLAYER_INFO).sendTo(player->getPeer(), Packet::Channel::INTERACT); } const std::shared_ptr ServerClients::getClient(unsigned int id) const { - for (auto& c : clients) if (c->id == id) return c; - return nullptr; + for (auto& c : clients) if (c->id == id) return c; + return nullptr; } const std::shared_ptr ServerClients::getPlayer(unsigned int id) const { - for (auto& c : players) if (c->getId() == id) return c; - return nullptr; + for (auto& c : players) if (c->getId() == id) return c; + return nullptr; } diff --git a/src/server/ServerClients.h b/src/server/ServerClients.h index 72779bab..9271f1da 100644 --- a/src/server/ServerClients.h +++ b/src/server/ServerClients.h @@ -11,27 +11,35 @@ #include "util/CovariantPtr.h" class ServerWorld; + class ServerClient; + class ServerPlayer; + class ServerSubgame; + class ServerDimension; class ServerClients { -public: - explicit ServerClients(SubgamePtr game); - void init(ServerWorld* world); - - void handleConnect(ENetEvent e); - void handleDisconnect(ENetEvent e); - - void createPlayer(std::shared_ptr client, DimensionPtr dimension); - const std::shared_ptr getClient(unsigned int id) const; - const std::shared_ptr getPlayer(unsigned int id) const; - - std::list> clients; - std::list> players; - -private: - SubgamePtr game; - ServerWorld* world = nullptr; + public: + explicit ServerClients(SubgamePtr game); + + void init(ServerWorld* world); + + void handleConnect(ENetEvent e); + + void handleDisconnect(ENetEvent e); + + void createPlayer(std::shared_ptr client, DimensionPtr dimension); + + const std::shared_ptr getClient(unsigned int id) const; + + const std::shared_ptr getPlayer(unsigned int id) const; + + std::list> clients; + std::list> players; + + private: + SubgamePtr game; + ServerWorld* world = nullptr; }; diff --git a/src/server/ServerConfig.cpp b/src/server/ServerConfig.cpp index 1e8b2437..eb7ef36e 100644 --- a/src/server/ServerConfig.cpp +++ b/src/server/ServerConfig.cpp @@ -15,109 +15,108 @@ ServerConfig::ServerConfig(SubgamePtr game) : game(game) {} void ServerConfig::init() { - blockIdentifierList.reserve(static_cast(game->getDefs().size())); - for (unsigned int i = 0; i < game->getDefs().size(); i++) { - blockIdentifierList.push_back(game->getDefs().fromId(i).identifier); - } - - biomeIdentifierList.reserve(static_cast(game->getBiomes().size())); - for (unsigned int i = 0; i < game->getBiomes().size(); i++) { - biomeIdentifierList.push_back(game->getBiomes().biomeFromId(i).identifier); - } + blockIdentifierList.reserve(static_cast(game->getDefs().size())); + for (unsigned int i = 0; i < game->getDefs().size(); i++) { + blockIdentifierList.push_back(game->getDefs().fromId(i).identifier); + } + + biomeIdentifierList.reserve(static_cast(game->getBiomes().size())); + for (unsigned int i = 0; i < game->getBiomes().size(); i++) { + biomeIdentifierList.push_back(game->getBiomes().biomeFromId(i).identifier); + } } bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) { - switch (r.type) { - default: break; - case Packet::Type::CONNECT_DATA_RECVD: - return true; - - case Packet::Type::SERVER_INFO: { - Serializer() - .append(game.s()->getBiomes().seed) - .packet(Packet::Type::SERVER_INFO) - .sendTo(client.peer, Packet::Channel::CONNECT); - break; - } - - case Packet::Type::BLOCK_IDENTIFIER_LIST: { - Serializer() - .append(blockIdentifierList) - .packet(Packet::Type::BLOCK_IDENTIFIER_LIST) - .sendTo(client.peer, Packet::Channel::CONNECT); - break; - } - - case Packet::Type::BIOME_IDENTIFIER_LIST: { - Serializer() - .append(biomeIdentifierList) - .packet(Packet::Type::BIOME_IDENTIFIER_LIST) - .sendTo(client.peer, Packet::Channel::CONNECT); - break; - } - - case Packet::Type::MODS: { - game.s()->getParser().sendModsPacket(client.peer); - break; - } - - case Packet::Type::MEDIA: { - const unsigned int MAX_PACKET_SIZE = 32*1024; - unsigned int packetSize = 0; - - Serializer s {}; - - for (ServerTexture& texture : game.s()->assets.textures) { - if (packetSize + 20 + texture.data.length() > MAX_PACKET_SIZE && packetSize != 0) { - s.append(static_cast(AssetType::END)); - Packet p(Packet::Type::MEDIA); - - p.data = s.data; - packetSize = 0; - s = {}; - - p.sendTo(client.peer, Packet::Channel::CONNECT); - } - - s.append(static_cast(AssetType::TEXTURE)) - .append(texture.name) - .append(texture.width) - .append(texture.height) - .append(texture.data); - - packetSize += texture.data.length() + 20; - } - - for (SerializedModel& model : game.s()->assets.models) { - if (packetSize + 16 + model.data.length() > MAX_PACKET_SIZE && packetSize != 0) { - s.append(static_cast(AssetType::END)); - Packet p(Packet::Type::MEDIA); - - p.data = s.data; - packetSize = 0; - s = {}; - - p.sendTo(client.peer, Packet::Channel::CONNECT); - } - - s.append(static_cast(AssetType::MODEL)) - .append(model.name) - .append(model.format) - .append(model.data); - - packetSize += model.data.length() + 16; - } - - s.append(static_cast(AssetType::END)); - Packet p(Packet::Type::MEDIA); - p.data = s.data; - - p.sendTo(client.peer, Packet::Channel::CONNECT); - - Packet d(Packet::Type::MEDIA_DONE); - d.sendTo(client.peer, Packet::Channel::CONNECT); - } - } - - return false; + switch (r.type) { + default: break; + case Packet::Type::CONNECT_DATA_RECVD:return true; + + case Packet::Type::SERVER_INFO: { + Serializer() + .append(game.s()->getBiomes().seed) + .packet(Packet::Type::SERVER_INFO) + .sendTo(client.peer, Packet::Channel::CONNECT); + break; + } + + case Packet::Type::BLOCK_IDENTIFIER_LIST: { + Serializer() + .append(blockIdentifierList) + .packet(Packet::Type::BLOCK_IDENTIFIER_LIST) + .sendTo(client.peer, Packet::Channel::CONNECT); + break; + } + + case Packet::Type::BIOME_IDENTIFIER_LIST: { + Serializer() + .append(biomeIdentifierList) + .packet(Packet::Type::BIOME_IDENTIFIER_LIST) + .sendTo(client.peer, Packet::Channel::CONNECT); + break; + } + + case Packet::Type::MODS: { + game.s()->getParser().sendModsPacket(client.peer); + break; + } + + case Packet::Type::MEDIA: { + const unsigned int MAX_PACKET_SIZE = 32 * 1024; + unsigned int packetSize = 0; + + Serializer s{}; + + for (ServerTexture& texture : game.s()->assets.textures) { + if (packetSize + 20 + texture.data.length() > MAX_PACKET_SIZE && packetSize != 0) { + s.append(static_cast(AssetType::END)); + Packet p(Packet::Type::MEDIA); + + p.data = s.data; + packetSize = 0; + s = {}; + + p.sendTo(client.peer, Packet::Channel::CONNECT); + } + + s.append(static_cast(AssetType::TEXTURE)) + .append(texture.name) + .append(texture.width) + .append(texture.height) + .append(texture.data); + + packetSize += texture.data.length() + 20; + } + + for (SerializedModel& model : game.s()->assets.models) { + if (packetSize + 16 + model.data.length() > MAX_PACKET_SIZE && packetSize != 0) { + s.append(static_cast(AssetType::END)); + Packet p(Packet::Type::MEDIA); + + p.data = s.data; + packetSize = 0; + s = {}; + + p.sendTo(client.peer, Packet::Channel::CONNECT); + } + + s.append(static_cast(AssetType::MODEL)) + .append(model.name) + .append(model.format) + .append(model.data); + + packetSize += model.data.length() + 16; + } + + s.append(static_cast(AssetType::END)); + Packet p(Packet::Type::MEDIA); + p.data = s.data; + + p.sendTo(client.peer, Packet::Channel::CONNECT); + + Packet d(Packet::Type::MEDIA_DONE); + d.sendTo(client.peer, Packet::Channel::CONNECT); + } + } + + return false; } diff --git a/src/server/ServerConfig.h b/src/server/ServerConfig.h index 3258c270..3d7c6dd4 100644 --- a/src/server/ServerConfig.h +++ b/src/server/ServerConfig.h @@ -8,19 +8,22 @@ #include "util/net/PacketView.h" class PacketView; + class ServerClient; + class ServerSubgame; class ServerConfig { -public: - explicit ServerConfig(SubgamePtr game); - - void init(); - - //Bool: Create player - bool handlePacket(ServerClient& client, PacketView& p); -private: - SubgamePtr game; - std::vector blockIdentifierList {}; - std::vector biomeIdentifierList {}; + public: + explicit ServerConfig(SubgamePtr game); + + void init(); + + //Bool: Create player + bool handlePacket(ServerClient& client, PacketView& p); + + private: + SubgamePtr game; + std::vector blockIdentifierList{}; + std::vector biomeIdentifierList{}; }; diff --git a/src/server/stream/ServerGenStream.cpp b/src/server/stream/ServerGenStream.cpp index c182f5cc..7a28e9e8 100644 --- a/src/server/stream/ServerGenStream.cpp +++ b/src/server/stream/ServerGenStream.cpp @@ -9,67 +9,67 @@ #include "world/dim/chunk/Chunk.h" ServerGenStream::ServerGenStream(ServerSubgame& game, ServerWorld& world, unsigned int seed) : - world(world) { - threads.reserve(THREADS); - for (int i = 0; i < THREADS; i++) threads.emplace_back(game, world, seed); + world(world) { + threads.reserve(THREADS); + for (int i = 0; i < THREADS; i++) threads.emplace_back(game, world, seed); } bool ServerGenStream::queue(unsigned int dimension, glm::ivec3 pos) { - auto v4 = glm::ivec4(pos, dimension); - if (!queuedMap.count(v4)) { - queuedTasks.push(v4); - queuedMap.insert(v4); - return true; - } - return false; + auto v4 = glm::ivec4(pos, dimension); + if (!queuedMap.count(v4)) { + queuedTasks.push(v4); + queuedMap.insert(v4); + return true; + } + return false; } std::unique_ptr> ServerGenStream::update() { - auto created = std::make_unique>(); - - for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { - for (auto& t : threads) { - auto& j = t.jobs[i]; - if (j.locked) continue; - - if (j.created) created->push_back({j.pos, j.dim, std::move(j.created)}); - - if (!queuedTasks.empty()) { - auto pos = queuedTasks.front(); - queuedMap.erase(pos); - queuedTasks.pop(); - - j.pos = glm::ivec3(pos); - j.gen = world.getDimension(pos.w)->getGen(); - j.dim = pos.w; - j.locked = true; - } - } - } - - return created; + auto created = std::make_unique>(); + + for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { + for (auto& t : threads) { + auto& j = t.jobs[i]; + if (j.locked) continue; + + if (j.created) created->push_back({ j.pos, j.dim, std::move(j.created) }); + + if (!queuedTasks.empty()) { + auto pos = queuedTasks.front(); + queuedMap.erase(pos); + queuedTasks.pop(); + + j.pos = glm::ivec3(pos); + j.gen = world.getDimension(pos.w)->getGen(); + j.dim = pos.w; + j.locked = true; + } + } + } + + return created; } ServerGenStream::Thread::Thread(ServerSubgame& game, ServerWorld& world, unsigned int seed) : - thread(std::bind(&ServerGenStream::Thread::run, this)) {} + thread(std::bind(&ServerGenStream::Thread::run, this)) {} void ServerGenStream::Thread::run() { - while (!kill) { - bool empty = true; - for (Job& j : jobs) { - if (j.locked) { - empty = false; - j.created = j.gen->generateMapBlock(j.dim, j.pos); - j.locked = false; - } - } - if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + while (!kill) { + bool empty = true; + for (Job& j : jobs) { + if (j.locked) { + empty = false; + j.created = j.gen->generateMapBlock(j.dim, j.pos); + j.locked = false; + } + } + if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } ServerGenStream::~ServerGenStream() { - for (auto& t : threads) { - t.kill = true; - t.thread.join(); - } + for (auto& t : threads) { + t.kill = true; + t.thread.join(); + } } \ No newline at end of file diff --git a/src/server/stream/ServerGenStream.h b/src/server/stream/ServerGenStream.h index 01dbddd9..0da07c0e 100644 --- a/src/server/stream/ServerGenStream.h +++ b/src/server/stream/ServerGenStream.h @@ -15,44 +15,48 @@ class ServerSubgame; class ServerGenStream { -public: - static const int THREADS = 6; - static const int THREAD_QUEUE_SIZE = 6; - - struct FinishedJob { - glm::ivec3 pos; - unsigned int dim; - std::unique_ptr created; - }; - - explicit ServerGenStream(ServerSubgame& game, ServerWorld& world, unsigned int seed); - ~ServerGenStream(); - - bool queue(unsigned int dim, glm::ivec3 pos); - std::unique_ptr> update(); -private: - struct Job { - bool locked = false; - std::unique_ptr created = nullptr; - - unsigned int dim; - glm::ivec3 pos {}; - std::shared_ptr gen; - }; - - struct Thread { - explicit Thread(ServerSubgame& game, ServerWorld& world, unsigned int seed); - void run(); - - bool kill = false; - - std::vector jobs = std::vector(THREAD_QUEUE_SIZE); - - std::thread thread; - }; - - ServerWorld& world; - std::vector threads; - std::queue queuedTasks; - std::unordered_set queuedMap; + public: + static const int THREADS = 6; + static const int THREAD_QUEUE_SIZE = 6; + + struct FinishedJob { + glm::ivec3 pos; + unsigned int dim; + std::unique_ptr created; + }; + + explicit ServerGenStream(ServerSubgame& game, ServerWorld& world, unsigned int seed); + + ~ServerGenStream(); + + bool queue(unsigned int dim, glm::ivec3 pos); + + std::unique_ptr> update(); + + private: + struct Job { + bool locked = false; + std::unique_ptr created = nullptr; + + unsigned int dim; + glm::ivec3 pos{}; + std::shared_ptr gen; + }; + + struct Thread { + explicit Thread(ServerSubgame& game, ServerWorld& world, unsigned int seed); + + void run(); + + bool kill = false; + + std::vector jobs = std::vector(THREAD_QUEUE_SIZE); + + std::thread thread; + }; + + ServerWorld& world; + std::vector threads; + std::queue queuedTasks; + std::unordered_set queuedMap; }; \ No newline at end of file diff --git a/src/server/stream/ServerPacketStream.cpp b/src/server/stream/ServerPacketStream.cpp index 3e709883..1af4ae90 100644 --- a/src/server/stream/ServerPacketStream.cpp +++ b/src/server/stream/ServerPacketStream.cpp @@ -11,80 +11,80 @@ #include "world/dim/chunk/Chunk.h" ServerPacketStream::ServerPacketStream(ServerWorld& world) { - threads.reserve(THREADS); - for (int i = 0; i < THREADS; i++) threads.emplace_back(world); + threads.reserve(THREADS); + for (int i = 0; i < THREADS; i++) threads.emplace_back(world); } bool ServerPacketStream::queue(unsigned int dim, glm::ivec3 pos) { - auto v4 = glm::ivec4(pos, dim); - if (!queuedMap.count(v4)) { - queuedTasks.push(v4); - queuedMap.insert(v4); - return true; - } - return false; + auto v4 = glm::ivec4(pos, dim); + if (!queuedMap.count(v4)) { + queuedTasks.push(v4); + queuedMap.insert(v4); + return true; + } + return false; } ServerPacketStream::Thread::Thread(ServerWorld& world) : - world(world), thread(std::bind(&ServerPacketStream::Thread::run, this)) {} + world(world), thread(std::bind(&ServerPacketStream::Thread::run, this)) {} std::unique_ptr>> ServerPacketStream::update() { - auto finished = std::make_unique>>(); - - for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { - for (auto& t : threads) { - auto& j = t.jobs[i]; - if (j.locked) continue; - - if (j.packet) finished->emplace_back(std::make_unique(j.pos, j.dim, std::move(j.packet))); - - if (!queuedTasks.empty()) { - auto pos = queuedTasks.front(); - queuedMap.erase(pos); - queuedTasks.pop(); - - j.pos = glm::vec3(pos); - j.dim = pos.w; - j.locked = true; - } - } - } - - return finished; + auto finished = std::make_unique>>(); + + for (unsigned int i = 0; i < THREAD_QUEUE_SIZE; i++) { + for (auto& t : threads) { + auto& j = t.jobs[i]; + if (j.locked) continue; + + if (j.packet) finished->emplace_back(std::make_unique(j.pos, j.dim, std::move(j.packet))); + + if (!queuedTasks.empty()) { + auto pos = queuedTasks.front(); + queuedMap.erase(pos); + queuedTasks.pop(); + + j.pos = glm::vec3(pos); + j.dim = pos.w; + j.locked = true; + } + } + } + + return finished; } void ServerPacketStream::Thread::run() { - while (!kill) { - bool empty = true; - for (Job& j : jobs) { - if (j.locked) { - empty = false; - - auto mapBlock = world.getDimension(j.dim)->getMapBlock(j.pos); - if (!mapBlock) { - j.locked = false; - continue; - } - - Serializer s {}; - for (unsigned int i = 0; i < 64; i++) { - auto chunk = mapBlock->get(i); - if (chunk) s.append(chunk->serialize()); - } - - j.packet = std::make_unique(Packet::Type::MAPBLOCK); - j.packet->data = s.data; - j.locked = false; - } - } - if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + while (!kill) { + bool empty = true; + for (Job& j : jobs) { + if (j.locked) { + empty = false; + + auto mapBlock = world.getDimension(j.dim)->getMapBlock(j.pos); + if (!mapBlock) { + j.locked = false; + continue; + } + + Serializer s{}; + for (unsigned int i = 0; i < 64; i++) { + auto chunk = mapBlock->get(i); + if (chunk) s.append(chunk->serialize()); + } + + j.packet = std::make_unique(Packet::Type::MAPBLOCK); + j.packet->data = s.data; + j.locked = false; + } + } + if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } ServerPacketStream::~ServerPacketStream() { - for (auto& t : threads) { - t.kill = true; - t.thread.join(); - } + for (auto& t : threads) { + t.kill = true; + t.thread.join(); + } } \ No newline at end of file diff --git a/src/server/stream/ServerPacketStream.h b/src/server/stream/ServerPacketStream.h index f8cb225c..c004837c 100644 --- a/src/server/stream/ServerPacketStream.h +++ b/src/server/stream/ServerPacketStream.h @@ -16,46 +16,49 @@ class ServerWorld; class ServerPacketStream { -public: - static const int THREADS = 4; - static const int THREAD_QUEUE_SIZE = 64; - - struct FinishedJob { - FinishedJob(glm::ivec3 pos, unsigned int dim, std::unique_ptr packet) : - pos(pos), dim(dim), packet(std::move(packet)) {} - - glm::ivec3 pos; - unsigned int dim; - std::unique_ptr packet; - }; - - ServerPacketStream(ServerWorld& world); - - bool queue(unsigned int dim, glm::ivec3 pos); - std::unique_ptr>> update(); - - ~ServerPacketStream(); -private: - struct Job { - bool locked = false; - glm::ivec3 pos {}; - unsigned int dim; - std::unique_ptr packet = nullptr; - }; - - struct Thread { - Thread(ServerWorld& world); - void run(); - - bool kill = false; - - std::vector jobs = std::vector(THREAD_QUEUE_SIZE); - - ServerWorld& world; - std::thread thread; - }; - - std::vector threads; - std::queue queuedTasks; - std::unordered_set queuedMap; + public: + static const int THREADS = 4; + static const int THREAD_QUEUE_SIZE = 64; + + struct FinishedJob { + FinishedJob(glm::ivec3 pos, unsigned int dim, std::unique_ptr packet) : + pos(pos), dim(dim), packet(std::move(packet)) {} + + glm::ivec3 pos; + unsigned int dim; + std::unique_ptr packet; + }; + + ServerPacketStream(ServerWorld& world); + + bool queue(unsigned int dim, glm::ivec3 pos); + + std::unique_ptr>> update(); + + ~ServerPacketStream(); + + private: + struct Job { + bool locked = false; + glm::ivec3 pos{}; + unsigned int dim; + std::unique_ptr packet = nullptr; + }; + + struct Thread { + Thread(ServerWorld& world); + + void run(); + + bool kill = false; + + std::vector jobs = std::vector(THREAD_QUEUE_SIZE); + + ServerWorld& world; + std::thread thread; + }; + + std::vector threads; + std::queue queuedTasks; + std::unordered_set queuedMap; }; \ No newline at end of file diff --git a/src/util/Any.h b/src/util/Any.h index 6bb8b222..464c6bed 100644 --- a/src/util/Any.h +++ b/src/util/Any.h @@ -11,81 +11,89 @@ #include class Any { - constexpr static std::size_t STACK_SIZE = 32; -public: - template static Any from(T_&& val) { - Any a {}; - a.set(std::forward(val)); - return a; - } - - template void set(T_&& val) { - isEmpty = false; - if (sizeof(T) < STACK_SIZE) { - data.h = nullptr; - new(data.s) T(std::forward(val)); - stack_destructor = std::bind(&Any::delete_stack, this); - type = typeid(T).hash_code(); - } - else { - if (stack_destructor) stack_destructor(); - data.h = std::make_shared(std::forward(val)); - stack_destructor = nullptr; - type = typeid(T).hash_code(); - } - } - - template const T& get() const { - if (empty()) throw std::logic_error("Tried to get empty Any."); - if (type != typeid(T).hash_code()) throw std::logic_error("Any is not of type specified."); - - if (sizeof(T) < STACK_SIZE) return *reinterpret_cast(const_cast(data.s)); - else return *std::static_pointer_cast(data.h); - } - - template const T& get_or(const T& other) const noexcept { - try { return get(); } - catch (...) { return other; } - } - - template const bool is() const noexcept { - size_t hash = typeid(T).hash_code(); - return hash == type; - } - - bool const empty() const noexcept { - return isEmpty; - } - - void reset() noexcept { - if (stack_destructor) stack_destructor(); - data.h = nullptr; - isEmpty = true; - type = 0; - } - - ~Any() { + constexpr static std::size_t STACK_SIZE = 32; + public: + template + static Any from(T_&& val) { + Any a{}; + a.set(std::forward(val)); + return a; + } + + template + void set(T_&& val) { + isEmpty = false; + if (sizeof(T) < STACK_SIZE) { + data.h = nullptr; + new(data.s) T(std::forward(val)); + stack_destructor = std::bind(&Any::delete_stack, this); + type = typeid(T).hash_code(); + } + else { + if (stack_destructor) stack_destructor(); + data.h = std::make_shared(std::forward(val)); + stack_destructor = nullptr; + type = typeid(T).hash_code(); + } + } + + template + const T& get() const { + if (empty()) throw std::logic_error("Tried to get empty Any."); + if (type != typeid(T).hash_code()) throw std::logic_error("Any is not of type specified."); + + if (sizeof(T) < STACK_SIZE) return *reinterpret_cast(const_cast(data.s)); + else return *std::static_pointer_cast(data.h); + } + + template + const T& get_or(const T& other) const noexcept { + try { return get(); } + catch (...) { return other; } + } + + template + const bool is() const noexcept { + size_t hash = typeid(T).hash_code(); + return hash == type; + } + + bool const empty() const noexcept { + return isEmpty; + } + + void reset() noexcept { + if (stack_destructor) stack_destructor(); + data.h = nullptr; + isEmpty = true; + type = 0; + } + + ~Any() { // if (stack_destructor) stack_destructor(); - } - -private: - template void delete_stack() { - reinterpret_cast(data.s)->~T(); - memset(data.s, 0, STACK_SIZE); - stack_destructor = nullptr; - type = 0; - } - - bool isEmpty = true; - std::size_t type = 0; - std::function stack_destructor = nullptr; - - union Data { - alignas(16) char s[STACK_SIZE]; - std::shared_ptr h; - - Data() : h(nullptr) {} - Data(const Data& o) { memcpy(this->s, o.s, STACK_SIZE); } - ~Data() {}; - } data {}; + } + + private: + template + void delete_stack() { + reinterpret_cast(data.s)->~T(); + memset(data.s, 0, STACK_SIZE); + stack_destructor = nullptr; + type = 0; + } + + bool isEmpty = true; + std::size_t type = 0; + std::function stack_destructor = nullptr; + + union Data { + alignas(16) char s[STACK_SIZE]; + std::shared_ptr h; + + Data() : h(nullptr) {} + + Data(const Data& o) { memcpy(this->s, o.s, STACK_SIZE); } + + ~Data() {}; + } data{}; }; \ No newline at end of file diff --git a/src/util/Bounds.cpp b/src/util/Bounds.cpp index 7135ed9e..adae3408 100644 --- a/src/util/Bounds.cpp +++ b/src/util/Bounds.cpp @@ -12,7 +12,7 @@ Bounds::Bounds(glm::vec3 a, glm::vec3 b) : a(a), b(b) {} */ glm::vec3 Bounds::getA() { - return a; + return a; } @@ -22,7 +22,7 @@ glm::vec3 Bounds::getA() { */ glm::vec3 Bounds::getB() { - return b; + return b; } @@ -32,7 +32,7 @@ glm::vec3 Bounds::getB() { */ void Bounds::setA(glm::vec3 vecA) { - a = vecA; + a = vecA; } @@ -42,7 +42,7 @@ void Bounds::setA(glm::vec3 vecA) { */ void Bounds::setB(glm::vec3 vecB) { - b = vecB; + b = vecB; } @@ -53,7 +53,7 @@ void Bounds::setB(glm::vec3 vecB) { */ bool Bounds::intersects(glm::vec3 test) { - return (test.x >= a.x && test.x <= b.x - && test.y >= a.y && test.y <= b.y - && test.z >= a.z && test.z <= b.z); + return (test.x >= a.x && test.x <= b.x + && test.y >= a.y && test.y <= b.y + && test.z >= a.z && test.z <= b.z); } diff --git a/src/util/Bounds.h b/src/util/Bounds.h index 548fac04..ef64bf00 100644 --- a/src/util/Bounds.h +++ b/src/util/Bounds.h @@ -10,17 +10,21 @@ #include class Bounds { -public: - Bounds() = default; - Bounds(glm::vec3 a, glm::vec3 b); - - glm::vec3 getA(); - glm::vec3 getB(); - void setA(glm::vec3 vecA); - void setB(glm::vec3 vecB); - - bool intersects(glm::vec3 test); - -private: - glm::vec3 a, b; + public: + Bounds() = default; + + Bounds(glm::vec3 a, glm::vec3 b); + + glm::vec3 getA(); + + glm::vec3 getB(); + + void setA(glm::vec3 vecA); + + void setB(glm::vec3 vecB); + + bool intersects(glm::vec3 test); + + private: + glm::vec3 a, b; }; diff --git a/src/util/CovariantPtr.h b/src/util/CovariantPtr.h index 30096113..6b0b6a38 100644 --- a/src/util/CovariantPtr.h +++ b/src/util/CovariantPtr.h @@ -7,60 +7,91 @@ #include class World; + class LocalWorld; + class ServerWorld; class Player; + class LocalPlayer; + class ServerPlayer; class LuaEntity; + class LocalLuaEntity; + class ServerLuaEntity; class Subgame; + class LocalSubgame; + class ServerSubgame; class Dimension; + class LocalDimension; + class ServerDimension; class Inventory; + class LocalInventory; + class ServerInventory; class InventoryList; + class LocalInventoryList; + class ServerInventoryList; class InventoryRefs; + class LocalInventoryRefs; + class ServerInventoryRefs; -template +template class CovariantPtr { - std::shared_ptr b = nullptr; - -public: - CovariantPtr() = default; - CovariantPtr(std::nullptr_t) {}; - CovariantPtr(std::shared_ptr ptr) : b(ptr) {} - CovariantPtr(std::shared_ptr ptr) : b(std::dynamic_pointer_cast(ptr)) {} - CovariantPtr(std::shared_ptr ptr) : b(std::dynamic_pointer_cast(ptr)) {} - - void operator=(std::nullptr_t) { b = nullptr; } - - operator bool() { return b != nullptr; } - - std::shared_ptr operator*() { return b; } - std::shared_ptr operator->() { return b; } - - bool isL() const { return std::dynamic_pointer_cast(b) != nullptr; } - bool isS() const { return std::dynamic_pointer_cast(b) != nullptr; } - - std::shared_ptr l() { auto ptr = std::dynamic_pointer_cast(b); if (!ptr) throw std::bad_cast(); return ptr; } - std::shared_ptr s() { auto ptr = std::dynamic_pointer_cast(b); if (!ptr) throw std::bad_cast(); return ptr; } + std::shared_ptr b = nullptr; + + public: + CovariantPtr() = default; + + CovariantPtr(std::nullptr_t) {}; + + CovariantPtr(std::shared_ptr ptr) : b(ptr) {} + + CovariantPtr(std::shared_ptr ptr) : b(std::dynamic_pointer_cast(ptr)) {} + + CovariantPtr(std::shared_ptr ptr) : b(std::dynamic_pointer_cast(ptr)) {} + + void operator=(std::nullptr_t) { b = nullptr; } + + operator bool() { return b != nullptr; } + + std::shared_ptr operator*() { return b; } + + std::shared_ptr operator->() { return b; } + + bool isL() const { return std::dynamic_pointer_cast(b) != nullptr; } + + bool isS() const { return std::dynamic_pointer_cast(b) != nullptr; } + + std::shared_ptr l() { + auto ptr = std::dynamic_pointer_cast(b); + if (!ptr) throw std::bad_cast(); + return ptr; + } + + std::shared_ptr s() { + auto ptr = std::dynamic_pointer_cast(b); + if (!ptr) throw std::bad_cast(); + return ptr; + } }; typedef CovariantPtr WorldPtr; diff --git a/src/util/Interp.h b/src/util/Interp.h index 58f05320..c33176d5 100644 --- a/src/util/Interp.h +++ b/src/util/Interp.h @@ -5,24 +5,24 @@ #pragma once namespace Interp { - const constexpr inline float lerp(float p0, float p1, float factor) { - return p0 + factor * (p1 - p0); - } - - const constexpr inline float bilerp(float x0z0, float x1z0, float x0z1, float x1z1, float xfactor, float zfactor) { - const float p0 = (x0z0 + xfactor * (x1z0 - x0z0)); - return p0 + zfactor * ((x0z1 + xfactor * (x1z1 - x0z1)) - p0); - } - - const constexpr inline float trilerp( - const float p000, const float p100, const float p001, const float p101, - const float p010, const float p110, const float p011, const float p111, - const float xfactor, const float zfactor, const float yfactor) { - - const float p00 = (p000 + xfactor * (p100 - p000)); - const float p01 = (p010 + xfactor * (p110 - p010)); - const float bl = (p00 + zfactor * ((p001 + xfactor * (p101 - p001)) - p00)); - return bl + yfactor * ((p01 + zfactor * ((p011 + xfactor * (p111 - p011)) - p01)) - bl); - } + const constexpr inline float lerp(float p0, float p1, float factor) { + return p0 + factor * (p1 - p0); + } + + const constexpr inline float bilerp(float x0z0, float x1z0, float x0z1, float x1z1, float xfactor, float zfactor) { + const float p0 = (x0z0 + xfactor * (x1z0 - x0z0)); + return p0 + zfactor * ((x0z1 + xfactor * (x1z1 - x0z1)) - p0); + } + + const constexpr inline float trilerp( + const float p000, const float p100, const float p001, const float p101, + const float p010, const float p110, const float p011, const float p111, + const float xfactor, const float zfactor, const float yfactor) { + + const float p00 = (p000 + xfactor * (p100 - p000)); + const float p01 = (p010 + xfactor * (p110 - p010)); + const float bl = (p00 + zfactor * ((p001 + xfactor * (p101 - p001)) - p00)); + return bl + yfactor * ((p01 + zfactor * ((p011 + xfactor * (p111 - p011)) - p01)) - bl); + } } diff --git a/src/util/Lockable.h b/src/util/Lockable.h index 73aabd82..f7b97a6d 100644 --- a/src/util/Lockable.h +++ b/src/util/Lockable.h @@ -7,19 +7,19 @@ #include using mutex_type = std::shared_timed_mutex; -using read_lock = std::shared_lock; +using read_lock = std::shared_lock; using write_lock = std::unique_lock; class Lockable { -public: - read_lock getReadLock() const { - return read_lock {const_cast(mutex)}; - }; - - write_lock getWriteLock() { - return write_lock {mutex}; - }; - -private: - mutex_type mutex; + public: + read_lock getReadLock() const { + return read_lock{ const_cast(mutex) }; + }; + + write_lock getWriteLock() { + return write_lock{ mutex }; + }; + + private: + mutex_type mutex; }; \ No newline at end of file diff --git a/src/util/Log.h b/src/util/Log.h index 7bded8ec..50f1994b 100644 --- a/src/util/Log.h +++ b/src/util/Log.h @@ -5,29 +5,30 @@ #pragma once namespace Log { - #ifdef _WIN32 - static const char* info = "[info] "; - static const char* warn = "[warn] "; - static const char* err = "[err] "; - static const char* endl = "\n"; +#ifdef _WIN32 + static const char* info = "[info] "; + static const char* warn = "[warn] "; + static const char* err = "[err] "; + static const char* endl = "\n"; - static const char* undl = ""; - static const char* bold = ""; - static const char* unbl = ""; - static const char* red = ""; + static const char* undl = ""; + static const char* bold = ""; + static const char* unbl = ""; + static const char* red = ""; - static void clear() { auto s = system("cls"); } - #else - static const char* info = "\033[36m[info] "; - static const char* warn = "\033[31m[warn] "; - static const char* err = "\033[31m[err] "; - static const char* endl = "\033[0m\n"; + static void clear() { auto s = system("cls"); } +#else + static const char* info = "\033[36m[info] "; + static const char* warn = "\033[31m[warn] "; + static const char* err = "\033[31m[err] "; + static const char* endl = "\033[0m\n"; + + static const char* undl = "\033[4m"; + static const char* bold = "\033[1m"; + static const char* unbl = "\033[4m\033[1m"; + static const char* red = "\033[31m"; + + static void clear() { auto s = system("clear"); } - static const char* undl = "\033[4m"; - static const char* bold = "\033[1m"; - static const char* unbl = "\033[4m\033[1m"; - static const char* red = "\033[31m"; - - static void clear() { auto s = system("clear"); } - #endif +#endif } \ No newline at end of file diff --git a/src/util/Mat4Conv.h b/src/util/Mat4Conv.h index 3d4da916..ed19a294 100644 --- a/src/util/Mat4Conv.h +++ b/src/util/Mat4Conv.h @@ -9,60 +9,60 @@ #include namespace MatConv { - static inline aiMatrix4x4 GLMMat4ToAi(const glm::mat4 mat) { - return {mat[0][0], mat[0][1], mat[0][2], mat[0][3], - mat[1][0], mat[1][1], mat[1][2], mat[1][3], - mat[2][0], mat[2][1], mat[2][2], mat[2][3], - mat[3][0], mat[3][1], mat[3][2], mat[3][3]}; - } - - static inline glm::mat4 AiToGLMMat4(const aiMatrix4x4 &in_mat) { - glm::mat4 tmp; - - tmp[0][0] = in_mat.a1; - tmp[1][0] = in_mat.b1; - tmp[2][0] = in_mat.c1; - tmp[3][0] = in_mat.d1; - - tmp[0][1] = in_mat.a2; - tmp[1][1] = in_mat.b2; - tmp[2][1] = in_mat.c2; - tmp[3][1] = in_mat.d2; - - tmp[0][2] = in_mat.a3; - tmp[1][2] = in_mat.b3; - tmp[2][2] = in_mat.c3; - tmp[3][2] = in_mat.d3; - - tmp[0][3] = in_mat.a4; - tmp[1][3] = in_mat.b4; - tmp[2][3] = in_mat.c4; - tmp[3][3] = in_mat.d4; - - return tmp; - } - - static inline aiMatrix3x3 GLMMat3ToAi(const glm::mat3 mat) { - return {mat[0][0], mat[0][1], mat[0][2], - mat[1][0], mat[1][1], mat[1][2], - mat[2][0], mat[2][1], mat[2][2]}; - } - - static inline glm::mat3 AiToGLMMat3(const aiMatrix3x3 &in_mat) { - glm::mat3 tmp; - - tmp[0][0] = in_mat.a1; - tmp[1][0] = in_mat.b1; - tmp[2][0] = in_mat.c1; - - tmp[0][1] = in_mat.a2; - tmp[1][1] = in_mat.b2; - tmp[2][1] = in_mat.c2; - - tmp[0][2] = in_mat.a3; - tmp[1][2] = in_mat.b3; - tmp[2][2] = in_mat.c3; - - return tmp; - } + static inline aiMatrix4x4 GLMMat4ToAi(const glm::mat4 mat) { + return { mat[0][0], mat[0][1], mat[0][2], mat[0][3], + mat[1][0], mat[1][1], mat[1][2], mat[1][3], + mat[2][0], mat[2][1], mat[2][2], mat[2][3], + mat[3][0], mat[3][1], mat[3][2], mat[3][3] }; + } + + static inline glm::mat4 AiToGLMMat4(const aiMatrix4x4& in_mat) { + glm::mat4 tmp; + + tmp[0][0] = in_mat.a1; + tmp[1][0] = in_mat.b1; + tmp[2][0] = in_mat.c1; + tmp[3][0] = in_mat.d1; + + tmp[0][1] = in_mat.a2; + tmp[1][1] = in_mat.b2; + tmp[2][1] = in_mat.c2; + tmp[3][1] = in_mat.d2; + + tmp[0][2] = in_mat.a3; + tmp[1][2] = in_mat.b3; + tmp[2][2] = in_mat.c3; + tmp[3][2] = in_mat.d3; + + tmp[0][3] = in_mat.a4; + tmp[1][3] = in_mat.b4; + tmp[2][3] = in_mat.c4; + tmp[3][3] = in_mat.d4; + + return tmp; + } + + static inline aiMatrix3x3 GLMMat3ToAi(const glm::mat3 mat) { + return { mat[0][0], mat[0][1], mat[0][2], + mat[1][0], mat[1][1], mat[1][2], + mat[2][0], mat[2][1], mat[2][2] }; + } + + static inline glm::mat3 AiToGLMMat3(const aiMatrix3x3& in_mat) { + glm::mat3 tmp; + + tmp[0][0] = in_mat.a1; + tmp[1][0] = in_mat.b1; + tmp[2][0] = in_mat.c1; + + tmp[0][1] = in_mat.a2; + tmp[1][1] = in_mat.b2; + tmp[2][1] = in_mat.c2; + + tmp[0][2] = in_mat.a3; + tmp[1][2] = in_mat.b3; + tmp[2][2] = in_mat.c3; + + return tmp; + } } \ No newline at end of file diff --git a/src/util/RIE.h b/src/util/RIE.h index 44b9db4e..068be38a 100644 --- a/src/util/RIE.h +++ b/src/util/RIE.h @@ -9,175 +9,175 @@ #include struct RIE { - template::value>::type> - static T read(const unsigned int ind, const std::vector& data, const unsigned int dataLen) { - - if (ind >= dataLen) return 0; - - unsigned int guess = - (ind < dataLen / 4) ? 0 : - (ind < dataLen / 2) ? data.size() / 5 : - (ind < dataLen * 3/4) ? data.size() / 4 : - data.size() / 3 ; - - unsigned int atGuess = data[guess * 2]; - if (ind < atGuess) { - unsigned short tries = 0; - while (tries++ < 3) { - guess /= 2; - atGuess = data[guess * 2]; - if (ind > atGuess) break; - } - if (ind < atGuess) guess = 0; - } - - for (unsigned int i = guess * 2; i < data.size(); i += 2) { - if (data[i] > ind) return data[i - 1]; - } - - return data[data.size() - 1]; - } - - template::value>::type> - static bool write(const unsigned int ind, const T val, std::vector& data, const unsigned int dataLen) { - - // Automatically keep the vectors in sane ranges - if (data.capacity() < data.size() + 8) data.reserve(data.size() + 50); - if (data.capacity() > data.size() + 60) data.shrink_to_fit(); - - if (ind >= dataLen) return false; - if (read(ind, data, dataLen) == val) return false; - - if (ind == 0) { - if (data.size() == 0) { - data[0] = 0; - data[1] = val; - return true; - } - else if (data.size() == 2) { - data.push_back(1); - data.push_back(data[1]); - data[1] = val; - return true; - } - else if (data[2] == ind + 1) { - data[1] = val; - return true; - } - else { - data.insert(data.begin() + 2, 2, ind); - data[2] = 1; - data[3] = data[1]; - data[1] = val; - return true; - } - } - - for (unsigned int i = 0; i < data.size(); i += 2) { - if (data[i] == ind) { - // We found an index equating to the block we are going to be setting. - if (data[i - 1] == val) { - // The last block strip is the same block ID as what we are setting, - // So we should extend that strip. - if (data.size() > i + 2 && data[i + 2] == ind + 1) { - // The next block is one later, meaning we can simply remove this found block - // To cause the next strip to cascade over its position. - data.erase(data.begin() + i, data.begin() + i + 2); - return true; - } - else { - // The next strip is multiple blocks over, so just add one to our found block index. - data[i] += 1; - return true; - } - } - else { - // The last strip is not the same block. - if (data.size() > i + 2 && data[i + 2] == ind + 1) { - // There is only one of our block, so we can just update its id. - data[i + 1] = val; - return true; - } - else { - // The next strip is multiple blocks over, so we need to copy the previous block to the right - // and then set our block into its place - data.insert(data.begin() + i, 2, ind); - data[i + 1] = val; - data[i + 2] = ind + 1; - return true; - } - } - } - else if (data[i] > ind) { - // We found a strip with an index *larger* than our ind. - // We can assume the last strip is not our block, because the getBlock() catch would have caught that. - if (data[i] == ind + 1) { - if (data[i + 1] == val) { - // The next block over is the same, so we can just decrement our index by one. - data[i]--; - return true; - } - else { - // There is only one of our block to be placed, directly before our current strip - data.insert(data.begin() + i, 2, ind); - data[i + 1] = val; - return true; - } - } - else { - // The next strip is multiple blocks over, so we need to insert both our block - // *and* the previous strip's block after - data.insert(data.begin() + i, 4, ind); - data[i + 1] = val; - data[i + 2] = ind + 1; - data[i + 3] = data[i - 1]; - return true; - } - } - } - // Escaped the for loop, meaning there's no index greater than ours. - // We will insert our index at the end of the array, and insert the previous block after - // if we're not at the end of the chunk. - data.push_back(ind); - data.push_back(val); - - if (ind >= dataLen - 1) return true; // Don't add the reset if at the end of the chunk. - - data.push_back(ind + 1); - data.push_back(data[data.size() - 4]); - return true; - } - - template::value>::type> - static void expand(const std::vector& rie, std::array& expand) { - - unsigned int rieI = 0; - unsigned int i = 0; - - while (rieI * 2 < rie.size()) { - T nI = ((rieI * 2) + 2 < rie.size()) ? rie[(rieI * 2) + 2] : L; - T value = rie[(rieI * 2) + 1]; - while (i < nI) expand[i++] = value; - rieI++; - } - } - - template::value>::type> - static void encode(const std::array& array, std::vector& out) { - T len = 1; - T block = array[0]; - - for (unsigned int i = 1; i < array.size(); i++) { - T newBlock = array[i]; - if (newBlock != block) { - out.push_back(len); - out.push_back(block); - block = newBlock; - len = 0; - } - len++; - } - out.push_back(len); - out.push_back(block); - } + template::value>::type> + static T read(const unsigned int ind, const std::vector& data, const unsigned int dataLen) { + + if (ind >= dataLen) return 0; + + unsigned int guess = + (ind < dataLen / 4) ? 0 : + (ind < dataLen / 2) ? data.size() / 5 : + (ind < dataLen * 3 / 4) ? data.size() / 4 : + data.size() / 3; + + unsigned int atGuess = data[guess * 2]; + if (ind < atGuess) { + unsigned short tries = 0; + while (tries++ < 3) { + guess /= 2; + atGuess = data[guess * 2]; + if (ind > atGuess) break; + } + if (ind < atGuess) guess = 0; + } + + for (unsigned int i = guess * 2; i < data.size(); i += 2) { + if (data[i] > ind) return data[i - 1]; + } + + return data[data.size() - 1]; + } + + template::value>::type> + static bool write(const unsigned int ind, const T val, std::vector& data, const unsigned int dataLen) { + + // Automatically keep the vectors in sane ranges + if (data.capacity() < data.size() + 8) data.reserve(data.size() + 50); + if (data.capacity() > data.size() + 60) data.shrink_to_fit(); + + if (ind >= dataLen) return false; + if (read(ind, data, dataLen) == val) return false; + + if (ind == 0) { + if (data.size() == 0) { + data[0] = 0; + data[1] = val; + return true; + } + else if (data.size() == 2) { + data.push_back(1); + data.push_back(data[1]); + data[1] = val; + return true; + } + else if (data[2] == ind + 1) { + data[1] = val; + return true; + } + else { + data.insert(data.begin() + 2, 2, ind); + data[2] = 1; + data[3] = data[1]; + data[1] = val; + return true; + } + } + + for (unsigned int i = 0; i < data.size(); i += 2) { + if (data[i] == ind) { + // We found an index equating to the block we are going to be setting. + if (data[i - 1] == val) { + // The last block strip is the same block ID as what we are setting, + // So we should extend that strip. + if (data.size() > i + 2 && data[i + 2] == ind + 1) { + // The next block is one later, meaning we can simply remove this found block + // To cause the next strip to cascade over its position. + data.erase(data.begin() + i, data.begin() + i + 2); + return true; + } + else { + // The next strip is multiple blocks over, so just add one to our found block index. + data[i] += 1; + return true; + } + } + else { + // The last strip is not the same block. + if (data.size() > i + 2 && data[i + 2] == ind + 1) { + // There is only one of our block, so we can just update its id. + data[i + 1] = val; + return true; + } + else { + // The next strip is multiple blocks over, so we need to copy the previous block to the right + // and then set our block into its place + data.insert(data.begin() + i, 2, ind); + data[i + 1] = val; + data[i + 2] = ind + 1; + return true; + } + } + } + else if (data[i] > ind) { + // We found a strip with an index *larger* than our ind. + // We can assume the last strip is not our block, because the getBlock() catch would have caught that. + if (data[i] == ind + 1) { + if (data[i + 1] == val) { + // The next block over is the same, so we can just decrement our index by one. + data[i]--; + return true; + } + else { + // There is only one of our block to be placed, directly before our current strip + data.insert(data.begin() + i, 2, ind); + data[i + 1] = val; + return true; + } + } + else { + // The next strip is multiple blocks over, so we need to insert both our block + // *and* the previous strip's block after + data.insert(data.begin() + i, 4, ind); + data[i + 1] = val; + data[i + 2] = ind + 1; + data[i + 3] = data[i - 1]; + return true; + } + } + } + // Escaped the for loop, meaning there's no index greater than ours. + // We will insert our index at the end of the array, and insert the previous block after + // if we're not at the end of the chunk. + data.push_back(ind); + data.push_back(val); + + if (ind >= dataLen - 1) return true; // Don't add the reset if at the end of the chunk. + + data.push_back(ind + 1); + data.push_back(data[data.size() - 4]); + return true; + } + + template::value>::type> + static void expand(const std::vector& rie, std::array& expand) { + + unsigned int rieI = 0; + unsigned int i = 0; + + while (rieI * 2 < rie.size()) { + T nI = ((rieI * 2) + 2 < rie.size()) ? rie[(rieI * 2) + 2] : L; + T value = rie[(rieI * 2) + 1]; + while (i < nI) expand[i++] = value; + rieI++; + } + } + + template::value>::type> + static void encode(const std::array& array, std::vector& out) { + T len = 1; + T block = array[0]; + + for (unsigned int i = 1; i < array.size(); i++) { + T newBlock = array[i]; + if (newBlock != block) { + out.push_back(len); + out.push_back(block); + block = newBlock; + len = 0; + } + len++; + } + out.push_back(len); + out.push_back(block); + } }; \ No newline at end of file diff --git a/src/util/Ray.cpp b/src/util/Ray.cpp index 426b286f..4731beb4 100644 --- a/src/util/Ray.cpp +++ b/src/util/Ray.cpp @@ -9,36 +9,36 @@ #include "world/player/LocalPlayer.h" Ray::Ray(glm::vec3 pos, float yawDeg, float pitchDeg) : - pos(pos), - start(pos) { - - float yaw = glm::radians(yawDeg + 90); - float pitch = glm::radians(pitchDeg); - - this->dir = glm::normalize(glm::vec3( - std::sin(yaw) * std::cos(pitch), std::sin(pitch), - -std::cos(yaw) * std::cos(pitch) )); + pos(pos), + start(pos) { + + float yaw = glm::radians(yawDeg + 90); + float pitch = glm::radians(pitchDeg); + + this->dir = glm::normalize(glm::vec3( + std::sin(yaw) * std::cos(pitch), std::sin(pitch), + -std::cos(yaw) * std::cos(pitch))); } Ray::Ray(Player& player) : pos(start), - start(player.getPos() + player.getLookOffset()) { - - float yaw = glm::radians(player.getYaw() + 90); - float pitch = glm::radians(player.getPitch()); - - dir = glm::normalize(glm::vec3( - std::sin(yaw) * std::cos(pitch), std::sin(pitch), - -std::cos(yaw) * std::cos(pitch) )); + start(player.getPos() + player.getLookOffset()) { + + float yaw = glm::radians(player.getYaw() + 90); + float pitch = glm::radians(player.getPitch()); + + dir = glm::normalize(glm::vec3( + std::sin(yaw) * std::cos(pitch), std::sin(pitch), + -std::cos(yaw) * std::cos(pitch))); } void Ray::step(float scale) { - pos += scale * dir; + pos += scale * dir; } glm::vec3 Ray::getEnd() { - return pos; + return pos; } float Ray::getLength() { - return glm::distance(start, pos); + return glm::distance(start, pos); } diff --git a/src/util/Ray.h b/src/util/Ray.h index 2abbcdb0..7a4a8a5a 100644 --- a/src/util/Ray.h +++ b/src/util/Ray.h @@ -10,18 +10,22 @@ class Player; class Ray { -public: - Ray() = default; - explicit Ray(Player& player); - Ray(glm::vec3 pos, float yaw, float pitch); - - void step(float scale); - glm::vec3 getEnd(); - - float getLength(); -private: - glm::vec3 start; - glm::vec3 pos; - glm::vec3 dir; + public: + Ray() = default; + + explicit Ray(Player& player); + + Ray(glm::vec3 pos, float yaw, float pitch); + + void step(float scale); + + glm::vec3 getEnd(); + + float getLength(); + + private: + glm::vec3 start; + glm::vec3 pos; + glm::vec3 dir; }; diff --git a/src/util/Schematic.cpp b/src/util/Schematic.cpp index 47d75657..24567e34 100644 --- a/src/util/Schematic.cpp +++ b/src/util/Schematic.cpp @@ -8,27 +8,27 @@ #include "game/atlas/DefinitionAtlas.h" void Schematic::process(DefinitionAtlas& atlas) { - blocks.reserve(stringData.size()); - - for (auto& string : stringData) blocks.push_back(atlas.blockFromStr(string).index); - - stringData.clear(); - stringData.shrink_to_fit(); - - processed = true; + blocks.reserve(stringData.size()); + + for (auto& string : stringData) blocks.push_back(atlas.blockFromStr(string).index); + + stringData.clear(); + stringData.shrink_to_fit(); + + processed = true; } glm::ivec3 Schematic::getOffset(unsigned int ind) { - glm::ivec3 vec {}; - - vec.z = ind / (dimensions.x * dimensions.y); - ind -= (vec.z * dimensions.x * dimensions.y); - vec.y = ind / dimensions.z; - vec.x = ind % dimensions.x; - - return vec; + glm::ivec3 vec{}; + + vec.z = ind / (dimensions.x * dimensions.y); + ind -= (vec.z * dimensions.x * dimensions.y); + vec.y = ind / dimensions.z; + vec.x = ind % dimensions.x; + + return vec; } unsigned int Schematic::index(const glm::ivec3& vec) { - return static_cast(vec.x + dimensions.x * (vec.y + dimensions.y * vec.z)); + return static_cast(vec.x + dimensions.x * (vec.y + dimensions.y * vec.z)); } \ No newline at end of file diff --git a/src/util/Schematic.h b/src/util/Schematic.h index 70db790d..ba514288 100644 --- a/src/util/Schematic.h +++ b/src/util/Schematic.h @@ -11,17 +11,18 @@ class DefinitionAtlas; struct Schematic { - std::vector stringData {}; - bool processed = false; - - std::vector blocks {}; - glm::ivec3 dimensions {}; - glm::ivec3 origin {}; - - void process(DefinitionAtlas& atlas); - - inline unsigned int length() { return blocks.size(); } - - glm::ivec3 getOffset(unsigned int ind); - unsigned int index(const glm::ivec3& vec); + std::vector stringData{}; + bool processed = false; + + std::vector blocks{}; + glm::ivec3 dimensions{}; + glm::ivec3 origin{}; + + void process(DefinitionAtlas& atlas); + + inline unsigned int length() { return blocks.size(); } + + glm::ivec3 getOffset(unsigned int ind); + + unsigned int index(const glm::ivec3& vec); }; diff --git a/src/util/Space.h b/src/util/Space.h index cb97d04b..ab8c82e2 100644 --- a/src/util/Space.h +++ b/src/util/Space.h @@ -9,189 +9,189 @@ #include namespace Space { - const static int CHUNK_SIZE = 16; - const static int MAPBLOCK_SIZE = 4; - const static int REGION_SIZE = 4; - - const static int CHUNK_BLOCK_LENGTH = CHUNK_SIZE; - const static int MAPBLOCK_BLOCK_LENGTH = CHUNK_BLOCK_LENGTH * MAPBLOCK_SIZE; - const static int REGION_BLOCK_LENGTH = MAPBLOCK_BLOCK_LENGTH * REGION_SIZE; - - const static int MAPBLOCK_CHUNK_LENGTH = MAPBLOCK_SIZE; - const static int REGION_CHUNK_LENGTH = MAPBLOCK_CHUNK_LENGTH * REGION_SIZE; - - // Private helper methods - namespace { - inline glm::ivec3 localFromGlobal(const glm::ivec3 &pos, int size) { - return glm::vec3 { - (pos.x < 0) ? size - 1 + static_cast(pos.x + 1) % size : static_cast(pos.x) % size, - (pos.y < 0) ? size - 1 + static_cast(pos.y + 1) % size : static_cast(pos.y) % size, - (pos.z < 0) ? size - 1 + static_cast(pos.z + 1) % size : static_cast(pos.z) % size - }; - } - - inline glm::ivec3 sectionFromGlobal(glm::ivec3 pos, float size) { - return { - std::floor(static_cast(pos.x) / size), - std::floor(static_cast(pos.y) / size), - std::floor(static_cast(pos.z) / size) - }; - } - } - - namespace Region { - namespace world { - // Get a Region world position from a MapBlock's world position. - static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) { - return sectionFromGlobal(pos, REGION_SIZE); - } - - // Get a Region world position from a Chunk's world position. - static inline glm::ivec3 fromChunk(const glm::ivec3& pos) { - return sectionFromGlobal(pos, REGION_CHUNK_LENGTH); - } - - // Get a Region world position from a Block's world position. - static inline glm::ivec3 fromBlock(const glm::ivec3& pos) { - return sectionFromGlobal(pos, REGION_BLOCK_LENGTH); - } - } - } - - namespace MapBlock { - namespace relative { - // Get a MapBlock's relative position in its Region from its world position. - static inline glm::ivec3 toRegion(const glm::ivec3& pos) { - return localFromGlobal(pos, MAPBLOCK_SIZE); - } - } - - namespace world { - // Get a MapBlock world position from a Region's world position. - static inline glm::ivec3 fromRegion(const glm::ivec3& pos) { - return sectionFromGlobal(pos, 1.f / REGION_SIZE); - } - - // Get a MapBlock world position from a Chunk's world position. - static inline glm::ivec3 fromChunk(const glm::ivec3 &pos) { - return sectionFromGlobal(pos, MAPBLOCK_SIZE); - } - - // Get a MapBlock world position from a Block's world position. - static inline glm::ivec3 fromBlock(const glm::ivec3 &pos) { - return sectionFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH); - } - } - - // Get the index of a MapBlock within its Region from its local or world position. - static inline unsigned int index(const glm::ivec3& vec) { - glm::ivec3 local = MapBlock::relative::toRegion(vec); - unsigned int ind = static_cast(local.x + REGION_SIZE * (local.y + REGION_SIZE * local.z)); - return ind; - } - } - - namespace Chunk { - namespace relative { - // Get a Chunk's relative position in its MapBlock from its world position. - static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) { - return localFromGlobal(pos, MAPBLOCK_CHUNK_LENGTH); - } - - // Get a Chunk's relative position in its Region from its world position. - static inline glm::ivec3 toRegion(const glm::ivec3& pos) { - return localFromGlobal(pos, REGION_CHUNK_LENGTH); - } - } - - namespace world { - // Get a Chunk world position from a Regions's world position. - static inline glm::ivec3 fromRegion(const glm::ivec3& pos) { - return sectionFromGlobal(pos, 1.f / REGION_CHUNK_LENGTH); - } - - // Get a Chunk world position from a MapBlock's world position. - static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) { - return sectionFromGlobal(pos, 1.f / MAPBLOCK_CHUNK_LENGTH); - } - - // Get a Chunk world position from a Block's world position. - static inline glm::ivec3 fromBlock(const glm::ivec3& pos) { - return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH); - } - } - - // Get the index of a Chunk within its MapBlock from its local or world position. - static inline unsigned int index(const glm::ivec3& vec) { - glm::ivec3 local = Chunk::relative::toMapBlock(vec); - return static_cast(local.x + MAPBLOCK_SIZE * (local.z + MAPBLOCK_SIZE * local.y)); - } - - // Return a local vector of an chunk within its mapblock. - static inline glm::ivec3 fromIndex(unsigned int ind) { - glm::ivec3 vec {}; - - vec.y = ind / (MAPBLOCK_SIZE * MAPBLOCK_SIZE); - ind -= (static_cast(vec.y) * MAPBLOCK_SIZE * MAPBLOCK_SIZE); - vec.z = ind / MAPBLOCK_SIZE; - vec.x = ind % MAPBLOCK_SIZE; - - return vec; - } - } - - namespace Block { - namespace relative { - // Get a Block's relative position to its Chunk from its world position. - static inline glm::ivec3 toChunk(const glm::ivec3& pos) { - return localFromGlobal(pos, CHUNK_BLOCK_LENGTH); - } - - // Get a Block's relative position to its MapBlock from its world position. - static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) { - return localFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH); - } - - // Get a Block's relative position in its Region from its world position. - static inline glm::ivec3 toRegion(const glm::ivec3& pos) { - return localFromGlobal(pos, REGION_BLOCK_LENGTH); - } - - namespace World { - // Get a Block world position from a Regions's world position. - static inline glm::ivec3 fromRegion(const glm::ivec3& pos) { - return sectionFromGlobal(pos, 1.f / REGION_BLOCK_LENGTH); - } - - // Get a Block world position from a MapBlock's world position. - static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) { - return sectionFromGlobal(pos, 1.f / MAPBLOCK_BLOCK_LENGTH); - } - - // Get a Block world position from a Chunk's world position. - static inline glm::ivec3 fromChunk(const glm::ivec3& pos) { - return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH); - } - } - } - - // Get the index of a Block within its Chunk from its local or world position. - static inline unsigned int index(const glm::ivec3& vec) { - glm::ivec3 local = Block::relative::toChunk(vec); - return static_cast(local.x + CHUNK_SIZE * (local.z + CHUNK_SIZE * local.y)); - } - - // Return a local vector of an block within its chunk. - static inline glm::ivec3 fromIndex(unsigned int ind) { - glm::ivec3 vec {}; - - vec.y = ind / (CHUNK_SIZE * CHUNK_SIZE); - ind -= (static_cast(vec.y) * CHUNK_SIZE * CHUNK_SIZE); - vec.z = ind / CHUNK_SIZE; - vec.x = ind % CHUNK_SIZE; - - return vec; - } - } + const static int CHUNK_SIZE = 16; + const static int MAPBLOCK_SIZE = 4; + const static int REGION_SIZE = 4; + + const static int CHUNK_BLOCK_LENGTH = CHUNK_SIZE; + const static int MAPBLOCK_BLOCK_LENGTH = CHUNK_BLOCK_LENGTH * MAPBLOCK_SIZE; + const static int REGION_BLOCK_LENGTH = MAPBLOCK_BLOCK_LENGTH * REGION_SIZE; + + const static int MAPBLOCK_CHUNK_LENGTH = MAPBLOCK_SIZE; + const static int REGION_CHUNK_LENGTH = MAPBLOCK_CHUNK_LENGTH * REGION_SIZE; + + // Private helper methods + namespace { + inline glm::ivec3 localFromGlobal(const glm::ivec3& pos, int size) { + return glm::vec3{ + (pos.x < 0) ? size - 1 + static_cast(pos.x + 1) % size : static_cast(pos.x) % size, + (pos.y < 0) ? size - 1 + static_cast(pos.y + 1) % size : static_cast(pos.y) % size, + (pos.z < 0) ? size - 1 + static_cast(pos.z + 1) % size : static_cast(pos.z) % size + }; + } + + inline glm::ivec3 sectionFromGlobal(glm::ivec3 pos, float size) { + return { + std::floor(static_cast(pos.x) / size), + std::floor(static_cast(pos.y) / size), + std::floor(static_cast(pos.z) / size) + }; + } + } + + namespace Region { + namespace world { + // Get a Region world position from a MapBlock's world position. + static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) { + return sectionFromGlobal(pos, REGION_SIZE); + } + + // Get a Region world position from a Chunk's world position. + static inline glm::ivec3 fromChunk(const glm::ivec3& pos) { + return sectionFromGlobal(pos, REGION_CHUNK_LENGTH); + } + + // Get a Region world position from a Block's world position. + static inline glm::ivec3 fromBlock(const glm::ivec3& pos) { + return sectionFromGlobal(pos, REGION_BLOCK_LENGTH); + } + } + } + + namespace MapBlock { + namespace relative { + // Get a MapBlock's relative position in its Region from its world position. + static inline glm::ivec3 toRegion(const glm::ivec3& pos) { + return localFromGlobal(pos, MAPBLOCK_SIZE); + } + } + + namespace world { + // Get a MapBlock world position from a Region's world position. + static inline glm::ivec3 fromRegion(const glm::ivec3& pos) { + return sectionFromGlobal(pos, 1.f / REGION_SIZE); + } + + // Get a MapBlock world position from a Chunk's world position. + static inline glm::ivec3 fromChunk(const glm::ivec3& pos) { + return sectionFromGlobal(pos, MAPBLOCK_SIZE); + } + + // Get a MapBlock world position from a Block's world position. + static inline glm::ivec3 fromBlock(const glm::ivec3& pos) { + return sectionFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH); + } + } + + // Get the index of a MapBlock within its Region from its local or world position. + static inline unsigned int index(const glm::ivec3& vec) { + glm::ivec3 local = MapBlock::relative::toRegion(vec); + unsigned int ind = static_cast(local.x + REGION_SIZE * (local.y + REGION_SIZE * local.z)); + return ind; + } + } + + namespace Chunk { + namespace relative { + // Get a Chunk's relative position in its MapBlock from its world position. + static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) { + return localFromGlobal(pos, MAPBLOCK_CHUNK_LENGTH); + } + + // Get a Chunk's relative position in its Region from its world position. + static inline glm::ivec3 toRegion(const glm::ivec3& pos) { + return localFromGlobal(pos, REGION_CHUNK_LENGTH); + } + } + + namespace world { + // Get a Chunk world position from a Regions's world position. + static inline glm::ivec3 fromRegion(const glm::ivec3& pos) { + return sectionFromGlobal(pos, 1.f / REGION_CHUNK_LENGTH); + } + + // Get a Chunk world position from a MapBlock's world position. + static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) { + return sectionFromGlobal(pos, 1.f / MAPBLOCK_CHUNK_LENGTH); + } + + // Get a Chunk world position from a Block's world position. + static inline glm::ivec3 fromBlock(const glm::ivec3& pos) { + return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH); + } + } + + // Get the index of a Chunk within its MapBlock from its local or world position. + static inline unsigned int index(const glm::ivec3& vec) { + glm::ivec3 local = Chunk::relative::toMapBlock(vec); + return static_cast(local.x + MAPBLOCK_SIZE * (local.z + MAPBLOCK_SIZE * local.y)); + } + + // Return a local vector of an chunk within its mapblock. + static inline glm::ivec3 fromIndex(unsigned int ind) { + glm::ivec3 vec{}; + + vec.y = ind / (MAPBLOCK_SIZE * MAPBLOCK_SIZE); + ind -= (static_cast(vec.y) * MAPBLOCK_SIZE * MAPBLOCK_SIZE); + vec.z = ind / MAPBLOCK_SIZE; + vec.x = ind % MAPBLOCK_SIZE; + + return vec; + } + } + + namespace Block { + namespace relative { + // Get a Block's relative position to its Chunk from its world position. + static inline glm::ivec3 toChunk(const glm::ivec3& pos) { + return localFromGlobal(pos, CHUNK_BLOCK_LENGTH); + } + + // Get a Block's relative position to its MapBlock from its world position. + static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) { + return localFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH); + } + + // Get a Block's relative position in its Region from its world position. + static inline glm::ivec3 toRegion(const glm::ivec3& pos) { + return localFromGlobal(pos, REGION_BLOCK_LENGTH); + } + + namespace World { + // Get a Block world position from a Regions's world position. + static inline glm::ivec3 fromRegion(const glm::ivec3& pos) { + return sectionFromGlobal(pos, 1.f / REGION_BLOCK_LENGTH); + } + + // Get a Block world position from a MapBlock's world position. + static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) { + return sectionFromGlobal(pos, 1.f / MAPBLOCK_BLOCK_LENGTH); + } + + // Get a Block world position from a Chunk's world position. + static inline glm::ivec3 fromChunk(const glm::ivec3& pos) { + return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH); + } + } + } + + // Get the index of a Block within its Chunk from its local or world position. + static inline unsigned int index(const glm::ivec3& vec) { + glm::ivec3 local = Block::relative::toChunk(vec); + return static_cast(local.x + CHUNK_SIZE * (local.z + CHUNK_SIZE * local.y)); + } + + // Return a local vector of an block within its chunk. + static inline glm::ivec3 fromIndex(unsigned int ind) { + glm::ivec3 vec{}; + + vec.y = ind / (CHUNK_SIZE * CHUNK_SIZE); + ind -= (static_cast(vec.y) * CHUNK_SIZE * CHUNK_SIZE); + vec.z = ind / CHUNK_SIZE; + vec.x = ind % CHUNK_SIZE; + + return vec; + } + } } diff --git a/src/util/Target.cpp b/src/util/Target.cpp index eed20510..79212a01 100644 --- a/src/util/Target.cpp +++ b/src/util/Target.cpp @@ -7,8 +7,8 @@ #include "game/def/mesh/SelectionBox.h" Target::Target(DimensionPtr dim, glm::ivec3 pos, EVec face) : - type(Type::BLOCK), dim(dim), pos(pos), face(face) {} + type(Type::BLOCK), dim(dim), pos(pos), face(face) {} glm::ivec3 Target::getAbovePos() const { - return glm::ivec3(pos) + SelectionBox::faceToOffset(face); + return glm::ivec3(pos) + SelectionBox::faceToOffset(face); } diff --git a/src/util/Target.h b/src/util/Target.h index 57b83719..8881bd35 100644 --- a/src/util/Target.h +++ b/src/util/Target.h @@ -8,19 +8,23 @@ #include "util/CovariantPtr.h" class Target { -public: - enum class Type { ENTITY, BLOCK, NOTHING }; - - Target() = default; - Target(const Target &o) = default; - Target(DimensionPtr dim, glm::ivec3 pos, EVec face); - - glm::ivec3 getAbovePos() const; - -public: - Type type = Target::Type::NOTHING; - - glm::vec3 pos {}; - DimensionPtr dim; - EVec face = EVec::NONE; + public: + enum class Type { + ENTITY, BLOCK, NOTHING + }; + + Target() = default; + + Target(const Target& o) = default; + + Target(DimensionPtr dim, glm::ivec3 pos, EVec face); + + glm::ivec3 getAbovePos() const; + + public: + Type type = Target::Type::NOTHING; + + glm::vec3 pos{}; + DimensionPtr dim; + EVec face = EVec::NONE; }; diff --git a/src/util/Timer.cpp b/src/util/Timer.cpp index 0041c185..c43b8ae3 100644 --- a/src/util/Timer.cpp +++ b/src/util/Timer.cpp @@ -7,25 +7,25 @@ #include "Timer.h" Timer::Timer() : - start(std::chrono::high_resolution_clock::now()) {} + start(std::chrono::high_resolution_clock::now()) {} Timer::Timer(const std::string& name) : - name(name), start(std::chrono::high_resolution_clock::now()) {} + name(name), start(std::chrono::high_resolution_clock::now()) {} long Timer::elapsedNs() const { - auto finish = std::chrono::high_resolution_clock::now(); - long elapsed = std::chrono::duration_cast(finish - start).count(); - return elapsed; + auto finish = std::chrono::high_resolution_clock::now(); + long elapsed = std::chrono::duration_cast(finish - start).count(); + return elapsed; }; void Timer::printElapsedNs() { - std::cout << this->name << " took " << elapsedNs() << " ns." << std::endl;; + std::cout << this->name << " took " << elapsedNs() << " ns." << std::endl;; } void Timer::printElapsedMs() { - std::cout << this->name << " took " << (elapsedNs() / 1000000.) << " ms." << std::endl;; + std::cout << this->name << " took " << (elapsedNs() / 1000000.) << " ms." << std::endl;; } void Timer::printElapsedSeconds() { - std::cout << this->name << " took " << (elapsedNs() / 1000000. / 1000.) << " secs." << std::endl; + std::cout << this->name << " took " << (elapsedNs() / 1000000. / 1000.) << " secs." << std::endl; } \ No newline at end of file diff --git a/src/util/Timer.h b/src/util/Timer.h index bb204c24..5fd3064d 100644 --- a/src/util/Timer.h +++ b/src/util/Timer.h @@ -8,17 +8,21 @@ #include class Timer { -public: - explicit Timer(); - explicit Timer(const std::string& name); - - long elapsedNs() const; - - void printElapsedNs(); - void printElapsedMs(); - void printElapsedSeconds(); -private: - std::string name = ""; - std::chrono::high_resolution_clock::time_point start; + public: + explicit Timer(); + + explicit Timer(const std::string& name); + + long elapsedNs() const; + + void printElapsedNs(); + + void printElapsedMs(); + + void printElapsedSeconds(); + + private: + std::string name = ""; + std::chrono::high_resolution_clock::time_point start; }; diff --git a/src/util/Util.h b/src/util/Util.h index 74649783..210782bb 100644 --- a/src/util/Util.h +++ b/src/util/Util.h @@ -14,253 +14,253 @@ #include "Log.h" namespace Util { - struct EnumClassHash { - template - std::size_t operator()(T t) const { - return static_cast(t); - } - }; - - static std::string floatToString(float val) { - std::ostringstream out; - out.precision(2); - out << std::fixed << val; - return out.str(); - } - - inline static std::string doubleToString(double val) { - return floatToString((float)val); - } - - static std::string vecToString(glm::ivec3 vec) { - std::ostringstream out; - out << vec.x << ", " << vec.y << ", " << vec.z; - return out.str(); - } - - static std::string vecToString(glm::vec3 vec) { - std::ostringstream out; - out << vec.x << ", " << vec.y << ", " << vec.z; - return out.str(); - } - - static std::string floatVecToString(glm::vec3 vec) { - std::ostringstream out; - out.precision(2); - out << std::fixed << vec.x << ", " << std::fixed << vec.y << ", " << std::fixed << vec.z; - return out.str(); - } - - inline static float packFloat(const glm::vec3& vec) { - auto charX = static_cast((vec.x + 1.0f) * 0.5f * 255.f); - auto charY = static_cast((vec.y + 1.0f) * 0.5f * 255.f); - auto charZ = static_cast((vec.z + 1.0f) * 0.5f * 255.f); - - unsigned int packedInt = (charX << 16) | (charY << 8) | charZ; - return static_cast(static_cast(packedInt) / static_cast(1 << 24)); - } - - inline static unsigned int intFromHexSegment(const std::string &t) { - unsigned int x; - std::stringstream ss; - ss << std::hex << t; - ss >> x; - return x; - } - - static glm::vec4 hexToColorVec(std::string hex) { - glm::vec4 color {}; - - if (hex[0] == '#') hex.erase(0, 1); - else std::cout << Log::err << "Color string does not begin with hash!" << Log::endl; - - std::string r, g, b, a; - - if (hex.length() == 3 || hex.length() == 4) { - r = hex.substr(0, 1); - r += r; - g = hex.substr(1, 1); - g += g; - b = hex.substr(2, 1); - b += b; - a = (hex.length() == 4) ? hex.substr(3, 1) : "f"; - a += a; - } - else if (hex.length() == 6 || hex.length() == 8) { - r = hex.substr(0,2); - g = hex.substr(2,2); - b = hex.substr(4,2); - a = (hex.length() == 8) ? hex.substr(6,2) : "ff"; - } - else { - std::cout << Log::err << "Color string \"" + hex + "\" is of incorrect length!" << Log::endl; - return color; - } - - color.r = intFromHexSegment(r) / 255.f; - color.g = intFromHexSegment(g) / 255.f; - color.b = intFromHexSegment(b) / 255.f; - color.a = intFromHexSegment(a) / 255.f; - - return color; - } - - static std::string getKeyStr(unsigned short key) { - switch (key) { - default: return ""; - - case 0: return "mouse0"; - case 1: return "mouse1"; - case 2: return "mouse2"; - case 3: return "mouse3"; - case 4: return "mouse4"; - case 5: return "mouse5"; - case 6: return "mouse6"; - case 7: return "mouse7"; - case 8: return "scrollup"; - case 9: return "scrolldown"; - case 10: return "scrollleft"; - case 11: return "scrollright"; - - case 32: return "space"; - case 39: return "'"; - case 44: return ","; - case 45: return "-"; - case 46: return "."; - case 47: return "/"; - case 48: return "0"; - case 49: return "1"; - case 50: return "2"; - case 51: return "3"; - case 52: return "4"; - case 53: return "5"; - case 54: return "6"; - case 55: return "7"; - case 56: return "8"; - case 57: return "9"; - case 59: return ";"; - case 61: return "="; - case 65: return "a"; - case 66: return "b"; - case 67: return "c"; - case 68: return "d"; - case 69: return "e"; - case 70: return "f"; - case 71: return "g"; - case 72: return "h"; - case 73: return "i"; - case 74: return "j"; - case 75: return "k"; - case 76: return "l"; - case 77: return "m"; - case 78: return "n"; - case 79: return "o"; - case 80: return "p"; - case 81: return "q"; - case 82: return "r"; - case 83: return "s"; - case 84: return "t"; - case 85: return "u"; - case 86: return "v"; - case 87: return "w"; - case 88: return "x"; - case 89: return "y"; - case 90: return "z"; - case 91: return "["; - case 92: return "\\"; - case 93: return "]"; - case 96: return "`"; - case 161: return "world1"; - case 162: return "world2"; - case 256: return "escape"; - case 257: return "enter"; - case 258: return "tab"; - case 259: return "backspace"; - case 260: return "insert"; - case 261: return "delete"; - case 262: return "right"; - case 263: return "left"; - case 264: return "down"; - case 265: return "up"; - case 266: return "pageup"; - case 267: return "pagedown"; - case 268: return "home"; - case 269: return "end"; - case 280: return "capslock"; - case 281: return "scrolllock"; - case 282: return "numlock"; - case 283: return "printscreen"; - case 284: return "pause"; - case 290: return "f1"; - case 291: return "f2"; - case 292: return "f3"; - case 293: return "f4"; - case 294: return "f5"; - case 295: return "f6"; - case 296: return "f7"; - case 297: return "f8"; - case 298: return "f9"; - case 299: return "f10"; - case 300: return "f11"; - case 301: return "f12"; - case 302: return "f13"; - case 303: return "f14"; - case 304: return "f15"; - case 305: return "f16"; - case 306: return "f17"; - case 307: return "f18"; - case 308: return "f19"; - case 309: return "f20"; - case 310: return "f21"; - case 311: return "f22"; - case 312: return "f23"; - case 313: return "f24"; - case 314: return "f25"; - case 320: return "num0"; - case 321: return "num1"; - case 322: return "num2"; - case 323: return "num3"; - case 324: return "num4"; - case 325: return "num5"; - case 326: return "num6"; - case 327: return "num7"; - case 328: return "num8"; - case 329: return "num9"; - case 330: return "num."; - case 331: return "num/"; - case 332: return "num*"; - case 333: return "num-"; - case 334: return "num+"; - case 335: return "numenter"; - case 336: return "num="; - case 340: return "leftshift"; - case 341: return "leftctrl"; - case 342: return "leftalt"; - case 344: return "rightshift"; - case 345: return "rightctrl"; - case 346: return "rightalt"; - case 348: return "menu"; - } - } - - namespace { - constexpr static uint64_t mix(char m, uint64_t s) { - return ((s << 7) + ~(s >> 3)) + ~m; - } - } - - constexpr static uint64_t hash(const char * m) { - return (*m) ? mix(*m, hash(m + 1)) : 0; - } - - template - std::function bind_this(C* c, Ret (C::*m)(Ts...)) { - return [=](auto&&... args) { return (c->*m)(std::forward(args)...); }; - } - - template - std::function bind_this(const C* c, Ret (C::*m)(Ts...) const) { - return [=](auto&&... args) { return (c->*m)(std::forward(args)...); }; - } + struct EnumClassHash { + template + std::size_t operator()(T t) const { + return static_cast(t); + } + }; + + static std::string floatToString(float val) { + std::ostringstream out; + out.precision(2); + out << std::fixed << val; + return out.str(); + } + + inline static std::string doubleToString(double val) { + return floatToString((float) val); + } + + static std::string vecToString(glm::ivec3 vec) { + std::ostringstream out; + out << vec.x << ", " << vec.y << ", " << vec.z; + return out.str(); + } + + static std::string vecToString(glm::vec3 vec) { + std::ostringstream out; + out << vec.x << ", " << vec.y << ", " << vec.z; + return out.str(); + } + + static std::string floatVecToString(glm::vec3 vec) { + std::ostringstream out; + out.precision(2); + out << std::fixed << vec.x << ", " << std::fixed << vec.y << ", " << std::fixed << vec.z; + return out.str(); + } + + inline static float packFloat(const glm::vec3& vec) { + auto charX = static_cast((vec.x + 1.0f) * 0.5f * 255.f); + auto charY = static_cast((vec.y + 1.0f) * 0.5f * 255.f); + auto charZ = static_cast((vec.z + 1.0f) * 0.5f * 255.f); + + unsigned int packedInt = (charX << 16) | (charY << 8) | charZ; + return static_cast(static_cast(packedInt) / static_cast(1 << 24)); + } + + inline static unsigned int intFromHexSegment(const std::string& t) { + unsigned int x; + std::stringstream ss; + ss << std::hex << t; + ss >> x; + return x; + } + + static glm::vec4 hexToColorVec(std::string hex) { + glm::vec4 color{}; + + if (hex[0] == '#') hex.erase(0, 1); + else std::cout << Log::err << "Color string does not begin with hash!" << Log::endl; + + std::string r, g, b, a; + + if (hex.length() == 3 || hex.length() == 4) { + r = hex.substr(0, 1); + r += r; + g = hex.substr(1, 1); + g += g; + b = hex.substr(2, 1); + b += b; + a = (hex.length() == 4) ? hex.substr(3, 1) : "f"; + a += a; + } + else if (hex.length() == 6 || hex.length() == 8) { + r = hex.substr(0, 2); + g = hex.substr(2, 2); + b = hex.substr(4, 2); + a = (hex.length() == 8) ? hex.substr(6, 2) : "ff"; + } + else { + std::cout << Log::err << "Color string \"" + hex + "\" is of incorrect length!" << Log::endl; + return color; + } + + color.r = intFromHexSegment(r) / 255.f; + color.g = intFromHexSegment(g) / 255.f; + color.b = intFromHexSegment(b) / 255.f; + color.a = intFromHexSegment(a) / 255.f; + + return color; + } + + static std::string getKeyStr(unsigned short key) { + switch (key) { + default: return ""; + + case 0: return "mouse0"; + case 1: return "mouse1"; + case 2: return "mouse2"; + case 3: return "mouse3"; + case 4: return "mouse4"; + case 5: return "mouse5"; + case 6: return "mouse6"; + case 7: return "mouse7"; + case 8: return "scrollup"; + case 9: return "scrolldown"; + case 10: return "scrollleft"; + case 11: return "scrollright"; + + case 32: return "space"; + case 39: return "'"; + case 44: return ","; + case 45: return "-"; + case 46: return "."; + case 47: return "/"; + case 48: return "0"; + case 49: return "1"; + case 50: return "2"; + case 51: return "3"; + case 52: return "4"; + case 53: return "5"; + case 54: return "6"; + case 55: return "7"; + case 56: return "8"; + case 57: return "9"; + case 59: return ";"; + case 61: return "="; + case 65: return "a"; + case 66: return "b"; + case 67: return "c"; + case 68: return "d"; + case 69: return "e"; + case 70: return "f"; + case 71: return "g"; + case 72: return "h"; + case 73: return "i"; + case 74: return "j"; + case 75: return "k"; + case 76: return "l"; + case 77: return "m"; + case 78: return "n"; + case 79: return "o"; + case 80: return "p"; + case 81: return "q"; + case 82: return "r"; + case 83: return "s"; + case 84: return "t"; + case 85: return "u"; + case 86: return "v"; + case 87: return "w"; + case 88: return "x"; + case 89: return "y"; + case 90: return "z"; + case 91: return "["; + case 92: return "\\"; + case 93: return "]"; + case 96: return "`"; + case 161: return "world1"; + case 162: return "world2"; + case 256: return "escape"; + case 257: return "enter"; + case 258: return "tab"; + case 259: return "backspace"; + case 260: return "insert"; + case 261: return "delete"; + case 262: return "right"; + case 263: return "left"; + case 264: return "down"; + case 265: return "up"; + case 266: return "pageup"; + case 267: return "pagedown"; + case 268: return "home"; + case 269: return "end"; + case 280: return "capslock"; + case 281: return "scrolllock"; + case 282: return "numlock"; + case 283: return "printscreen"; + case 284: return "pause"; + case 290: return "f1"; + case 291: return "f2"; + case 292: return "f3"; + case 293: return "f4"; + case 294: return "f5"; + case 295: return "f6"; + case 296: return "f7"; + case 297: return "f8"; + case 298: return "f9"; + case 299: return "f10"; + case 300: return "f11"; + case 301: return "f12"; + case 302: return "f13"; + case 303: return "f14"; + case 304: return "f15"; + case 305: return "f16"; + case 306: return "f17"; + case 307: return "f18"; + case 308: return "f19"; + case 309: return "f20"; + case 310: return "f21"; + case 311: return "f22"; + case 312: return "f23"; + case 313: return "f24"; + case 314: return "f25"; + case 320: return "num0"; + case 321: return "num1"; + case 322: return "num2"; + case 323: return "num3"; + case 324: return "num4"; + case 325: return "num5"; + case 326: return "num6"; + case 327: return "num7"; + case 328: return "num8"; + case 329: return "num9"; + case 330: return "num."; + case 331: return "num/"; + case 332: return "num*"; + case 333: return "num-"; + case 334: return "num+"; + case 335: return "numenter"; + case 336: return "num="; + case 340: return "leftshift"; + case 341: return "leftctrl"; + case 342: return "leftalt"; + case 344: return "rightshift"; + case 345: return "rightctrl"; + case 346: return "rightalt"; + case 348: return "menu"; + } + } + + namespace { + constexpr static uint64_t mix(char m, uint64_t s) { + return ((s << 7) + ~(s >> 3)) + ~m; + } + } + + constexpr static uint64_t hash(const char* m) { + return (*m) ? mix(*m, hash(m + 1)) : 0; + } + + template + std::function bind_this(C* c, Ret (C::*m)(Ts...)) { + return [=](auto&& ... args) { return (c->*m)(std::forward(args)...); }; + } + + template + std::function bind_this(const C* c, Ret (C::*m)(Ts...) const) { + return [=](auto&& ... args) { return (c->*m)(std::forward(args)...); }; + } }; diff --git a/src/util/Vec.h b/src/util/Vec.h index 47475d40..fe2a578c 100644 --- a/src/util/Vec.h +++ b/src/util/Vec.h @@ -12,40 +12,49 @@ #include "Space.h" enum class EVec { - LEFT = 0, RIGHT = 1, BOTTOM = 2, TOP = 3, FRONT = 4, BACK = 5, - XNEG = 0, XPOS = 1, YNEG = 2, YPOS = 3, ZPOS = 4, ZNEG = 5, - - INVALID = -1, NONE = -1, - NO_CULL = 6, + LEFT = 0, RIGHT = 1, BOTTOM = 2, TOP = 3, FRONT = 4, BACK = 5, + XNEG = 0, XPOS = 1, YNEG = 2, YPOS = 3, ZPOS = 4, ZNEG = 5, + + INVALID = -1, NONE = -1, + NO_CULL = 6, }; namespace Vec { - - // Comparison Functions - - struct vec3 { size_t operator()(const glm::vec3& k)const { - return std::hash()(k.x) ^ std::hash()(k.y) ^ std::hash()(k.z); } }; - - struct ivec3 { size_t operator()(const glm::ivec3& k)const { - return std::hash()(k.x) ^ std::hash()(k.y) ^ std::hash()(k.z); } }; - - struct ivec4 { size_t operator()(const glm::ivec4& k)const { - return std::hash()(k.x) ^ std::hash()(k.y) ^ std::hash()(k.z) ^ std::hash()(k.w); } }; - - // Adjacent Arrays & Maps - - const static std::array TO_VEC = { - glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} }; - - const static std::array TO_VEC_R = { - glm::ivec3 {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1} }; - - const static std::unordered_map TO_ENUM = { - {TO_VEC[0], EVec::LEFT }, {TO_VEC[1], EVec::RIGHT }, {TO_VEC[2], EVec::BOTTOM }, - {TO_VEC[3], EVec::TOP }, {TO_VEC[4], EVec::FRONT }, {TO_VEC[5], EVec::BACK } }; - - const static std::unordered_map TO_ENUM_R = { - {TO_VEC[0], EVec::RIGHT }, {TO_VEC[1], EVec::LEFT }, {TO_VEC[2], EVec::TOP }, - {TO_VEC[3], EVec::BOTTOM }, {TO_VEC[4], EVec::BACK }, {TO_VEC[5], EVec::FRONT } }; + + // Comparison Functions + + struct vec3 { + size_t operator()(const glm::vec3& k) const { + return std::hash()(k.x) ^ std::hash()(k.y) ^ std::hash()(k.z); + } + }; + + struct ivec3 { + size_t operator()(const glm::ivec3& k) const { + return std::hash()(k.x) ^ std::hash()(k.y) ^ std::hash()(k.z); + } + }; + + struct ivec4 { + size_t operator()(const glm::ivec4& k) const { + return std::hash()(k.x) ^ std::hash()(k.y) ^ std::hash()(k.z) ^ std::hash()(k.w); + } + }; + + // Adjacent Arrays & Maps + + const static std::array TO_VEC = { + glm::ivec3{ -1, 0, 0 }, { 1, 0, 0 }, { 0, -1, 0 }, { 0, 1, 0 }, { 0, 0, -1 }, { 0, 0, 1 }}; + + const static std::array TO_VEC_R = { + glm::ivec3{ 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }}; + + const static std::unordered_map TO_ENUM = { + { TO_VEC[0], EVec::LEFT }, { TO_VEC[1], EVec::RIGHT }, { TO_VEC[2], EVec::BOTTOM }, + { TO_VEC[3], EVec::TOP }, { TO_VEC[4], EVec::FRONT }, { TO_VEC[5], EVec::BACK }}; + + const static std::unordered_map TO_ENUM_R = { + { TO_VEC[0], EVec::RIGHT }, { TO_VEC[1], EVec::LEFT }, { TO_VEC[2], EVec::TOP }, + { TO_VEC[3], EVec::BOTTOM }, { TO_VEC[4], EVec::BACK }, { TO_VEC[5], EVec::FRONT }}; }; diff --git a/src/util/Voronoi3D.cpp b/src/util/Voronoi3D.cpp index 4efc83fb..2985dab5 100644 --- a/src/util/Voronoi3D.cpp +++ b/src/util/Voronoi3D.cpp @@ -7,42 +7,42 @@ #include "Voronoi3D.h" Voronoi3D::Voronoi3D(unsigned short size) : - size(size), - data(voronoi_data(size)) { - - for (unsigned short i = 0; i < size; i++) { - data[i].resize(size); - for (unsigned short j = 0; j < size; j++) { - data[i][j].resize(size); - } - } + size(size), + data(voronoi_data(size)) { + + for (unsigned short i = 0; i < size; i++) { + data[i].resize(size); + for (unsigned short j = 0; j < size; j++) { + data[i][j].resize(size); + } + } } void Voronoi3D::setPoints(const std::vector>& points) { - this->points = points; - - for (unsigned short i = 0; i < size; i++) { - for (unsigned short j = 0; j < size; j++) { - for (unsigned short k = 0; k < size; k++) { - float pointDistance = INFINITY; - unsigned short ind = 0; - - for (auto& point : points) { - float thisPointDistance = glm::distance(point.first, {i, j, k}); - if (thisPointDistance < pointDistance) { - pointDistance = thisPointDistance; - ind = point.second; - } - } - - data[i][j][k] = ind; - } - } - } + this->points = points; + + for (unsigned short i = 0; i < size; i++) { + for (unsigned short j = 0; j < size; j++) { + for (unsigned short k = 0; k < size; k++) { + float pointDistance = INFINITY; + unsigned short ind = 0; + + for (auto& point : points) { + float thisPointDistance = glm::distance(point.first, { i, j, k }); + if (thisPointDistance < pointDistance) { + pointDistance = thisPointDistance; + ind = point.second; + } + } + + data[i][j][k] = ind; + } + } + } } unsigned short Voronoi3D::getPoint(unsigned short x, unsigned short y, unsigned short z) { - return data[x][y][z]; + return data[x][y][z]; } //void Voronoi3D::setColorValues(const std::vector& values) { diff --git a/src/util/Voronoi3D.h b/src/util/Voronoi3D.h index 9b3b4118..91b6e49b 100644 --- a/src/util/Voronoi3D.h +++ b/src/util/Voronoi3D.h @@ -8,20 +8,22 @@ #include class Voronoi3D { -public: - Voronoi3D() = default; - Voronoi3D(unsigned short size); - - void setPoints(const std::vector>& points); - unsigned short getPoint(unsigned short x, unsigned short y, unsigned short z); + public: + Voronoi3D() = default; + + Voronoi3D(unsigned short size); + + void setPoints(const std::vector>& points); + + unsigned short getPoint(unsigned short x, unsigned short y, unsigned short z); // void setColorValues(const std::vector& values); // void generateImage(unsigned short depth); -private: - typedef std::vector>> voronoi_data; - - unsigned short size; - voronoi_data data; - std::vector> points; + private: + typedef std::vector>> voronoi_data; + + unsigned short size; + voronoi_data data; + std::vector> points; // std::vector colorValues; }; diff --git a/src/util/frustum/Frustum.cpp b/src/util/frustum/Frustum.cpp index 17797510..f9b7d896 100644 --- a/src/util/frustum/Frustum.cpp +++ b/src/util/frustum/Frustum.cpp @@ -7,55 +7,55 @@ #include "Frustum.h" void Frustum::setCamInternals(float fov, float ratio, float nearD, float farD) { - this->nearD = nearD; - this->farD = farD; - - nearH = std::tan(fov) * nearD; - nearW = nearH * ratio; - - farH = std::tan(fov) * farD; - farW = farH * ratio; + this->nearD = nearD; + this->farD = farD; + + nearH = std::tan(fov) * nearD; + nearW = nearH * ratio; + + farH = std::tan(fov) * farD; + farW = farH * ratio; } -void Frustum::update(glm::vec3 &pos, glm::vec3 &look, glm::vec3 &up, glm::vec3 &right) { - glm::vec3 fc = pos + (look * farD); - - ftl = fc + (up * (farH / 2.0f)) - (right * (farW / 2.0f)); - ftr = fc + (up * (farH / 2.0f)) + (right * (farW / 2.0f)); - fbl = fc - (up * (farH / 2.0f)) - (right * (farW / 2.0f)); - fbr = fc - (up * (farH / 2.0f)) + (right * (farW / 2.0f)); - - glm::vec3 nc = pos + (look * nearD); - - ntl = nc + (up * (nearH / 2.0f)) - (right * (nearW / 2.0f)); - ntr = nc + (up * (nearH / 2.0f)) + (right * (nearW / 2.0f)); - nbl = nc - (up * (nearH / 2.0f)) - (right * (nearW / 2.0f)); - nbr = nc - (up * (nearH / 2.0f)) + (right * (nearW / 2.0f)); - - planes[TOP].setPoints(ntr,ntl,ftl); - planes[BOTTOM].setPoints(nbl,nbr,fbr); - planes[LEFT].setPoints(ntl,nbl,fbl); - planes[RIGHT].setPoints(nbr,ntr,fbr); - planes[FNEAR].setPoints(ntl,ntr,nbr); - planes[FFAR].setPoints(ftr,ftl,fbl); +void Frustum::update(glm::vec3& pos, glm::vec3& look, glm::vec3& up, glm::vec3& right) { + glm::vec3 fc = pos + (look * farD); + + ftl = fc + (up * (farH / 2.0f)) - (right * (farW / 2.0f)); + ftr = fc + (up * (farH / 2.0f)) + (right * (farW / 2.0f)); + fbl = fc - (up * (farH / 2.0f)) - (right * (farW / 2.0f)); + fbr = fc - (up * (farH / 2.0f)) + (right * (farW / 2.0f)); + + glm::vec3 nc = pos + (look * nearD); + + ntl = nc + (up * (nearH / 2.0f)) - (right * (nearW / 2.0f)); + ntr = nc + (up * (nearH / 2.0f)) + (right * (nearW / 2.0f)); + nbl = nc - (up * (nearH / 2.0f)) - (right * (nearW / 2.0f)); + nbr = nc - (up * (nearH / 2.0f)) + (right * (nearW / 2.0f)); + + planes[TOP].setPoints(ntr, ntl, ftl); + planes[BOTTOM].setPoints(nbl, nbr, fbr); + planes[LEFT].setPoints(ntl, nbl, fbl); + planes[RIGHT].setPoints(nbr, ntr, fbr); + planes[FNEAR].setPoints(ntl, ntr, nbr); + planes[FFAR].setPoints(ftr, ftl, fbl); } -int Frustum::pointInFrustum(glm::vec3 &p) { - for (FrustumPlane &plane : planes) { - if (plane.distance(p) < 0) return OUTSIDE; - } - return INSIDE; +int Frustum::pointInFrustum(glm::vec3& p) { + for (FrustumPlane& plane : planes) { + if (plane.distance(p) < 0) return OUTSIDE; + } + return INSIDE; } -int Frustum::boxInFrustum(FrustumAABB &b) { - int result = INSIDE; - - for (auto &plane : planes) { - glm::vec3 vertexP = b.getVertexP(plane.normal); - if (plane.distance(vertexP) < 0) return OUTSIDE; - - glm::vec3 vertexN = b.getVertexN(plane.normal); - if (plane.distance(vertexN) < 0) result = INTERSECT; - } - return result; +int Frustum::boxInFrustum(FrustumAABB& b) { + int result = INSIDE; + + for (auto& plane : planes) { + glm::vec3 vertexP = b.getVertexP(plane.normal); + if (plane.distance(vertexP) < 0) return OUTSIDE; + + glm::vec3 vertexN = b.getVertexN(plane.normal); + if (plane.distance(vertexN) < 0) result = INTERSECT; + } + return result; } diff --git a/src/util/frustum/Frustum.h b/src/util/frustum/Frustum.h index b67dc668..5bc2e482 100644 --- a/src/util/frustum/Frustum.h +++ b/src/util/frustum/Frustum.h @@ -9,37 +9,39 @@ #include "FrustumAABB.h" class Frustum { -private: - enum { - TOP = 0, - BOTTOM, - LEFT, - RIGHT, - FNEAR, - FFAR - }; - -public: - enum { - OUTSIDE, - INSIDE, - INTERSECT - }; - - Frustum() = default; - - void setCamInternals(float angle, float ratio, float nearD, float farD); - void update(glm::vec3 &pos, glm::vec3 &look, glm::vec3 &up, glm::vec3 &right); - - int pointInFrustum(glm::vec3 &p); - int boxInFrustum(FrustumAABB &b); - - FrustumPlane planes[6]; - - float nearD, farD; - float nearW, nearH, farW, farH; - - glm::vec3 ntl, ntr, nbl, nbr, - ftl, ftr, fbl, fbr; + private: + enum { + TOP = 0, + BOTTOM, + LEFT, + RIGHT, + FNEAR, + FFAR + }; + + public: + enum { + OUTSIDE, + INSIDE, + INTERSECT + }; + + Frustum() = default; + + void setCamInternals(float angle, float ratio, float nearD, float farD); + + void update(glm::vec3& pos, glm::vec3& look, glm::vec3& up, glm::vec3& right); + + int pointInFrustum(glm::vec3& p); + + int boxInFrustum(FrustumAABB& b); + + FrustumPlane planes[6]; + + float nearD, farD; + float nearW, nearH, farW, farH; + + glm::vec3 ntl, ntr, nbl, nbr, + ftl, ftr, fbl, fbr; }; diff --git a/src/util/frustum/FrustumAABB.cpp b/src/util/frustum/FrustumAABB.cpp index 6afca821..76331f46 100644 --- a/src/util/frustum/FrustumAABB.cpp +++ b/src/util/frustum/FrustumAABB.cpp @@ -7,28 +7,28 @@ FrustumAABB::FrustumAABB(glm::vec3 a, glm::vec3 s) : corner(a), size(s) {} void FrustumAABB::set(glm::vec3 a, glm::vec3 s) { - corner = a; - size = s; + corner = a; + size = s; } -glm::vec3 FrustumAABB::getVertexP(glm::vec3 &normal) { - glm::vec3 res = corner; - - if (normal.x > 0) res.x += size.x; - if (normal.y > 0) res.y += size.y; - if (normal.z > 0) res.z += size.z; - - return res; +glm::vec3 FrustumAABB::getVertexP(glm::vec3& normal) { + glm::vec3 res = corner; + + if (normal.x > 0) res.x += size.x; + if (normal.y > 0) res.y += size.y; + if (normal.z > 0) res.z += size.z; + + return res; } -glm::vec3 FrustumAABB::getVertexN(glm::vec3 &normal){ - glm::vec3 res = corner; - - if (normal.x < 0) res.x += size.x; - if (normal.y < 0) res.y += size.y; - if (normal.z < 0) res.z += size.z; - - return res; +glm::vec3 FrustumAABB::getVertexN(glm::vec3& normal) { + glm::vec3 res = corner; + + if (normal.x < 0) res.x += size.x; + if (normal.y < 0) res.y += size.y; + if (normal.z < 0) res.z += size.z; + + return res; } diff --git a/src/util/frustum/FrustumAABB.h b/src/util/frustum/FrustumAABB.h index 61ac96a5..df3d3722 100644 --- a/src/util/frustum/FrustumAABB.h +++ b/src/util/frustum/FrustumAABB.h @@ -7,15 +7,16 @@ #include class FrustumAABB { -public: - glm::vec3 corner; - glm::vec3 size; - - FrustumAABB(glm::vec3 a, glm::vec3 b); - - void set(glm::vec3 a, glm::vec3 b); - - glm::vec3 getVertexP(glm::vec3 &normal); - glm::vec3 getVertexN(glm::vec3 &normal); + public: + glm::vec3 corner; + glm::vec3 size; + + FrustumAABB(glm::vec3 a, glm::vec3 b); + + void set(glm::vec3 a, glm::vec3 b); + + glm::vec3 getVertexP(glm::vec3& normal); + + glm::vec3 getVertexN(glm::vec3& normal); }; diff --git a/src/util/frustum/FrustumPlane.cpp b/src/util/frustum/FrustumPlane.cpp index 2c88242b..e0610e6f 100644 --- a/src/util/frustum/FrustumPlane.cpp +++ b/src/util/frustum/FrustumPlane.cpp @@ -3,16 +3,17 @@ // #define GLM_ENABLE_EXPERIMENTAL + #include #include "FrustumPlane.h" -void FrustumPlane::setPoints(glm::vec3 &v1, glm::vec3 &v2, glm::vec3 &v3) { - normal = glm::triangleNormal(v1, v2, v3); - point = v2; - d = -glm::dot(normal, point); +void FrustumPlane::setPoints(glm::vec3& v1, glm::vec3& v2, glm::vec3& v3) { + normal = glm::triangleNormal(v1, v2, v3); + point = v2; + d = -glm::dot(normal, point); } -float FrustumPlane::distance(glm::vec3 &p) { - return (d + glm::dot(normal, p)); +float FrustumPlane::distance(glm::vec3& p) { + return (d + glm::dot(normal, p)); } \ No newline at end of file diff --git a/src/util/frustum/FrustumPlane.h b/src/util/frustum/FrustumPlane.h index e239658b..6829da84 100644 --- a/src/util/frustum/FrustumPlane.h +++ b/src/util/frustum/FrustumPlane.h @@ -7,14 +7,14 @@ #include class FrustumPlane { -public: - glm::vec3 normal, point; - float d; - - FrustumPlane() = default; - - void setPoints(glm::vec3 &v1, glm::vec3 &v2, glm::vec3 &v3); - - float distance(glm::vec3 &p); + public: + glm::vec3 normal, point; + float d; + + FrustumPlane() = default; + + void setPoints(glm::vec3& v1, glm::vec3& v2, glm::vec3& v3); + + float distance(glm::vec3& p); }; diff --git a/src/util/net/Address.cpp b/src/util/net/Address.cpp index cabcabea..cfa818c9 100644 --- a/src/util/net/Address.cpp +++ b/src/util/net/Address.cpp @@ -16,20 +16,20 @@ * @returns - An Address object with the specified address. */ -Address Address::fromString(const std::string &addressString) { - std::string address; - unsigned short port; - - size_t sep = addressString.find(':'); - if (sep == std::string::npos) { - port = Address::DEFAULT_PORT; - } - else { - address = addressString.substr(0, sep++); // Increment sep for next substr call. - unsigned int p = stoi(addressString.substr(sep, addressString.length() - sep)); - if (p > 65535) throw std::out_of_range("Port value is greater than 65535."); - port = static_cast(p); - } - - return Address { address, port }; +Address Address::fromString(const std::string& addressString) { + std::string address; + unsigned short port; + + size_t sep = addressString.find(':'); + if (sep == std::string::npos) { + port = Address::DEFAULT_PORT; + } + else { + address = addressString.substr(0, sep++); // Increment sep for next substr call. + unsigned int p = stoi(addressString.substr(sep, addressString.length() - sep)); + if (p > 65535) throw std::out_of_range("Port value is greater than 65535."); + port = static_cast(p); + } + + return Address{ address, port }; } diff --git a/src/util/net/Address.h b/src/util/net/Address.h index 6dcfb9ed..6ef30165 100644 --- a/src/util/net/Address.h +++ b/src/util/net/Address.h @@ -7,10 +7,10 @@ #include struct Address { - std::string host; - unsigned short port = Address::DEFAULT_PORT; - - static Address fromString(const std::string& addressString); - - constexpr static unsigned short DEFAULT_PORT = 13110; + std::string host; + unsigned short port = Address::DEFAULT_PORT; + + static Address fromString(const std::string& addressString); + + constexpr static unsigned short DEFAULT_PORT = 13110; }; diff --git a/src/util/net/Deserializer.h b/src/util/net/Deserializer.h index 54cf60eb..b944688a 100644 --- a/src/util/net/Deserializer.h +++ b/src/util/net/Deserializer.h @@ -11,204 +11,247 @@ #include class Deserializer { -public: - Deserializer(const std::string& data) : data(&data[0]), len(data.length()) {}; - Deserializer(const char* start, size_t len) : data(start), len(len) {}; - - template inline T read() { throw std::runtime_error("Tried to append a non-serializable type"); }; - template inline Deserializer& read(T& ref) { - ref = read(); - return *this; - }; - - template::value>::type> inline E readE() { - return static_cast(read()); - }; - template::value>::type> inline Deserializer& readE(E& ref) { - ref = static_cast(read()); - return *this; - }; - - bool atEnd() { - return ind >= len; - }; - - const char* data; - size_t len; - size_t ind = 0; - -private: - typedef union { int in; char bytes[4]; } int_union; - typedef union { unsigned int in; char bytes[4]; } uint_union; - typedef union { short sh; char bytes[2]; } short_union; - typedef union { unsigned short sh; char bytes[2]; } ushort_union; - typedef union { float fl; char bytes[4]; } float_union; + public: + Deserializer(const std::string& data) : data(&data[0]), len(data.length()) {}; + + Deserializer(const char* start, size_t len) : data(start), len(len) {}; + + template + inline T read() { throw std::runtime_error("Tried to append a non-serializable type"); }; + + template + inline Deserializer& read(T& ref) { + ref = read(); + return *this; + }; + + template::value>::type> + inline E readE() { + return static_cast(read()); + }; + + template::value>::type> + inline Deserializer& readE(E& ref) { + ref = static_cast(read()); + return *this; + }; + + bool atEnd() { + return ind >= len; + }; + + const char* data; + size_t len; + size_t ind = 0; + + private: + typedef union { + int in; + char bytes[4]; + } int_union; + typedef union { + unsigned int in; + char bytes[4]; + } uint_union; + typedef union { + short sh; + char bytes[2]; + } short_union; + typedef union { + unsigned short sh; + char bytes[2]; + } ushort_union; + typedef union { + float fl; + char bytes[4]; + } float_union; }; -template <> inline int Deserializer::read() { - int_union cv; - cv.bytes[0] = data[ind]; - cv.bytes[1] = data[ind+1]; - cv.bytes[2] = data[ind+2]; - cv.bytes[3] = data[ind+3]; - ind += 4; - return cv.in; +template<> +inline int Deserializer::read() { + int_union cv; + cv.bytes[0] = data[ind]; + cv.bytes[1] = data[ind + 1]; + cv.bytes[2] = data[ind + 2]; + cv.bytes[3] = data[ind + 3]; + ind += 4; + return cv.in; } -template <> inline unsigned int Deserializer::read() { - uint_union cv; - cv.bytes[0] = data[ind]; - cv.bytes[1] = data[ind+1]; - cv.bytes[2] = data[ind+2]; - cv.bytes[3] = data[ind+3]; - ind += 4; - return cv.in; +template<> +inline unsigned int Deserializer::read() { + uint_union cv; + cv.bytes[0] = data[ind]; + cv.bytes[1] = data[ind + 1]; + cv.bytes[2] = data[ind + 2]; + cv.bytes[3] = data[ind + 3]; + ind += 4; + return cv.in; } -template <> inline short Deserializer::read() { - short_union cv; - cv.bytes[0] = data[ind]; - cv.bytes[1] = data[ind+1]; - ind += 2; - return cv.sh; +template<> +inline short Deserializer::read() { + short_union cv; + cv.bytes[0] = data[ind]; + cv.bytes[1] = data[ind + 1]; + ind += 2; + return cv.sh; } -template <> inline unsigned short Deserializer::read() { - ushort_union cv; - cv.bytes[0] = data[ind]; - cv.bytes[1] = data[ind+1]; - ind += 2; - return cv.sh; +template<> +inline unsigned short Deserializer::read() { + ushort_union cv; + cv.bytes[0] = data[ind]; + cv.bytes[1] = data[ind + 1]; + ind += 2; + return cv.sh; } -template <> inline char Deserializer::read() { - return data[ind++]; +template<> +inline char Deserializer::read() { + return data[ind++]; } -template <> inline unsigned char Deserializer::read() { - return static_cast(data[ind++]); +template<> +inline unsigned char Deserializer::read() { + return static_cast(data[ind++]); } -template <> inline bool Deserializer::read() { - return read(); +template<> +inline bool Deserializer::read() { + return read(); } -template <> inline float Deserializer::read() { - float_union cv; - cv.bytes[0] = data[ind]; - cv.bytes[1] = data[ind+1]; - cv.bytes[2] = data[ind+2]; - cv.bytes[3] = data[ind+3]; - ind += 4; - return cv.fl; +template<> +inline float Deserializer::read() { + float_union cv; + cv.bytes[0] = data[ind]; + cv.bytes[1] = data[ind + 1]; + cv.bytes[2] = data[ind + 2]; + cv.bytes[3] = data[ind + 3]; + ind += 4; + return cv.fl; } -template <> inline std::string Deserializer::read() { - unsigned int len = read(); - size_t i = ind; - ind += len; - return std::string(&data[i], len); +template<> +inline std::string Deserializer::read() { + unsigned int len = read(); + size_t i = ind; + ind += len; + return std::string(&data[i], len); } -template <> inline glm::vec2 Deserializer::read() { - return { - read(), - read() - }; +template<> +inline glm::vec2 Deserializer::read() { + return { + read(), + read() + }; } -template <> inline glm::ivec2 Deserializer::read() { - return { - read(), - read() - }; +template<> +inline glm::ivec2 Deserializer::read() { + return { + read(), + read() + }; } -template <> inline glm::vec3 Deserializer::read() { - return { - read(), - read(), - read() - }; +template<> +inline glm::vec3 Deserializer::read() { + return { + read(), + read(), + read() + }; } -template <> inline glm::ivec3 Deserializer::read() { - return { - read(), - read(), - read() - }; +template<> +inline glm::ivec3 Deserializer::read() { + return { + read(), + read(), + read() + }; } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len * 4; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len * 4; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len * 4; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len * 4; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len * 2; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len * 2; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len * 2; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len * 2; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - auto oldInd = ind; - ind += len * 4; - return std::vector( - reinterpret_cast(&data[oldInd]), - reinterpret_cast(&data[ind])); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + auto oldInd = ind; + ind += len * 4; + return std::vector( + reinterpret_cast(&data[oldInd]), + reinterpret_cast(&data[ind])); } -template <> inline std::vector Deserializer::read>() { - unsigned int len = read(); - std::vector v {}; - v.reserve(len); - for (unsigned int i = 0; i < len; i++) { - v.push_back(read()); - } - return std::move(v); +template<> +inline std::vector Deserializer::read>() { + unsigned int len = read(); + std::vector v{}; + v.reserve(len); + for (unsigned int i = 0; i < len; i++) { + v.push_back(read()); + } + return std::move(v); } \ No newline at end of file diff --git a/src/util/net/NetField.h b/src/util/net/NetField.h index b1ef5fab..ca87bc15 100644 --- a/src/util/net/NetField.h +++ b/src/util/net/NetField.h @@ -12,29 +12,29 @@ #include "game/atlas/DefinitionAtlas.h" enum class NetField { - // General - ID, - - DIM, - POS, - VEL, - ROT, - SCALE, - - // Entities - DISPLAY, - VISUAL_OFF, - ANIM_RANGE, - ANIM_STATE, - - // Players - LOOK_OFF, - LOOK_PITCH, - LOOK_YAW, - - FLYING, - - HAND_INV, - WIELD_INV, - WIELD_INDEX, + // General + ID, + + DIM, + POS, + VEL, + ROT, + SCALE, + + // Entities + DISPLAY, + VISUAL_OFF, + ANIM_RANGE, + ANIM_STATE, + + // Players + LOOK_OFF, + LOOK_PITCH, + LOOK_YAW, + + FLYING, + + HAND_INV, + WIELD_INV, + WIELD_INDEX, }; diff --git a/src/util/net/NetHandler.cpp b/src/util/net/NetHandler.cpp index c87a3450..04f2c809 100644 --- a/src/util/net/NetHandler.cpp +++ b/src/util/net/NetHandler.cpp @@ -14,130 +14,130 @@ NetHandler::NetHandler(const Address& hostAddress) : NetHandler(std::move(hostAddress), 3, 3) {} NetHandler::NetHandler(const Address& hostAddress, int attempts, int timeout) { - initClient(std::move(hostAddress), attempts, timeout); - initialized = true; + initClient(std::move(hostAddress), attempts, timeout); + initialized = true; } NetHandler::NetHandler(unsigned short port, short max_clients) { - initServer(port, max_clients); - if (state == NetState::ENET_ERROR) throw std::runtime_error("Failed to initialize ENet."); + initServer(port, max_clients); + if (state == NetState::ENET_ERROR) throw std::runtime_error("Failed to initialize ENet."); } void NetHandler::initServer(unsigned short port, short max_clients) { - state = NetState::HOST; - - if (enet_initialize() != 0) { - state = NetState::ENET_ERROR; - throw std::runtime_error("Failed to initialize ENet."); - } - - address.host = ENET_HOST_ANY; - address.port = port; - - host = enet_host_create(&address, (size_t)max_clients, PACKET_CHANNELS, 0, 0); - peer = nullptr; - - if (host == nullptr) { - state = NetState::ENET_ERROR; - throw std::runtime_error("Failed to create ENet host at port " + std::to_string(address.port) + "."); - } - - std::cout << Log::info << "Starting Zepha Server on port " << address.port << "." << Log::endl; + state = NetState::HOST; + + if (enet_initialize() != 0) { + state = NetState::ENET_ERROR; + throw std::runtime_error("Failed to initialize ENet."); + } + + address.host = ENET_HOST_ANY; + address.port = port; + + host = enet_host_create(&address, (size_t) max_clients, PACKET_CHANNELS, 0, 0); + peer = nullptr; + + if (host == nullptr) { + state = NetState::ENET_ERROR; + throw std::runtime_error("Failed to create ENet host at port " + std::to_string(address.port) + "."); + } + + std::cout << Log::info << "Starting Zepha Server on port " << address.port << "." << Log::endl; } void NetHandler::initClient(Address hostAddress, int attempts, int timeout) { - state = NetState::FAILED_CONNECT; - - if (enet_initialize() != 0) { - fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n"); - state = NetState::ENET_ERROR; - return; - } - - host = enet_host_create(nullptr, 1, PACKET_CHANNELS, 0, 0); - - if (host == nullptr) { - fprintf(stderr, "[FATAL] Failed to create ENet client.\n"); - state = NetState::ENET_ERROR; - return; - } - - enet_address_set_host(&address, hostAddress.host.c_str()); - address.port = hostAddress.port; - - int attempt = 0; - while (attempt++ < attempts) { - - peer = enet_host_connect(host, &address, PACKET_CHANNELS, 0); - - if (peer == nullptr) { - fprintf(stderr, "[FATAL] Failed to find ENet peer.\n"); - state = NetState::ENET_ERROR; - return; - } - - ENetEvent event; - if (enet_host_service(host, &event, (enet_uint32)timeout) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { - std::cout << Log::info << "Connected to " - << NetHandler::intToIPString(event.peer->address.host) - << ":" << event.peer->address.port << "." << Log::endl; - state = NetState::CLIENT; - break; - } - else { - enet_peer_reset(peer); - if (attempt < attempts) { - std::cout << Log::info << "Failed to connect to peer, retrying." << Log::endl; - } - } - } - - if (state == NetState::FAILED_CONNECT) { - std::cout << Log::err << "Failed to connect to peer." << Log::endl; - return; - } + state = NetState::FAILED_CONNECT; + + if (enet_initialize() != 0) { + fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n"); + state = NetState::ENET_ERROR; + return; + } + + host = enet_host_create(nullptr, 1, PACKET_CHANNELS, 0, 0); + + if (host == nullptr) { + fprintf(stderr, "[FATAL] Failed to create ENet client.\n"); + state = NetState::ENET_ERROR; + return; + } + + enet_address_set_host(&address, hostAddress.host.c_str()); + address.port = hostAddress.port; + + int attempt = 0; + while (attempt++ < attempts) { + + peer = enet_host_connect(host, &address, PACKET_CHANNELS, 0); + + if (peer == nullptr) { + fprintf(stderr, "[FATAL] Failed to find ENet peer.\n"); + state = NetState::ENET_ERROR; + return; + } + + ENetEvent event; + if (enet_host_service(host, &event, (enet_uint32) timeout) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { + std::cout << Log::info << "Connected to " + << NetHandler::intToIPString(event.peer->address.host) + << ":" << event.peer->address.port << "." << Log::endl; + state = NetState::CLIENT; + break; + } + else { + enet_peer_reset(peer); + if (attempt < attempts) { + std::cout << Log::info << "Failed to connect to peer, retrying." << Log::endl; + } + } + } + + if (state == NetState::FAILED_CONNECT) { + std::cout << Log::err << "Failed to connect to peer." << Log::endl; + return; + } } -bool NetHandler::update(ENetEvent *event) { - return enet_host_service(host, event, 0) > 0; +bool NetHandler::update(ENetEvent* event) { + return enet_host_service(host, event, 0) > 0; } NetState NetHandler::getState() { - return state; + return state; } ENetPeer* NetHandler::getPeer() { - return peer; + return peer; } void NetHandler::disconnect() { - if (state == NetState::CLIENT) { - std::cout << Log::info << "Disconnecting from host." << Log::endl; - enet_peer_disconnect(peer, 0); - enet_host_flush(host); - } - if (state != NetState::HOST) { - enet_host_destroy(host); - state = NetState::CLOSED; - } + if (state == NetState::CLIENT) { + std::cout << Log::info << "Disconnecting from host." << Log::endl; + enet_peer_disconnect(peer, 0); + enet_host_flush(host); + } + if (state != NetState::HOST) { + enet_host_destroy(host); + state = NetState::CLOSED; + } } NetHandler::~NetHandler() { - if (initialized) { - if (host != nullptr) { - disconnect(); - } - if (getState() != NetState::UNINITIALIZED) { - enet_deinitialize(); - } - } + if (initialized) { + if (host != nullptr) { + disconnect(); + } + if (getState() != NetState::UNINITIALIZED) { + enet_deinitialize(); + } + } } std::string NetHandler::intToIPString(unsigned int ip) { - std::ostringstream s; - s << ((ip ) & 0xFF) << "."; - s << ((ip >> 8 ) & 0xFF) << "."; - s << ((ip >> 16) & 0xFF) << "."; - s << ((ip >> 24) & 0xFF); - return s.str(); + std::ostringstream s; + s << ((ip) & 0xFF) << "."; + s << ((ip >> 8) & 0xFF) << "."; + s << ((ip >> 16) & 0xFF) << "."; + s << ((ip >> 24) & 0xFF); + return s.str(); } diff --git a/src/util/net/NetHandler.h b/src/util/net/NetHandler.h index 8ec1ae94..5fd0cb48 100644 --- a/src/util/net/NetHandler.h +++ b/src/util/net/NetHandler.h @@ -12,33 +12,38 @@ class Address; class NetHandler { -public: - NetHandler() = default; - explicit NetHandler(const Address& hostAddress); - NetHandler(const Address& hostAddress, int connection_attempts, int connection_timeout); - - NetHandler(unsigned short port, short max_clients); - - void disconnect(); - - NetState getState(); - ENetPeer* getPeer(); - bool update(ENetEvent* event); - - static std::string intToIPString(unsigned int ip); - - ~NetHandler(); - - const static int PACKET_CHANNELS = 12; -private: - void initServer(unsigned short port, short max_clients); - void initClient(Address hostAddress, int connection_attempts, int connection_timeout); - - bool initialized = false; //Not default constructed. - NetState state = NetState::UNINITIALIZED; - - ENetPeer* peer = nullptr; - ENetHost* host = nullptr; - - ENetAddress address {}; + public: + NetHandler() = default; + + explicit NetHandler(const Address& hostAddress); + + NetHandler(const Address& hostAddress, int connection_attempts, int connection_timeout); + + NetHandler(unsigned short port, short max_clients); + + void disconnect(); + + NetState getState(); + + ENetPeer* getPeer(); + + bool update(ENetEvent* event); + + static std::string intToIPString(unsigned int ip); + + ~NetHandler(); + + const static int PACKET_CHANNELS = 12; + private: + void initServer(unsigned short port, short max_clients); + + void initClient(Address hostAddress, int connection_attempts, int connection_timeout); + + bool initialized = false; //Not default constructed. + NetState state = NetState::UNINITIALIZED; + + ENetPeer* peer = nullptr; + ENetHost* host = nullptr; + + ENetAddress address{}; }; diff --git a/src/util/net/NetState.h b/src/util/net/NetState.h index d35b79e8..0d64694f 100644 --- a/src/util/net/NetState.h +++ b/src/util/net/NetState.h @@ -5,11 +5,11 @@ #pragma once enum class NetState { - UNINITIALIZED, - FAILED_CONNECT, - ENET_ERROR, - CLIENT, - HOST, - CLOSED + UNINITIALIZED, + FAILED_CONNECT, + ENET_ERROR, + CLIENT, + HOST, + CLOSED }; diff --git a/src/util/net/Packet.cpp b/src/util/net/Packet.cpp index 75e015f8..a0b5b601 100644 --- a/src/util/net/Packet.cpp +++ b/src/util/net/Packet.cpp @@ -9,18 +9,19 @@ Packet::Packet(Type type, bool reliable) : type(type), reliable(reliable) {} ENetPacket* Packet::toENetPacket() const { - std::string serialized = Serializer().append(static_cast(type)).data + data; - - ENetPacket* enet = enet_packet_create(serialized.data(), serialized.length(), (reliable ? ENET_PACKET_FLAG_RELIABLE : 0)); - return enet; + std::string serialized = Serializer().append(static_cast(type)).data + data; + + ENetPacket* enet = enet_packet_create(serialized.data(), serialized.length(), + (reliable ? ENET_PACKET_FLAG_RELIABLE : 0)); + return enet; } -void Packet::sendTo(ENetPeer *peer, Channel channel) const { - ENetPacket* enet = toENetPacket(); - enet_peer_send(peer, static_cast(channel), enet); +void Packet::sendTo(ENetPeer* peer, Channel channel) const { + ENetPacket* enet = toENetPacket(); + enet_peer_send(peer, static_cast(channel), enet); } -void Packet::sendTo(const ENetPeer &peer, Channel channel) const { - ENetPacket* enet = toENetPacket(); - enet_peer_send(const_cast(&peer), static_cast(channel), enet); +void Packet::sendTo(const ENetPeer& peer, Channel channel) const { + ENetPacket* enet = toENetPacket(); + enet_peer_send(const_cast(&peer), static_cast(channel), enet); } \ No newline at end of file diff --git a/src/util/net/Packet.h b/src/util/net/Packet.h index 47dcfa27..ed870674 100644 --- a/src/util/net/Packet.h +++ b/src/util/net/Packet.h @@ -10,45 +10,48 @@ #include class Packet { -public: - enum class Channel { - UNDEFINED = 0, - // Authentication - AUTH, CONNECT, - // Misc Server Information - SERVER, - // Data streams - WORLD, ENTITY, INTERACT - }; - - enum class Type { - UNDEFINED = 0, - // Information Request Types - BLOCK_IDENTIFIER_LIST, BIOME_IDENTIFIER_LIST, MOD_ORDER, - MODS, MEDIA, MEDIA_DONE, CONNECT_DATA_RECVD, - // Miscellaneous - SERVER_INFO, - // Player Info - PLAYER_ENT_INFO, THIS_PLAYER_INFO, - // World - CHUNK, MAPBLOCK, - // Block - BLOCK_HIT, BLOCK_PLACE, BLOCK_INTERACT, - BLOCK_PLACE_OR_INTERACT, BLOCK_SET, - // Entity - ENTITY_INFO, ENTITY_REMOVED, - // Inventory - INV_WATCH, INV_UNWATCH, INV_INVALID, INV_DATA, INV_INTERACT - }; - - Packet() = default; - explicit Packet(Type type, bool reliable = true); - - ENetPacket* toENetPacket() const; - void sendTo(ENetPeer* peer, Channel channel) const; - void sendTo(const ENetPeer &peer, Channel channel) const; - - Type type = Type::UNDEFINED; - std::string data {}; - bool reliable = true; + public: + enum class Channel { + UNDEFINED = 0, + // Authentication + AUTH, CONNECT, + // Misc Server Information + SERVER, + // Data streams + WORLD, ENTITY, INTERACT + }; + + enum class Type { + UNDEFINED = 0, + // Information Request Types + BLOCK_IDENTIFIER_LIST, BIOME_IDENTIFIER_LIST, MOD_ORDER, + MODS, MEDIA, MEDIA_DONE, CONNECT_DATA_RECVD, + // Miscellaneous + SERVER_INFO, + // Player Info + PLAYER_ENT_INFO, THIS_PLAYER_INFO, + // World + CHUNK, MAPBLOCK, + // Block + BLOCK_HIT, BLOCK_PLACE, BLOCK_INTERACT, + BLOCK_PLACE_OR_INTERACT, BLOCK_SET, + // Entity + ENTITY_INFO, ENTITY_REMOVED, + // Inventory + INV_WATCH, INV_UNWATCH, INV_INVALID, INV_DATA, INV_INTERACT + }; + + Packet() = default; + + explicit Packet(Type type, bool reliable = true); + + ENetPacket* toENetPacket() const; + + void sendTo(ENetPeer* peer, Channel channel) const; + + void sendTo(const ENetPeer& peer, Channel channel) const; + + Type type = Type::UNDEFINED; + std::string data{}; + bool reliable = true; }; \ No newline at end of file diff --git a/src/util/net/PacketView.cpp b/src/util/net/PacketView.cpp index 8e419dea..600aeccf 100644 --- a/src/util/net/PacketView.cpp +++ b/src/util/net/PacketView.cpp @@ -5,7 +5,7 @@ #include "PacketView.h" #include "Packet.h" -PacketView::PacketView(ENetPacket *packet) : - packet(packet, [](ENetPacket* p) { enet_packet_destroy(p); }), - d(reinterpret_cast(this->packet->data), this->packet->dataLength), - type(static_cast(d.read())) {} +PacketView::PacketView(ENetPacket* packet) : + packet(packet, [](ENetPacket* p) { enet_packet_destroy(p); }), + d(reinterpret_cast(this->packet->data), this->packet->dataLength), + type(static_cast(d.read())) {} diff --git a/src/util/net/PacketView.h b/src/util/net/PacketView.h index 76359f16..5cdd9488 100644 --- a/src/util/net/PacketView.h +++ b/src/util/net/PacketView.h @@ -11,11 +11,12 @@ #include "Packet.h" class PacketView { -public: - explicit PacketView(ENetPacket* packet); - PacketView(const PacketView&) = delete; - - std::shared_ptr packet; - Deserializer d; - Packet::Type type; + public: + explicit PacketView(ENetPacket* packet); + + PacketView(const PacketView&) = delete; + + std::shared_ptr packet; + Deserializer d; + Packet::Type type; }; diff --git a/src/util/net/Serializer.h b/src/util/net/Serializer.h index e41e3c2d..f49d02da 100644 --- a/src/util/net/Serializer.h +++ b/src/util/net/Serializer.h @@ -14,171 +14,209 @@ #include "Packet.h" class Serializer { -public: - std::string data {}; - - template inline Serializer& append(const T& elem) { throw std::runtime_error("Tried to append a non-serializable type"); }; - - template::value>::type> inline Serializer& appendE(const E& elem) { - append(static_cast(elem)); - return *this; - } - - Packet packet(Packet::Type p = Packet::Type::UNDEFINED, bool reliable = true) { - Packet packet(p, reliable); - packet.data = data; - return std::move(packet); - }; - -private: - typedef union { int in; char bytes[4]; } int_union; - typedef union { unsigned int in; char bytes[4]; } uint_union; - typedef union { short sh; char bytes[2]; } short_union; - typedef union { unsigned short sh; char bytes[2]; } ushort_union; - typedef union { float fl; char bytes[4]; } float_union; + public: + std::string data{}; + + template + inline Serializer& append(const T& elem) { throw std::runtime_error("Tried to append a non-serializable type"); }; + + template::value>::type> + inline Serializer& appendE(const E& elem) { + append(static_cast(elem)); + return *this; + } + + Packet packet(Packet::Type p = Packet::Type::UNDEFINED, bool reliable = true) { + Packet packet(p, reliable); + packet.data = data; + return std::move(packet); + }; + + private: + typedef union { + int in; + char bytes[4]; + } int_union; + typedef union { + unsigned int in; + char bytes[4]; + } uint_union; + typedef union { + short sh; + char bytes[2]; + } short_union; + typedef union { + unsigned short sh; + char bytes[2]; + } ushort_union; + typedef union { + float fl; + char bytes[4]; + } float_union; }; -template <> inline Serializer& Serializer::append(const int& elem) { - int_union cv = { elem }; - data += cv.bytes[0]; - data += cv.bytes[1]; - data += cv.bytes[2]; - data += cv.bytes[3]; - return *this; +template<> +inline Serializer& Serializer::append(const int& elem) { + int_union cv = { elem }; + data += cv.bytes[0]; + data += cv.bytes[1]; + data += cv.bytes[2]; + data += cv.bytes[3]; + return *this; } -template <> inline Serializer& Serializer::append(const unsigned int& elem) { - uint_union cv = { elem }; - data += cv.bytes[0]; - data += cv.bytes[1]; - data += cv.bytes[2]; - data += cv.bytes[3]; - return *this; +template<> +inline Serializer& Serializer::append(const unsigned int& elem) { + uint_union cv = { elem }; + data += cv.bytes[0]; + data += cv.bytes[1]; + data += cv.bytes[2]; + data += cv.bytes[3]; + return *this; } -template <> inline Serializer& Serializer::append(const short& elem) { - short_union cv = { elem }; - data += cv.bytes[0]; - data += cv.bytes[1]; - return *this; +template<> +inline Serializer& Serializer::append(const short& elem) { + short_union cv = { elem }; + data += cv.bytes[0]; + data += cv.bytes[1]; + return *this; } -template <> inline Serializer& Serializer::append(const unsigned short& elem) { - ushort_union cv = { elem }; - data += cv.bytes[0]; - data += cv.bytes[1]; - return *this; +template<> +inline Serializer& Serializer::append(const unsigned short& elem) { + ushort_union cv = { elem }; + data += cv.bytes[0]; + data += cv.bytes[1]; + return *this; } -template <> inline Serializer& Serializer::append(const char& elem) { - data += elem; - return *this; +template<> +inline Serializer& Serializer::append(const char& elem) { + data += elem; + return *this; } -template <> inline Serializer& Serializer::append(const unsigned char& elem) { - data += static_cast(elem); - return *this; +template<> +inline Serializer& Serializer::append(const unsigned char& elem) { + data += static_cast(elem); + return *this; } -template <> inline Serializer& Serializer::append(const bool& elem) { - append(elem); - return *this; +template<> +inline Serializer& Serializer::append(const bool& elem) { + append(elem); + return *this; } -template <> inline Serializer& Serializer::append(const float& elem) { - float_union cv = { elem }; - data += cv.bytes[0]; - data += cv.bytes[1]; - data += cv.bytes[2]; - data += cv.bytes[3]; - return *this; +template<> +inline Serializer& Serializer::append(const float& elem) { + float_union cv = { elem }; + data += cv.bytes[0]; + data += cv.bytes[1]; + data += cv.bytes[2]; + data += cv.bytes[3]; + return *this; } -template <> inline Serializer& Serializer::append(const std::string& elem) { - append(elem.length()); - data += elem; - return *this; +template<> +inline Serializer& Serializer::append(const std::string& elem) { + append(elem.length()); + data += elem; + return *this; } -template <> inline Serializer& Serializer::append(const glm::vec2& elem) { - append(elem.x); - append(elem.y); - return *this; +template<> +inline Serializer& Serializer::append(const glm::vec2& elem) { + append(elem.x); + append(elem.y); + return *this; } -template <> inline Serializer& Serializer::append(const glm::ivec2& elem) { - append(elem.x); - append(elem.y); - return *this; +template<> +inline Serializer& Serializer::append(const glm::ivec2& elem) { + append(elem.x); + append(elem.y); + return *this; } -template <> inline Serializer& Serializer::append(const glm::vec3& elem) { - append(elem.x); - append(elem.y); - append(elem.z); - return *this; +template<> +inline Serializer& Serializer::append(const glm::vec3& elem) { + append(elem.x); + append(elem.y); + append(elem.z); + return *this; } -template <> inline Serializer& Serializer::append(const glm::ivec3& elem) { - append(elem.x); - append(elem.y); - append(elem.z); - return *this; +template<> +inline Serializer& Serializer::append(const glm::ivec3& elem) { + append(elem.x); + append(elem.y); + append(elem.z); + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() * 4 + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() * 4 }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() * 4 + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() * 4 }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() * 4 + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() * 4 }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() * 4 + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() * 4 }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() * 2 + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() * 2 }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() * 2 + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() * 2 }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() * 2 + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() * 2 }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() * 2 + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() * 2 }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - data.reserve(data.length() + elem.size() * 4 + 4); - append(elem.size()); - data += std::string { reinterpret_cast(&elem[0]), elem.size() * 4 }; - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + data.reserve(data.length() + elem.size() * 4 + 4); + append(elem.size()); + data += std::string{ reinterpret_cast(&elem[0]), elem.size() * 4 }; + return *this; } -template <> inline Serializer& Serializer::append>(const std::vector& elem) { - append(elem.size()); - for (unsigned int i = 0; i < elem.size(); i++) { - append(elem[i]); - } - return *this; +template<> +inline Serializer& Serializer::append>(const std::vector& elem) { + append(elem.size()); + for (unsigned int i = 0; i < elem.size(); i++) { + append(elem[i]); + } + return *this; } \ No newline at end of file diff --git a/src/world/LocalWorld.cpp b/src/world/LocalWorld.cpp index c0f84899..d5d77be8 100644 --- a/src/world/LocalWorld.cpp +++ b/src/world/LocalWorld.cpp @@ -10,61 +10,61 @@ #include "client/stream/WorldInterpolationStream.h" LocalWorld::LocalWorld(SubgamePtr game, ServerConnection& conn, Renderer& renderer) : - World(game), - net(conn, *this), - renderer(renderer), - refs(std::make_shared(game, net)), - worldGenStream(std::make_shared(*game.l(), *this, 55)), - player(std::make_shared(game, *this, DimensionPtr(nullptr), renderer)) {} + World(game), + net(conn, *this), + renderer(renderer), + refs(std::make_shared(game, net)), + worldGenStream(std::make_shared(*game.l(), *this, 55)), + player(std::make_shared(game, *this, DimensionPtr(nullptr), renderer)) {} void LocalWorld::connect() { - net.init(Util::bind_this(&(*refs), &LocalInventoryRefs::packetReceived)); - refs->init(); + net.init(Util::bind_this(&(*refs), &LocalInventoryRefs::packetReceived)); + refs->init(); } bool LocalWorld::updatePlayerDimension() { - if (defaultDimension.empty()) return false; - player->setDim(getDefaultDimension()); - activeDimension = getDefaultDimension().l(); - return true; + if (defaultDimension.empty()) return false; + player->setDim(getDefaultDimension()); + activeDimension = getDefaultDimension().l(); + return true; } void LocalWorld::update(double delta) { - World::update(delta); - - if (*player) player.l()->update(renderer.window.input, delta, renderer.window.input.mouseDelta()); - refs->update(delta, net); - net.update(); - - auto finishedChunks = worldGenStream->update(); - mapBlocksInterpolated = finishedChunks->size() / 64; - for (const auto &chunk : *finishedChunks) commitChunk(chunk); + World::update(delta); + + if (*player) player.l()->update(renderer.window.input, delta, renderer.window.input.mouseDelta()); + refs->update(delta, net); + net.update(); + + auto finishedChunks = worldGenStream->update(); + mapBlocksInterpolated = finishedChunks->size() / 64; + for (const auto& chunk : *finishedChunks) commitChunk(chunk); } void LocalWorld::handleWorldPacket(std::unique_ptr p) { - worldGenStream->queuePacket(std::move(p)); + worldGenStream->queuePacket(std::move(p)); } void LocalWorld::handlePlayerEntPacket(std::unique_ptr p) { - if (!player) throw std::runtime_error("Received playerEnt info *before* the player was created."); - - unsigned int id = p->d.read(); - if (player->getId() == id) return; - - bool found = false; - for (auto& entity : getActiveDimension().l()->playerEntities) { - if (entity.getId() == id) { - entity.interpPos(p->d.read()); - entity.interpRotateZ(-p->d.read() + 90); - entity.interpRotateY(-p->d.read() + 90); - - found = true; - break; - } - } - if (found) return; - - //TODO: Reimplement player models. + if (!player) throw std::runtime_error("Received playerEnt info *before* the player was created."); + + unsigned int id = p->d.read(); + if (player->getId() == id) return; + + bool found = false; + for (auto& entity : getActiveDimension().l()->playerEntities) { + if (entity.getId() == id) { + entity.interpPos(p->d.read()); + entity.interpRotateZ(-p->d.read() + 90); + entity.interpRotateY(-p->d.read() + 90); + + found = true; + break; + } + } + if (found) return; + + //TODO: Reimplement player models. // auto playerModel = std::make_shared(); // playerModel->fromSerialized(static_cast(game).models.models["zeus:default:player"], // { static_cast(game).textures["zeus:default:player"] }); @@ -72,44 +72,44 @@ void LocalWorld::handlePlayerEntPacket(std::unique_ptr p) { } void LocalWorld::commitChunk(std::shared_ptr c) { - activeDimension->setChunk(std::move(c)); + activeDimension->setChunk(std::move(c)); } -DimensionPtr LocalWorld::createDimension(const std::string &identifier, std::unordered_set& biomes) { - auto mapGen = std::make_shared(**game, *this, 0 /* TODO: Get the seed here */, biomes); - dimensions.emplace_back(std::make_shared( - game, *this, identifier, this->dimensions.size(), std::move(mapGen))); - - DimensionPtr d = dimensions.back(); - return d; +DimensionPtr LocalWorld::createDimension(const std::string& identifier, std::unordered_set& biomes) { + auto mapGen = std::make_shared(**game, *this, 0 /* TODO: Get the seed here */, biomes); + dimensions.emplace_back(std::make_shared( + game, *this, identifier, this->dimensions.size(), std::move(mapGen))); + + DimensionPtr d = dimensions.back(); + return d; } DimensionPtr LocalWorld::getActiveDimension() { - return activeDimension; + return activeDimension; } void LocalWorld::setActiveDimension(DimensionPtr dim) { - this->activeDimension->deactivate(); - this->activeDimension = dim.l(); + this->activeDimension->deactivate(); + this->activeDimension = dim.l(); } ClientNetworkInterpreter& LocalWorld::getNet() { - return net; + return net; } PlayerPtr LocalWorld::getPlayer() { - return player; + return player; } InventoryRefsPtr LocalWorld::getRefs() { - return refs; + return refs; } -int LocalWorld::renderChunks(Renderer &renderer) { - return activeDimension->renderChunks(renderer); +int LocalWorld::renderChunks(Renderer& renderer) { + return activeDimension->renderChunks(renderer); } -void LocalWorld::renderEntities(Renderer &renderer) { - activeDimension->renderEntities(renderer); - player.l()->draw(renderer); +void LocalWorld::renderEntities(Renderer& renderer) { + activeDimension->renderEntities(renderer); + player.l()->draw(renderer); } diff --git a/src/world/LocalWorld.h b/src/world/LocalWorld.h index 6d96e6cc..c12c6a7d 100644 --- a/src/world/LocalWorld.h +++ b/src/world/LocalWorld.h @@ -10,46 +10,60 @@ #include "client/conn/ClientNetworkInterpreter.h" class Window; + class Renderer; + class LocalPlayer; + class LocalSubgame; + class LocalInventoryRefs; + class WorldInterpolationStream; class LocalWorld : public World { -public: - LocalWorld(SubgamePtr game, ServerConnection& conn, Renderer& window); - - void connect(); - bool updatePlayerDimension(); - void update(double delta) override; - - void handleWorldPacket(std::unique_ptr p); - void handlePlayerEntPacket(std::unique_ptr p); - void commitChunk(std::shared_ptr chunk); - - virtual DimensionPtr createDimension(const std::string& identifier, std::unordered_set& biomes) override; - - DimensionPtr getActiveDimension(); - void setActiveDimension(DimensionPtr); - - PlayerPtr getPlayer(); - virtual InventoryRefsPtr getRefs() override; - ClientNetworkInterpreter& getNet(); - - int renderChunks(Renderer &render); - void renderEntities(Renderer &renderer); - - int mapBlocksInterpolated = 0; - int lastMeshUpdates = 0; -private: - Renderer& renderer; - - ClientNetworkInterpreter net; - std::shared_ptr refs; - PlayerPtr player; - - std::shared_ptr activeDimension = nullptr; - - std::shared_ptr worldGenStream = nullptr; + public: + LocalWorld(SubgamePtr game, ServerConnection& conn, Renderer& window); + + void connect(); + + bool updatePlayerDimension(); + + void update(double delta) override; + + void handleWorldPacket(std::unique_ptr p); + + void handlePlayerEntPacket(std::unique_ptr p); + + void commitChunk(std::shared_ptr chunk); + + virtual DimensionPtr + createDimension(const std::string& identifier, std::unordered_set& biomes) override; + + DimensionPtr getActiveDimension(); + + void setActiveDimension(DimensionPtr); + + PlayerPtr getPlayer(); + + virtual InventoryRefsPtr getRefs() override; + + ClientNetworkInterpreter& getNet(); + + int renderChunks(Renderer& render); + + void renderEntities(Renderer& renderer); + + int mapBlocksInterpolated = 0; + int lastMeshUpdates = 0; + private: + Renderer& renderer; + + ClientNetworkInterpreter net; + std::shared_ptr refs; + PlayerPtr player; + + std::shared_ptr activeDimension = nullptr; + + std::shared_ptr worldGenStream = nullptr; }; diff --git a/src/world/ServerWorld.cpp b/src/world/ServerWorld.cpp index 071b6330..000bfe52 100644 --- a/src/world/ServerWorld.cpp +++ b/src/world/ServerWorld.cpp @@ -22,78 +22,79 @@ #include "server/stream/ServerPacketStream.h" ServerWorld::ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients) : - World(game), - seed(seed), - clients(clients), - refs(std::make_shared(game, clients)) { - - clients.init(this); - - generateOrder.reserve(mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.y * 2 + 1); - std::unordered_set found {}; - std::queue queue {}; - - queue.emplace(0, 0, 0); - found.emplace(0, 0, 0); - - const std::vector dirs { - glm::ivec3 {1, 0, 0}, glm::ivec3 {-1, 0, 0}, - glm::ivec3 {0, 1, 0}, glm::ivec3 {0, -1, 0}, - glm::ivec3 {0, 0, 1}, glm::ivec3 {0, 0, -1}}; - - while (!queue.empty()) { - glm::ivec3 pos = queue.front(); - queue.pop(); - - generateOrder.push_back(pos); - - for (auto dir : dirs) { - glm::ivec3 offset = pos + dir; - if (offset.x < -mapBlockGenRange.x || offset.x > mapBlockGenRange.x || - offset.y < -mapBlockGenRange.y || offset.y > mapBlockGenRange.y || - offset.z < -mapBlockGenRange.x || offset.z > mapBlockGenRange.x || - found.count(offset)) continue; - else { - found.insert(offset); - queue.push(offset); - } - } - } + World(game), + seed(seed), + clients(clients), + refs(std::make_shared(game, clients)) { + + clients.init(this); + + generateOrder.reserve(mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.y * 2 + 1); + std::unordered_set found{}; + std::queue queue{}; + + queue.emplace(0, 0, 0); + found.emplace(0, 0, 0); + + const std::vector dirs{ + glm::ivec3{ 1, 0, 0 }, glm::ivec3{ -1, 0, 0 }, + glm::ivec3{ 0, 1, 0 }, glm::ivec3{ 0, -1, 0 }, + glm::ivec3{ 0, 0, 1 }, glm::ivec3{ 0, 0, -1 }}; + + while (!queue.empty()) { + glm::ivec3 pos = queue.front(); + queue.pop(); + + generateOrder.push_back(pos); + + for (auto dir : dirs) { + glm::ivec3 offset = pos + dir; + if (offset.x < -mapBlockGenRange.x || offset.x > mapBlockGenRange.x || + offset.y < -mapBlockGenRange.y || offset.y > mapBlockGenRange.y || + offset.z < -mapBlockGenRange.x || offset.z > mapBlockGenRange.x || + found.count(offset)) + continue; + else { + found.insert(offset); + queue.push(offset); + } + } + } } void ServerWorld::init(const std::string& worldDir) { - genStream = std::make_unique(*game.s(), *this, seed); - packetStream = std::make_unique(*this); + genStream = std::make_unique(*game.s(), *this, seed); + packetStream = std::make_unique(*this); // fileManip = std::make_shared("worlds/" + worldDir + "/"); } void ServerWorld::update(double delta) { - World::update(delta); - refs->update(); - - unsigned int genCount = 0; - std::unordered_set updatedChunks {}; - - auto finishedGen = genStream->update(); - for (auto& data : *finishedGen) { - for (const auto& pos : *data.created) - updatedChunks.insert(glm::ivec4(pos, data.dim)); - - // Mapblock might have been pruned in between generation assignment and now. - auto mb = getDimension(data.dim)->getMapBlock(glm::ivec3(data.pos)); - if (mb) mb->generated = true; - - packetStream->queue(data.dim, data.pos); - genCount++; - } - - auto finishedPackets = packetStream->update(); - for (auto& data : *finishedPackets) { - for (auto& player : clients.players) - data->packet->sendTo(player->getPeer(), Packet::Channel::WORLD); - } - - this->generatedMapBlocks = genCount; + World::update(delta); + refs->update(); + + unsigned int genCount = 0; + std::unordered_set updatedChunks{}; + + auto finishedGen = genStream->update(); + for (auto& data : *finishedGen) { + for (const auto& pos : *data.created) + updatedChunks.insert(glm::ivec4(pos, data.dim)); + + // Mapblock might have been pruned in between generation assignment and now. + auto mb = getDimension(data.dim)->getMapBlock(glm::ivec3(data.pos)); + if (mb) mb->generated = true; + + packetStream->queue(data.dim, data.pos); + genCount++; + } + + auto finishedPackets = packetStream->update(); + for (auto& data : *finishedPackets) { + for (auto& player : clients.players) + data->packet->sendTo(player->getPeer(), Packet::Channel::WORLD); + } + + this->generatedMapBlocks = genCount; // for (auto& chunkPos : updatedChunks) { // glm::ivec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos); @@ -122,117 +123,117 @@ void ServerWorld::update(double delta) { // if (isInBounds(chunkPos, bounds)) p.sendTo(client->peer, PacketChannel::WORLD); // } // } - - Packet r = Serializer().append(this->generatedMapBlocks).packet(Packet::Type::SERVER_INFO); - - for (auto& player : clients.players) { - r.sendTo(player->getPeer(), Packet::Channel::SERVER); - if (player->changedMapBlocks) changedMapBlocks(*player); - } - - for (auto& d : dimensions) { - auto dimension = std::static_pointer_cast(d); - unsigned int ind = dimension->getInd(); - - // Update clients with new entity information. - - Serializer inf; - inf.append(ind); - - for (auto& entity : dimension->getLuaEntities()) { - auto str = entity.entity.s()->serialize(); - if (!str.empty()) inf.append(str); - } - - if (inf.data.size() > 4) { - auto p = inf.packet(Packet::Type::ENTITY_INFO); - for (auto& player : clients.players) - if (player->getDim()->getInd() == ind) - p.sendTo(player->getPeer(), Packet::Channel::ENTITY); - } - - // Update clients with removed entities. - - Serializer rem; - rem.append(ind); - - for (unsigned int entity : dimension->getRemovedEntities()) { - rem.append(entity); - } - - if (rem.data.size() > 4) { - Packet p = rem.packet(Packet::Type::ENTITY_REMOVED); - for (auto& player : clients.players) - if (player->getDim()->getInd() == ind) - p.sendTo(player->getPeer(), Packet::Channel::ENTITY); - } - - dimension->clearRemovedEntities(); - } + + Packet r = Serializer().append(this->generatedMapBlocks).packet(Packet::Type::SERVER_INFO); + + for (auto& player : clients.players) { + r.sendTo(player->getPeer(), Packet::Channel::SERVER); + if (player->changedMapBlocks) changedMapBlocks(*player); + } + + for (auto& d : dimensions) { + auto dimension = std::static_pointer_cast(d); + unsigned int ind = dimension->getInd(); + + // Update clients with new entity information. + + Serializer inf; + inf.append(ind); + + for (auto& entity : dimension->getLuaEntities()) { + auto str = entity.entity.s()->serialize(); + if (!str.empty()) inf.append(str); + } + + if (inf.data.size() > 4) { + auto p = inf.packet(Packet::Type::ENTITY_INFO); + for (auto& player : clients.players) + if (player->getDim()->getInd() == ind) + p.sendTo(player->getPeer(), Packet::Channel::ENTITY); + } + + // Update clients with removed entities. + + Serializer rem; + rem.append(ind); + + for (unsigned int entity : dimension->getRemovedEntities()) { + rem.append(entity); + } + + if (rem.data.size() > 4) { + Packet p = rem.packet(Packet::Type::ENTITY_REMOVED); + for (auto& player : clients.players) + if (player->getDim()->getInd() == ind) + p.sendTo(player->getPeer(), Packet::Channel::ENTITY); + } + + dimension->clearRemovedEntities(); + } } -DimensionPtr ServerWorld::createDimension(const std::string &identifier, std::unordered_set& biomes) { - auto mapGen = std::make_shared(**game, *this, seed, biomes); - dimensions.emplace_back(std::make_shared( - game, *this, identifier, this->dimensions.size(), std::move(mapGen))); - - DimensionPtr d = dimensions.back(); - return d; +DimensionPtr ServerWorld::createDimension(const std::string& identifier, std::unordered_set& biomes) { + auto mapGen = std::make_shared(**game, *this, seed, biomes); + dimensions.emplace_back(std::make_shared( + game, *this, identifier, this->dimensions.size(), std::move(mapGen))); + + DimensionPtr d = dimensions.back(); + return d; } DimensionPtr ServerWorld::getDimension(unsigned int index) { - return dimensions[index]; + return dimensions[index]; } -DimensionPtr ServerWorld::getDimension(const std::string &identifier) { - for (auto& dimension : dimensions) - if (dimension->getIdentifier() == identifier) return dimension; - throw std::runtime_error("No dimension named " + identifier + " found."); +DimensionPtr ServerWorld::getDimension(const std::string& identifier) { + for (auto& dimension : dimensions) + if (dimension->getIdentifier() == identifier) return dimension; + throw std::runtime_error("No dimension named " + identifier + " found."); } InventoryRefsPtr ServerWorld::getRefs() { - return InventoryRefsPtr(refs); + return InventoryRefsPtr(refs); } ServerClients& ServerWorld::getClients() { - return clients; + return clients; } void ServerWorld::changedMapBlocks(ServerPlayer& player) { - generateMapBlocks(player); - sendChunksToPlayer(player); - player.changedMapBlocks = false; + generateMapBlocks(player); + sendChunksToPlayer(player); + player.changedMapBlocks = false; } void ServerWorld::generateMapBlocks(ServerPlayer& player) { - unsigned int generating = 0; - glm::ivec3 playerMapBlock = Space::MapBlock::world::fromBlock(player.getPos()); - - for (const auto &c : generateOrder) { - glm::ivec3 mapBlockPos = playerMapBlock + c; - generating += generateMapBlock(player.getDim()->getInd(), mapBlockPos); - } - - std::cout << "Player moved, generating " << generating << " MapBlocks." << std::endl; + unsigned int generating = 0; + glm::ivec3 playerMapBlock = Space::MapBlock::world::fromBlock(player.getPos()); + + for (const auto& c : generateOrder) { + glm::ivec3 mapBlockPos = playerMapBlock + c; + generating += generateMapBlock(player.getDim()->getInd(), mapBlockPos); + } + + std::cout << "Player moved, generating " << generating << " MapBlocks." << std::endl; } bool ServerWorld::generateMapBlock(unsigned int dim, glm::ivec3 pos) { - auto dimension = getDimension(dim); - if(!dimension->getMapBlock(pos) || !dimension->getMapBlock(pos)->generated) return genStream->queue(dim, pos); - return false; + auto dimension = getDimension(dim); + if (!dimension->getMapBlock(pos) || !dimension->getMapBlock(pos)->generated) return genStream->queue(dim, pos); + return false; } void ServerWorld::sendChunksToPlayer(ServerPlayer& client) { - glm::ivec3 playerPos = Space::MapBlock::world::fromBlock(client.getPos()); - glm::ivec3 lastPlayerPos = Space::MapBlock::world::fromBlock(client.lastPos); - - Bounds newBounds = { playerPos - glm::ivec3 { sendRange.x, sendRange.y, sendRange.x }, - playerPos + glm::ivec3 { sendRange.x, sendRange.y, sendRange.x }}; - Bounds oldBounds = { lastPlayerPos - glm::ivec3 { sendRange.x, sendRange.y, sendRange.x }, - lastPlayerPos + glm::ivec3 { sendRange.x, sendRange.y, sendRange.x }}; - - for (auto& pos : generateOrder) { - if (oldBounds.intersects(playerPos + pos) || !newBounds.intersects(playerPos + pos)) continue; - packetStream->queue(client.getDim()->getInd(), pos + playerPos); - } + glm::ivec3 playerPos = Space::MapBlock::world::fromBlock(client.getPos()); + glm::ivec3 lastPlayerPos = Space::MapBlock::world::fromBlock(client.lastPos); + + Bounds newBounds = { playerPos - glm::ivec3{ sendRange.x, sendRange.y, sendRange.x }, + playerPos + glm::ivec3{ sendRange.x, sendRange.y, sendRange.x }}; + Bounds oldBounds = { lastPlayerPos - glm::ivec3{ sendRange.x, sendRange.y, sendRange.x }, + lastPlayerPos + glm::ivec3{ sendRange.x, sendRange.y, sendRange.x }}; + + for (auto& pos : generateOrder) { + if (oldBounds.intersects(playerPos + pos) || !newBounds.intersects(playerPos + pos)) continue; + packetStream->queue(client.getDim()->getInd(), pos + playerPos); + } } \ No newline at end of file diff --git a/src/world/ServerWorld.h b/src/world/ServerWorld.h index 2f3d4333..f5b19deb 100644 --- a/src/world/ServerWorld.h +++ b/src/world/ServerWorld.h @@ -11,50 +11,64 @@ #include "world/dim/ServerDimension.h" class Target; + class ItemStack; + class ServerClients; + class ServerPlayer; + class ServerInventoryRefs; + class ServerSubgame; + class ServerGenStream; + class ServerPacketStream; class ServerWorld : public World { -public: - explicit ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients); - - void init(const std::string& worldDir); - void update(double delta) override; - - virtual DimensionPtr createDimension(const std::string& identifier, std::unordered_set& biomes) override; - - virtual DimensionPtr getDimension(unsigned int index) override; - virtual DimensionPtr getDimension(const std::string& identifier) override; - - virtual InventoryRefsPtr getRefs() override; - virtual ServerClients& getClients(); -private: - void changedMapBlocks(ServerPlayer& player); - - bool generateMapBlock(unsigned int dim, glm::ivec3 pos); - void generateMapBlocks(ServerPlayer& player); - void sendChunksToPlayer(ServerPlayer& client); - - std::shared_ptr genStream = nullptr; - std::shared_ptr packetStream = nullptr; - - unsigned int seed; - ServerClients& clients; - std::shared_ptr refs; + public: + explicit ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients); + + void init(const std::string& worldDir); + + void update(double delta) override; + + virtual DimensionPtr + createDimension(const std::string& identifier, std::unordered_set& biomes) override; + + virtual DimensionPtr getDimension(unsigned int index) override; + + virtual DimensionPtr getDimension(const std::string& identifier) override; + + virtual InventoryRefsPtr getRefs() override; + + virtual ServerClients& getClients(); + + private: + void changedMapBlocks(ServerPlayer& player); + + bool generateMapBlock(unsigned int dim, glm::ivec3 pos); + + void generateMapBlocks(ServerPlayer& player); + + void sendChunksToPlayer(ServerPlayer& client); + + std::shared_ptr genStream = nullptr; + std::shared_ptr packetStream = nullptr; + + unsigned int seed; + ServerClients& clients; + std::shared_ptr refs; // std::string worldDir; // std::shared_ptr fileManip; - - unsigned int generatedMapBlocks = 0; - std::vector generateOrder; - - const glm::ivec2 mapBlockGenRange = {4, 4}; - const glm::ivec2 sendRange = {4, 4}; - const glm::ivec2 activeChunkRange = {16, 16}; + + unsigned int generatedMapBlocks = 0; + std::vector generateOrder; + + const glm::ivec2 mapBlockGenRange = { 4, 4 }; + const glm::ivec2 sendRange = { 4, 4 }; + const glm::ivec2 activeChunkRange = { 16, 16 }; }; diff --git a/src/world/World.cpp b/src/world/World.cpp index 79b15379..1b7a3c45 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -11,23 +11,23 @@ World::World(SubgamePtr game) : game(game) {} void World::update(double delta) { - for (auto& dimension : dimensions) dimension->update(delta); + for (auto& dimension : dimensions) dimension->update(delta); } DimensionPtr World::getDefaultDimension() { - if (defaultDimension.empty()) throw std::runtime_error("No default dimension was set."); - return getDimension(defaultDimension); + if (defaultDimension.empty()) throw std::runtime_error("No default dimension was set."); + return getDimension(defaultDimension); } void World::setDefaultDimension(const std::string& identifier) { - defaultDimension = identifier; + defaultDimension = identifier; } DimensionPtr World::getDimension(unsigned int index) { - return dimensions[index]; + return dimensions[index]; } -DimensionPtr World::getDimension(const std::string &identifier) { - for (auto& dimension : dimensions) if (dimension->getIdentifier() == identifier) return dimension; - throw std::runtime_error("No dimension named " + identifier + " found."); +DimensionPtr World::getDimension(const std::string& identifier) { + for (auto& dimension : dimensions) if (dimension->getIdentifier() == identifier) return dimension; + throw std::runtime_error("No dimension named " + identifier + " found."); } diff --git a/src/world/World.h b/src/world/World.h index 83c58d7c..50902cb8 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -12,27 +12,32 @@ #include "util/CovariantPtr.h" class Subgame; + class Dimension; class World { -public: - World(const World& o) = delete; - explicit World(SubgamePtr game); - - virtual void update(double delta); - - virtual DimensionPtr createDimension(const std::string& identifier, std::unordered_set& biomes) = 0; - - virtual DimensionPtr getDefaultDimension(); - virtual void setDefaultDimension(const std::string& defaultDimension); - - virtual DimensionPtr getDimension(unsigned int index); - virtual DimensionPtr getDimension(const std::string& identifier); - - virtual InventoryRefsPtr getRefs() = 0; -protected: - std::string defaultDimension {}; - std::vector> dimensions; - - SubgamePtr game; + public: + World(const World& o) = delete; + + explicit World(SubgamePtr game); + + virtual void update(double delta); + + virtual DimensionPtr createDimension(const std::string& identifier, std::unordered_set& biomes) = 0; + + virtual DimensionPtr getDefaultDimension(); + + virtual void setDefaultDimension(const std::string& defaultDimension); + + virtual DimensionPtr getDimension(unsigned int index); + + virtual DimensionPtr getDimension(const std::string& identifier); + + virtual InventoryRefsPtr getRefs() = 0; + + protected: + std::string defaultDimension{}; + std::vector> dimensions; + + SubgamePtr game; }; diff --git a/src/world/dim/Dimension.cpp b/src/world/dim/Dimension.cpp index 5fa15b86..8ec25e6f 100644 --- a/src/world/dim/Dimension.cpp +++ b/src/world/dim/Dimension.cpp @@ -10,34 +10,34 @@ #include "game/atlas/DefinitionAtlas.h" bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) { - auto l = getReadLock(); - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - l.unlock(); - - if (!chunk) return false; - - if (!DimensionBase::setBlock(pos, block)) return false; - - auto &def = game->getDefs().blockFromId(block); - - glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos)); - glm::ivec3 newLight = def.lightSource; - - if (oldLight.x + oldLight.y + oldLight.z != 0) removeBlockLight(pos); - if (newLight.x + newLight.y + newLight.z != 0) addBlockLight(pos, newLight); - - if (def.lightPropagates) reflowLight(pos); - - if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) removeSunlight(pos); - - propogateRemoveNodes(); - - return true; + auto l = getReadLock(); + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + l.unlock(); + + if (!chunk) return false; + + if (!DimensionBase::setBlock(pos, block)) return false; + + auto& def = game->getDefs().blockFromId(block); + + glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos)); + glm::ivec3 newLight = def.lightSource; + + if (oldLight.x + oldLight.y + oldLight.z != 0) removeBlockLight(pos); + if (newLight.x + newLight.y + newLight.z != 0) addBlockLight(pos, newLight); + + if (def.lightPropagates) reflowLight(pos); + + if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) removeSunlight(pos); + + propogateRemoveNodes(); + + return true; } unsigned int Dimension::nextEntityInd() { - auto _ = getWriteLock(); - return entityInd++; + auto _ = getWriteLock(); + return entityInd++; } //std::unordered_set Dimension::calculateEdgeLight(glm::ivec3 mbPos) { @@ -68,219 +68,224 @@ unsigned int Dimension::nextEntityInd() { //} std::unordered_set Dimension::propogateAddNodes() { - std::unordered_set chunksUpdated {}; - - for (unsigned int channel = 0; channel < 4; channel++) { - while (true) { - auto l = getWriteLock(); - if (lightAddQueue[channel].empty()) break; - LightAddNode node = lightAddQueue[channel].front(); - lightAddQueue[channel].pop(); - l.unlock(); - - Chunk* chunk = node.chunk; - if (!chunksUpdated.count(chunk->getPos())) chunksUpdated.insert(chunk->getPos()); - - unsigned char lightLevel = node.chunk->getLight(node.index, channel); - glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index); - - for (const auto& i : Vec::TO_VEC) { - glm::ivec3 check = worldPos + i; - unsigned int ind = Space::Block::index(check); - Chunk* chunk; - if (containsWorldPos(node.chunk, check)) chunk = node.chunk; - else { - chunk = getChunk(Space::Chunk::world::fromBlock(check)).get(); - if (!chunk) continue; - if (!chunksUpdated.count(chunk->getPos())) { - chunksUpdated.insert(chunk->getPos()); - chunk->setDirty(true); - } - } - - bool sunDown = (channel == SUNLIGHT_CHANNEL && lightLevel == 15 && i.y == -1); - if (game->getDefs().blockFromId(chunk->getBlock(ind)).lightPropagates && (sunDown || chunk->getLight(ind, channel) + 2 <= lightLevel)) { - int subtract = sunDown ? 0 : 1; - chunk->setLight(ind, channel, lightLevel - subtract); - - l.lock(); - lightAddQueue[channel].emplace(ind, chunk); - l.unlock(); - } - } - } - } - - return chunksUpdated; + std::unordered_set chunksUpdated{}; + + for (unsigned int channel = 0; channel < 4; channel++) { + while (true) { + auto l = getWriteLock(); + if (lightAddQueue[channel].empty()) break; + LightAddNode node = lightAddQueue[channel].front(); + lightAddQueue[channel].pop(); + l.unlock(); + + Chunk* chunk = node.chunk; + if (!chunksUpdated.count(chunk->getPos())) chunksUpdated.insert(chunk->getPos()); + + unsigned char lightLevel = node.chunk->getLight(node.index, channel); + glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index); + + for (const auto& i : Vec::TO_VEC) { + glm::ivec3 check = worldPos + i; + unsigned int ind = Space::Block::index(check); + Chunk* chunk; + if (containsWorldPos(node.chunk, check)) chunk = node.chunk; + else { + chunk = getChunk(Space::Chunk::world::fromBlock(check)).get(); + if (!chunk) continue; + if (!chunksUpdated.count(chunk->getPos())) { + chunksUpdated.insert(chunk->getPos()); + chunk->setDirty(true); + } + } + + bool sunDown = (channel == SUNLIGHT_CHANNEL && lightLevel == 15 && i.y == -1); + if (game->getDefs().blockFromId(chunk->getBlock(ind)).lightPropagates && + (sunDown || chunk->getLight(ind, channel) + 2 <= lightLevel)) { + int subtract = sunDown ? 0 : 1; + chunk->setLight(ind, channel, lightLevel - subtract); + + l.lock(); + lightAddQueue[channel].emplace(ind, chunk); + l.unlock(); + } + } + } + } + + return chunksUpdated; } std::unordered_set Dimension::propogateRemoveNodes() { - std::unordered_set chunksUpdated {}; - - for (unsigned int channel = 0; channel < 4; channel++) { - while (true) { - auto l = getWriteLock(); - if (lightRemoveQueue[channel].empty()) break; - LightRemoveNode node = lightRemoveQueue[channel].front(); - lightRemoveQueue[channel].pop(); - l.unlock(); - - glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index); - - for (const auto& i : Vec::TO_VEC) { - glm::ivec3 check = worldPos + i; - unsigned int ind = Space::Block::index(check); - Chunk* chunk; - if (containsWorldPos(node.chunk, check)) chunk = node.chunk; - else { - chunk = getChunk(Space::Chunk::world::fromBlock(check)).get(); - if (!chunk) continue; - if (!chunksUpdated.count(chunk->getPos())) { - chunksUpdated.insert(chunk->getPos()); - chunk->setDirty(true); - } - } - - unsigned char checkLight = chunk->getLight(ind, channel); - if (checkLight != 0 && (checkLight < node.value || (channel == SUNLIGHT_CHANNEL && i.y == -1 && node.value == 15))) { - unsigned int replaceLight = (channel == SUNLIGHT_CHANNEL ? 0 : - game->getDefs().blockFromId(chunk->getBlock(Space::Block::index(check))).lightSource[channel]); - chunk->setLight(ind, channel, replaceLight); - - l.lock(); - if (replaceLight) lightAddQueue[channel].emplace(ind, chunk); - lightRemoveQueue[channel].emplace(ind, checkLight, chunk); - l.unlock(); - } - else if (checkLight >= node.value) { - auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get(); - if (!chunk) continue; - - l.lock(); - lightAddQueue[channel].emplace(ind, chunk); - l.unlock(); - } - } - } - } - - auto otherChunksUpdated = propogateAddNodes(); - chunksUpdated.insert(otherChunksUpdated.begin(), otherChunksUpdated.end()); - - return chunksUpdated; + std::unordered_set chunksUpdated{}; + + for (unsigned int channel = 0; channel < 4; channel++) { + while (true) { + auto l = getWriteLock(); + if (lightRemoveQueue[channel].empty()) break; + LightRemoveNode node = lightRemoveQueue[channel].front(); + lightRemoveQueue[channel].pop(); + l.unlock(); + + glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index); + + for (const auto& i : Vec::TO_VEC) { + glm::ivec3 check = worldPos + i; + unsigned int ind = Space::Block::index(check); + Chunk* chunk; + if (containsWorldPos(node.chunk, check)) chunk = node.chunk; + else { + chunk = getChunk(Space::Chunk::world::fromBlock(check)).get(); + if (!chunk) continue; + if (!chunksUpdated.count(chunk->getPos())) { + chunksUpdated.insert(chunk->getPos()); + chunk->setDirty(true); + } + } + + unsigned char checkLight = chunk->getLight(ind, channel); + if (checkLight != 0 && + (checkLight < node.value || (channel == SUNLIGHT_CHANNEL && i.y == -1 && node.value == 15))) { + unsigned int replaceLight = (channel == SUNLIGHT_CHANNEL ? 0 : + game->getDefs().blockFromId( + chunk->getBlock(Space::Block::index(check))).lightSource[channel]); + chunk->setLight(ind, channel, replaceLight); + + l.lock(); + if (replaceLight) lightAddQueue[channel].emplace(ind, chunk); + lightRemoveQueue[channel].emplace(ind, checkLight, chunk); + l.unlock(); + } + else if (checkLight >= node.value) { + auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk( + Space::Chunk::world::fromBlock(check)).get(); + if (!chunk) continue; + + l.lock(); + lightAddQueue[channel].emplace(ind, chunk); + l.unlock(); + } + } + } + } + + auto otherChunksUpdated = propogateAddNodes(); + chunksUpdated.insert(otherChunksUpdated.begin(), otherChunksUpdated.end()); + + return chunksUpdated; } -bool Dimension::containsWorldPos(Chunk *chunk, glm::ivec3 pos) { - return chunk && Space::Chunk::world::fromBlock(pos) == chunk->getPos(); +bool Dimension::containsWorldPos(Chunk* chunk, glm::ivec3 pos) { + return chunk && Space::Chunk::world::fromBlock(pos) == chunk->getPos(); } -glm::ivec4 Dimension::getLight(glm::ivec3 worldPos, Chunk *chunk) { - if (containsWorldPos(chunk, worldPos)) return chunk->getLight(Space::Block::index(worldPos)); - auto oChunk = getChunk(Space::Chunk::world::fromBlock(worldPos)).get(); - return (oChunk ? oChunk->getLight(Space::Block::index(worldPos)) : glm::ivec4 {}); +glm::ivec4 Dimension::getLight(glm::ivec3 worldPos, Chunk* chunk) { + if (containsWorldPos(chunk, worldPos)) return chunk->getLight(Space::Block::index(worldPos)); + auto oChunk = getChunk(Space::Chunk::world::fromBlock(worldPos)).get(); + return (oChunk ? oChunk->getLight(Space::Block::index(worldPos)) : glm::ivec4{}); } void Dimension::calculateHorizontalEdge(std::shared_ptr a, std::shared_ptr b) { - for (unsigned int j = 0; j < 256; j++) { - glm::ivec3 diff = a->getPos() - b->getPos(); - - glm::ivec3 aPos = { - (diff.x == 0 ? j % 16 : diff.x == 1 ? 0 : 15), j / 16, - (diff.z == 0 ? j % 16 : diff.z == 1 ? 0 : 15) }; - glm::ivec3 bPos = { - (diff.x == 0 ? j % 16 : diff.x == 1 ? 15 : 0), j / 16, - (diff.z == 0 ? j % 16 : diff.z == 1 ? 15 : 0) }; - - auto lightA = a->getLight(Space::Block::index(aPos), 3); - auto lightB = b->getLight(Space::Block::index(bPos), 3); - - if (lightA > lightB + 1) setAndReflowSunlight(b->getPos() * 16 + bPos, lightA - 1); - else if (lightB > lightA + 1) setAndReflowSunlight(a->getPos() * 16 + aPos, lightB - 1); - } + for (unsigned int j = 0; j < 256; j++) { + glm::ivec3 diff = a->getPos() - b->getPos(); + + glm::ivec3 aPos = { + (diff.x == 0 ? j % 16 : diff.x == 1 ? 0 : 15), j / 16, + (diff.z == 0 ? j % 16 : diff.z == 1 ? 0 : 15) }; + glm::ivec3 bPos = { + (diff.x == 0 ? j % 16 : diff.x == 1 ? 15 : 0), j / 16, + (diff.z == 0 ? j % 16 : diff.z == 1 ? 15 : 0) }; + + auto lightA = a->getLight(Space::Block::index(aPos), 3); + auto lightB = b->getLight(Space::Block::index(bPos), 3); + + if (lightA > lightB + 1) setAndReflowSunlight(b->getPos() * 16 + bPos, lightA - 1); + else if (lightB > lightA + 1) setAndReflowSunlight(a->getPos() * 16 + aPos, lightB - 1); + } } void Dimension::calculateVerticalEdge(std::shared_ptr above, std::shared_ptr below) { - for (unsigned int j = 0; j < 256; j++) { - unsigned int xx = j / 16; - unsigned int zz = j % 16; - - auto lightAbove = above->getLight(Space::Block::index({xx, 0, zz}), 3); - auto lightBelow = below->getLight(Space::Block::index({xx, 15, zz}), 3); - - if (lightBelow > lightAbove) removeSunlight(below->getPos() * 16 + glm::ivec3{xx, 15, zz}); - } + for (unsigned int j = 0; j < 256; j++) { + unsigned int xx = j / 16; + unsigned int zz = j % 16; + + auto lightAbove = above->getLight(Space::Block::index({ xx, 0, zz }), 3); + auto lightBelow = below->getLight(Space::Block::index({ xx, 15, zz }), 3); + + if (lightBelow > lightAbove) removeSunlight(below->getPos() * 16 + glm::ivec3{ xx, 15, zz }); + } } void Dimension::addBlockLight(glm::ivec3 pos, glm::ivec3 light) { - auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos)); - auto ind = Space::Block::index(pos); - - startChunk->setLight(ind, 0, light.x); - startChunk->setLight(ind, 1, light.y); - startChunk->setLight(ind, 2, light.z); - - auto _ = getWriteLock(); - lightAddQueue[0].emplace(ind, startChunk.get()); - lightAddQueue[1].emplace(ind, startChunk.get()); - lightAddQueue[2].emplace(ind, startChunk.get()); + auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos)); + auto ind = Space::Block::index(pos); + + startChunk->setLight(ind, 0, light.x); + startChunk->setLight(ind, 1, light.y); + startChunk->setLight(ind, 2, light.z); + + auto _ = getWriteLock(); + lightAddQueue[0].emplace(ind, startChunk.get()); + lightAddQueue[1].emplace(ind, startChunk.get()); + lightAddQueue[2].emplace(ind, startChunk.get()); } void Dimension::removeBlockLight(glm::ivec3 pos) { - auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos)); - unsigned int ind = Space::Block::index(pos); - glm::ivec4 val = startChunk->getLight(ind); - - startChunk->setLight(ind, 0, 0); - startChunk->setLight(ind, 1, 0); - startChunk->setLight(ind, 2, 0); - - auto _ = getWriteLock(); - lightRemoveQueue[0].emplace(ind, val.x, startChunk.get()); - lightRemoveQueue[1].emplace(ind, val.y, startChunk.get()); - lightRemoveQueue[2].emplace(ind, val.z, startChunk.get()); + auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos)); + unsigned int ind = Space::Block::index(pos); + glm::ivec4 val = startChunk->getLight(ind); + + startChunk->setLight(ind, 0, 0); + startChunk->setLight(ind, 1, 0); + startChunk->setLight(ind, 2, 0); + + auto _ = getWriteLock(); + lightRemoveQueue[0].emplace(ind, val.x, startChunk.get()); + lightRemoveQueue[1].emplace(ind, val.y, startChunk.get()); + lightRemoveQueue[2].emplace(ind, val.z, startChunk.get()); } void Dimension::reflowLight(glm::ivec3 pos) { - glm::ivec4 placeLight {}; - const static std::array checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} }; - - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - auto ind = Space::Block::index(pos); - if (!chunk) return; - - for (const auto& i : checks) { - glm::ivec3 check = pos + i; - auto adjLight = getLight(check, chunk.get()); - placeLight.x = fmax(placeLight.x, adjLight.x - 1); - placeLight.y = fmax(placeLight.y, adjLight.y - 1); - placeLight.z = fmax(placeLight.z, adjLight.z - 1); - placeLight.w = fmax(placeLight.w, adjLight.w - (i.y == 1 ? 0 : 1)); - } - - chunk->setLight(ind, placeLight); - - auto _ = getWriteLock(); - lightAddQueue[0].emplace(ind, chunk.get()); - lightAddQueue[1].emplace(ind, chunk.get()); - lightAddQueue[2].emplace(ind, chunk.get()); - lightAddQueue[3].emplace(ind, chunk.get()); + glm::ivec4 placeLight{}; + const static std::array checks = { glm::ivec3{ -1, 0, 0 }, { 1, 0, 0 }, { 0, -1, 0 }, { 0, 1, 0 }, + { 0, 0, -1 }, { 0, 0, 1 }}; + + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + auto ind = Space::Block::index(pos); + if (!chunk) return; + + for (const auto& i : checks) { + glm::ivec3 check = pos + i; + auto adjLight = getLight(check, chunk.get()); + placeLight.x = fmax(placeLight.x, adjLight.x - 1); + placeLight.y = fmax(placeLight.y, adjLight.y - 1); + placeLight.z = fmax(placeLight.z, adjLight.z - 1); + placeLight.w = fmax(placeLight.w, adjLight.w - (i.y == 1 ? 0 : 1)); + } + + chunk->setLight(ind, placeLight); + + auto _ = getWriteLock(); + lightAddQueue[0].emplace(ind, chunk.get()); + lightAddQueue[1].emplace(ind, chunk.get()); + lightAddQueue[2].emplace(ind, chunk.get()); + lightAddQueue[3].emplace(ind, chunk.get()); } void Dimension::removeSunlight(glm::ivec3 pos) { - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - unsigned int ind = Space::Block::index(pos); - unsigned int light = chunk->getLight(ind, 3); - - chunk->setLight(ind, 3, 0); - auto _ = getWriteLock(); - lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, light, chunk.get()); + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + unsigned int ind = Space::Block::index(pos); + unsigned int light = chunk->getLight(ind, 3); + + chunk->setLight(ind, 3, 0); + auto _ = getWriteLock(); + lightRemoveQueue[SUNLIGHT_CHANNEL].emplace(ind, light, chunk.get()); } void Dimension::setAndReflowSunlight(glm::ivec3 pos, unsigned char level) { - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - unsigned int ind = Space::Block::index(pos); - - chunk->setLight(ind, 3, level); - auto _ = getWriteLock(); - lightAddQueue[SUNLIGHT_CHANNEL].emplace(ind, chunk.get()); + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + unsigned int ind = Space::Block::index(pos); + + chunk->setLight(ind, 3, level); + auto _ = getWriteLock(); + lightAddQueue[SUNLIGHT_CHANNEL].emplace(ind, chunk.get()); } \ No newline at end of file diff --git a/src/world/dim/Dimension.h b/src/world/dim/Dimension.h index 6a0d7a48..a14f8c31 100644 --- a/src/world/dim/Dimension.h +++ b/src/world/dim/Dimension.h @@ -13,64 +13,81 @@ #include "DimensionBase.h" class Target; + class Player; class Dimension : public DimensionBase { -public: - typedef std::unordered_set relitChunks; - - Dimension(const Dimension& o) = delete; - Dimension(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind, std::shared_ptr mapGen) : - DimensionBase(game, world, identifier, ind, std::move(mapGen)) {} - - // Override setBlock to update lighting. - bool setBlock(glm::ivec3 pos, unsigned int block) override; - - virtual double blockHit(const Target &target, PlayerPtr player) = 0; - virtual void blockPlace(const Target &target, PlayerPtr player) = 0; - virtual void blockPlaceOrInteract(const Target &target, PlayerPtr player) = 0; - virtual void blockInteract(const Target &target, PlayerPtr player) = 0; - - unsigned int nextEntityInd(); - - // Calculate light propogation around MapBlock edges, - // Called after a new mapblock is inserted into the dimension. + public: + typedef std::unordered_set relitChunks; + + Dimension(const Dimension& o) = delete; + + Dimension(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind, + std::shared_ptr mapGen) : + DimensionBase(game, world, identifier, ind, std::move(mapGen)) {} + + // Override setBlock to update lighting. + bool setBlock(glm::ivec3 pos, unsigned int block) override; + + virtual double blockHit(const Target& target, PlayerPtr player) = 0; + + virtual void blockPlace(const Target& target, PlayerPtr player) = 0; + + virtual void blockPlaceOrInteract(const Target& target, PlayerPtr player) = 0; + + virtual void blockInteract(const Target& target, PlayerPtr player) = 0; + + unsigned int nextEntityInd(); + + // Calculate light propogation around MapBlock edges, + // Called after a new mapblock is inserted into the dimension. // relitChunks calculateEdgeLight(glm::ivec3 mbPos); -protected: - - // Lighting propagation. - - virtual relitChunks propogateAddNodes(); - virtual relitChunks propogateRemoveNodes(); -private: - - // Other Lighting methods. - - static inline bool containsWorldPos(Chunk* chunk, glm::ivec3 pos); - inline glm::ivec4 getLight(glm::ivec3 worldPos, Chunk* chunk = nullptr); - - void calculateHorizontalEdge(std::shared_ptr a, std::shared_ptr b); - void calculateVerticalEdge(std::shared_ptr above, std::shared_ptr below); - - inline void addBlockLight(glm::ivec3 pos, glm::ivec3 light); - inline void removeBlockLight(glm::ivec3 pos); - - inline void reflowLight(glm::ivec3 pos); - inline void removeSunlight(glm::ivec3 pos); - inline void setAndReflowSunlight(glm::ivec3 pos, unsigned char level); - - struct LightAddNode { - LightAddNode(unsigned short index, Chunk* chunk) : index(index), chunk(chunk) {}; - unsigned short index; Chunk* chunk; - }; - struct LightRemoveNode { - LightRemoveNode(unsigned short index, unsigned short value, Chunk* chunk) : index(index), value(value), chunk(chunk) {}; - unsigned short index, value; Chunk* chunk; - }; - - static constexpr unsigned char SUNLIGHT_CHANNEL = 3; - std::array, 4> lightAddQueue; - std::array, 4> lightRemoveQueue; - - unsigned int entityInd = 0; + protected: + + // Lighting propagation. + + virtual relitChunks propogateAddNodes(); + + virtual relitChunks propogateRemoveNodes(); + + private: + + // Other Lighting methods. + + static inline bool containsWorldPos(Chunk* chunk, glm::ivec3 pos); + + inline glm::ivec4 getLight(glm::ivec3 worldPos, Chunk* chunk = nullptr); + + void calculateHorizontalEdge(std::shared_ptr a, std::shared_ptr b); + + void calculateVerticalEdge(std::shared_ptr above, std::shared_ptr below); + + inline void addBlockLight(glm::ivec3 pos, glm::ivec3 light); + + inline void removeBlockLight(glm::ivec3 pos); + + inline void reflowLight(glm::ivec3 pos); + + inline void removeSunlight(glm::ivec3 pos); + + inline void setAndReflowSunlight(glm::ivec3 pos, unsigned char level); + + struct LightAddNode { + LightAddNode(unsigned short index, Chunk* chunk) : index(index), chunk(chunk) {}; + unsigned short index; + Chunk* chunk; + }; + + struct LightRemoveNode { + LightRemoveNode(unsigned short index, unsigned short value, Chunk* chunk) : index(index), value(value), + chunk(chunk) {}; + unsigned short index, value; + Chunk* chunk; + }; + + static constexpr unsigned char SUNLIGHT_CHANNEL = 3; + std::array, 4> lightAddQueue; + std::array, 4> lightRemoveQueue; + + unsigned int entityInd = 0; }; diff --git a/src/world/dim/DimensionBase.cpp b/src/world/dim/DimensionBase.cpp index c08ad9eb..188efabe 100644 --- a/src/world/dim/DimensionBase.cpp +++ b/src/world/dim/DimensionBase.cpp @@ -12,161 +12,161 @@ #include "world/dim/chunk/MapBlock.h" #include "game/atlas/DefinitionAtlas.h" -DimensionBase::DimensionBase(SubgamePtr game, World& world, const std::string &identifier, - unsigned int ind, std::shared_ptr mapGen) : - game(game), world(world), identifier(identifier), ind(ind), mapGen(std::move(mapGen)) {} +DimensionBase::DimensionBase(SubgamePtr game, World& world, const std::string& identifier, + unsigned int ind, std::shared_ptr mapGen) : + game(game), world(world), identifier(identifier), ind(ind), mapGen(std::move(mapGen)) {} std::string DimensionBase::getIdentifier() const { - return identifier; + return identifier; } unsigned int DimensionBase::getInd() { - return ind; + return ind; } std::shared_ptr DimensionBase::getRegion(glm::ivec3 regionPosition) const { - auto _ = getReadLock(); - if (!regions.count(regionPosition)) return nullptr; - return regions.at(regionPosition); + auto _ = getReadLock(); + if (!regions.count(regionPosition)) return nullptr; + return regions.at(regionPosition); } void DimensionBase::removeRegion(glm::ivec3 pos) { - auto _ = getWriteLock(); - regions.erase(pos); + auto _ = getWriteLock(); + regions.erase(pos); } std::shared_ptr DimensionBase::getMapBlock(glm::ivec3 mapBlockPosition) const { - auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition)); - if (!region) return nullptr; - return region->get(Space::MapBlock::index(mapBlockPosition)); + auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition)); + if (!region) return nullptr; + return region->get(Space::MapBlock::index(mapBlockPosition)); } void DimensionBase::removeMapBlock(glm::ivec3 pos) { - auto region = getRegion(Space::Region::world::fromMapBlock(pos)); - if (!region) return; - auto i = Space::MapBlock::index(pos); - region->remove(i); - if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos)); + auto region = getRegion(Space::Region::world::fromMapBlock(pos)); + if (!region) return; + auto i = Space::MapBlock::index(pos); + region->remove(i); + if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos)); } bool DimensionBase::mapBlockGenerated(glm::ivec3 mapBlockPosition) { - auto mb = getMapBlock(mapBlockPosition); - return mb && mb->generated; + auto mb = getMapBlock(mapBlockPosition); + return mb && mb->generated; } std::shared_ptr DimensionBase::getChunk(glm::ivec3 chunkPosition) const { - auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition)); - if (!mapBlock) return nullptr; - return mapBlock->get(Space::Chunk::index(chunkPosition)); + auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition)); + if (!mapBlock) return nullptr; + return mapBlock->get(Space::Chunk::index(chunkPosition)); } void DimensionBase::setChunk(std::shared_ptr chunk) { - auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->getPos())); - mapBlock->set(Space::Chunk::index(chunk->getPos()), chunk); + auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->getPos())); + mapBlock->set(Space::Chunk::index(chunk->getPos()), chunk); } -void DimensionBase::removeChunk(glm::ivec3 pos){ - auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos)); - if (!mapBlock) return; - auto i = Space::Chunk::index(pos); - mapBlock->remove(i); - if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos)); +void DimensionBase::removeChunk(glm::ivec3 pos) { + auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos)); + if (!mapBlock) return; + auto i = Space::Chunk::index(pos); + mapBlock->remove(i); + if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos)); } unsigned int DimensionBase::getBlock(glm::ivec3 pos) const { - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - if (!chunk) return 0; - - return chunk->getBlock(Space::Block::relative::toChunk(pos)); + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + if (!chunk) return 0; + + return chunk->getBlock(Space::Block::relative::toChunk(pos)); } bool DimensionBase::setBlock(glm::ivec3 pos, unsigned int block) { - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - if (!chunk) return false; - - bool manip = chunk->setBlock(Space::Block::relative::toChunk(pos), block); - setBlockDamage(pos, 0); - return manip; + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + if (!chunk) return false; + + bool manip = chunk->setBlock(Space::Block::relative::toChunk(pos), block); + setBlockDamage(pos, 0); + return manip; } double DimensionBase::getBlockDamage(glm::ivec3 pos) const { - auto _ = getReadLock(); - return blockDamages.count(pos) ? blockDamages.at(pos).curr : 0; + auto _ = getReadLock(); + return blockDamages.count(pos) ? blockDamages.at(pos).curr : 0; } double DimensionBase::setBlockDamage(glm::ivec3 pos, double damage) { - if (blockDamages.count(pos)) blockDamages[pos].curr = damage; - else { - double health = game->getDefs().blockFromId(getBlock(pos)).health; - auto _ = getWriteLock(); - blockDamages.insert({pos, Damage { damage, health }}); - } - - return getBlockDamage(pos); + if (blockDamages.count(pos)) blockDamages[pos].curr = damage; + else { + double health = game->getDefs().blockFromId(getBlock(pos)).health; + auto _ = getWriteLock(); + blockDamages.insert({ pos, Damage{ damage, health }}); + } + + return getBlockDamage(pos); } unsigned int DimensionBase::getBiome(glm::ivec3 pos) const { - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - if (!chunk) return 0; - - return chunk->getBiome(Space::Block::relative::toChunk(pos)); + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + if (!chunk) return 0; + + return chunk->getBiome(Space::Block::relative::toChunk(pos)); } bool DimensionBase::setBiome(glm::ivec3 pos, unsigned int biome) { - auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); - if (!chunk) return false; - - return chunk->setBiome(Space::Block::relative::toChunk(pos), biome); + auto chunk = getChunk(Space::Chunk::world::fromBlock(pos)); + if (!chunk) return false; + + return chunk->setBiome(Space::Block::relative::toChunk(pos), biome); } std::shared_ptr DimensionBase::getOrCreateRegion(glm::ivec3 pos) { - auto _ = getWriteLock(); - if (regions[pos]) return regions[pos]; - regions[pos] = std::make_shared(pos); - return regions[pos]; + auto _ = getWriteLock(); + if (regions[pos]) return regions[pos]; + regions[pos] = std::make_shared(pos); + return regions[pos]; } std::shared_ptr DimensionBase::getOrCreateMapBlock(glm::ivec3 mapBlockPosition) { - auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition)); - unsigned int index = Space::MapBlock::index(mapBlockPosition); - - if (region->get(index) != nullptr) return region->get(index); - region->set(index, std::make_shared(mapBlockPosition)); - return region->get(index); + auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition)); + unsigned int index = Space::MapBlock::index(mapBlockPosition); + + if (region->get(index) != nullptr) return region->get(index); + region->set(index, std::make_shared(mapBlockPosition)); + return region->get(index); } SubgamePtr DimensionBase::getGame() { - return game; + return game; } World& DimensionBase::getWorld() { - return world; + return world; } std::shared_ptr DimensionBase::combinePartials(std::shared_ptr a, std::shared_ptr b) { - std::shared_ptr src; - std::shared_ptr res; - - if (a->isGenerated()) { - res = a; - src = b; - } - else { - res = b; - src = a; - } - - for (unsigned int i = 0; i < 4096; i++) { - if (src->getBlock(i) > DefinitionAtlas::INVALID) res->setBlock(i, src->getBlock(i)); - } - - res->setGenerated(src->isGenerated() || res->isGenerated()); - res->setPartial(!res->isGenerated()); - res->countRenderableBlocks(); - return res; + std::shared_ptr src; + std::shared_ptr res; + + if (a->isGenerated()) { + res = a; + src = b; + } + else { + res = b; + src = a; + } + + for (unsigned int i = 0; i < 4096; i++) { + if (src->getBlock(i) > DefinitionAtlas::INVALID) res->setBlock(i, src->getBlock(i)); + } + + res->setGenerated(src->isGenerated() || res->isGenerated()); + res->setPartial(!res->isGenerated()); + res->countRenderableBlocks(); + return res; } std::shared_ptr DimensionBase::getGen() { - return mapGen; + return mapGen; } diff --git a/src/world/dim/DimensionBase.h b/src/world/dim/DimensionBase.h index 6c827973..bfc3dac3 100644 --- a/src/world/dim/DimensionBase.h +++ b/src/world/dim/DimensionBase.h @@ -13,67 +13,87 @@ #include "util/CovariantPtr.h" class World; + class Chunk; + class MapGen; + class Region; + class Subgame; + class MapBlock; + class DefinitionAtlas; class DimensionBase : protected Lockable { -public: - DimensionBase(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind, std::shared_ptr mapGen); - - std::string getIdentifier() const; - unsigned int getInd(); - - virtual void update(double delta) = 0; - - std::shared_ptr getRegion(glm::ivec3 regionPosition) const; - void removeRegion(glm::ivec3 pos); - - std::shared_ptr getMapBlock(glm::ivec3 mapBlockPosition) const; - virtual void removeMapBlock(glm::ivec3 pos); - - bool mapBlockGenerated(glm::ivec3 mapBlockPosition); - - std::shared_ptr getChunk(glm::ivec3 chunkPosition) const; - virtual void setChunk(std::shared_ptr chunk); - virtual void removeChunk(glm::ivec3 pos); - - unsigned int getBlock(glm::ivec3 pos) const; - virtual bool setBlock(glm::ivec3 pos, unsigned int block); - - virtual double getBlockDamage(glm::ivec3 pos) const; - virtual double setBlockDamage(glm::ivec3 pos, double damage); - - unsigned int getBiome(glm::ivec3 pos) const; - virtual bool setBiome(glm::ivec3 pos, unsigned int biome); - - std::shared_ptr getGen(); - SubgamePtr getGame(); - World& getWorld(); - -protected: - // Combine two chunk partials, or a chunk and a chunk partial. - // If both are partials `b` takes preference, if one is a fully generated chunk the partial takes preference. - // TODO: Make this more efficient using proper RIE traversal. - static std::shared_ptr combinePartials(std::shared_ptr a, std::shared_ptr b); - - std::shared_ptr mapGen; - SubgamePtr game; - World& world; - - typedef std::unordered_map, Vec::ivec3> block_region_map; - block_region_map regions; - - std::string identifier; - unsigned int ind; - - struct Damage { double curr, max; }; - std::unordered_map blockDamages; - -private: - inline std::shared_ptr getOrCreateRegion(glm::ivec3 pos); - inline std::shared_ptr getOrCreateMapBlock(glm::ivec3 mapBlockPosition); + public: + DimensionBase(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind, + std::shared_ptr mapGen); + + std::string getIdentifier() const; + + unsigned int getInd(); + + virtual void update(double delta) = 0; + + std::shared_ptr getRegion(glm::ivec3 regionPosition) const; + + void removeRegion(glm::ivec3 pos); + + std::shared_ptr getMapBlock(glm::ivec3 mapBlockPosition) const; + + virtual void removeMapBlock(glm::ivec3 pos); + + bool mapBlockGenerated(glm::ivec3 mapBlockPosition); + + std::shared_ptr getChunk(glm::ivec3 chunkPosition) const; + + virtual void setChunk(std::shared_ptr chunk); + + virtual void removeChunk(glm::ivec3 pos); + + unsigned int getBlock(glm::ivec3 pos) const; + + virtual bool setBlock(glm::ivec3 pos, unsigned int block); + + virtual double getBlockDamage(glm::ivec3 pos) const; + + virtual double setBlockDamage(glm::ivec3 pos, double damage); + + unsigned int getBiome(glm::ivec3 pos) const; + + virtual bool setBiome(glm::ivec3 pos, unsigned int biome); + + std::shared_ptr getGen(); + + SubgamePtr getGame(); + + World& getWorld(); + + protected: + // Combine two chunk partials, or a chunk and a chunk partial. + // If both are partials `b` takes preference, if one is a fully generated chunk the partial takes preference. + // TODO: Make this more efficient using proper RIE traversal. + static std::shared_ptr combinePartials(std::shared_ptr a, std::shared_ptr b); + + std::shared_ptr mapGen; + SubgamePtr game; + World& world; + + typedef std::unordered_map, Vec::ivec3> block_region_map; + block_region_map regions; + + std::string identifier; + unsigned int ind; + + struct Damage { + double curr, max; + }; + std::unordered_map blockDamages; + + private: + inline std::shared_ptr getOrCreateRegion(glm::ivec3 pos); + + inline std::shared_ptr getOrCreateMapBlock(glm::ivec3 mapBlockPosition); }; diff --git a/src/world/dim/LocalDimension.cpp b/src/world/dim/LocalDimension.cpp index 985b3884..4673417a 100644 --- a/src/world/dim/LocalDimension.cpp +++ b/src/world/dim/LocalDimension.cpp @@ -17,9 +17,9 @@ #include "client/graph/mesh/MeshChunk.h" LocalDimension::LocalDimension(SubgamePtr game, LocalWorld& world, const std::string& identifier, - unsigned int ind, std::shared_ptr mapGen) : - Dimension(game, static_cast(world), identifier, ind, std::move(mapGen)), - meshGenStream(std::make_shared(game, *this)) {} + unsigned int ind, std::shared_ptr mapGen) : + Dimension(game, static_cast(world), identifier, ind, std::move(mapGen)), + meshGenStream(std::make_shared(game, *this)) {} /** @@ -28,279 +28,292 @@ LocalDimension::LocalDimension(SubgamePtr game, LocalWorld& world, const std::st */ void LocalDimension::deactivate() { - while (!renderElems.empty()) { - auto chunk = renderElems.front(); - renderRefs.erase(chunk->getPos()); - renderElems.pop_front(); - } - - while (!regions.empty()) { - removeRegion(regions.begin()->first); - } + while (!renderElems.empty()) { + auto chunk = renderElems.front(); + renderRefs.erase(chunk->getPos()); + renderElems.pop_front(); + } + + while (!regions.empty()) { + removeRegion(regions.begin()->first); + } } void LocalDimension::update(double delta) { - finishMeshes(); - - for (auto& entity : localEntities ) entity.entity.l()->update(delta); - for (auto& entity : serverEntities) entity.entity.l()->update(delta); - for (auto& entity : playerEntities) entity.update(delta); - - auto clientMapBlock = Space::MapBlock::world::fromBlock(static_cast(world).getPlayer()->getPos()); - - for (auto it = regions.cbegin(); it != regions.cend();) { - bool remove = false; - for (unsigned short m = 0; m < 64; m++) { - auto mapBlock = it->second->get(m); - if (!mapBlock) continue; - - if (abs(clientMapBlock.x - mapBlock->pos.x) > LocalDimension::MB_STORE_H + 1 - || abs(clientMapBlock.y - mapBlock->pos.y) > LocalDimension::MB_STORE_V + 1 - || abs(clientMapBlock.z - mapBlock->pos.z) > LocalDimension::MB_STORE_H + 1) { - - for (unsigned short c = 0; c < 64; c++) { - auto chunk = mapBlock->get(c); - if (!chunk) continue; - removeMeshChunk(chunk->getPos()); - } - - it->second->remove(m); - if (it->second->count <= 0) { - remove = true; - auto l = getWriteLock(); - it = regions.erase(it); - break; - } - } - } - if (!remove) it++; - } + finishMeshes(); + + for (auto& entity : localEntities) entity.entity.l()->update(delta); + for (auto& entity : serverEntities) entity.entity.l()->update(delta); + for (auto& entity : playerEntities) entity.update(delta); + + auto clientMapBlock = Space::MapBlock::world::fromBlock(static_cast(world).getPlayer()->getPos()); + + for (auto it = regions.cbegin(); it != regions.cend();) { + bool remove = false; + for (unsigned short m = 0; m < 64; m++) { + auto mapBlock = it->second->get(m); + if (!mapBlock) continue; + + if (abs(clientMapBlock.x - mapBlock->pos.x) > LocalDimension::MB_STORE_H + 1 + || abs(clientMapBlock.y - mapBlock->pos.y) > LocalDimension::MB_STORE_V + 1 + || abs(clientMapBlock.z - mapBlock->pos.z) > LocalDimension::MB_STORE_H + 1) { + + for (unsigned short c = 0; c < 64; c++) { + auto chunk = mapBlock->get(c); + if (!chunk) continue; + removeMeshChunk(chunk->getPos()); + } + + it->second->remove(m); + if (it->second->count <= 0) { + remove = true; + auto l = getWriteLock(); + it = regions.erase(it); + break; + } + } + } + if (!remove) it++; + } } void LocalDimension::setChunk(std::shared_ptr chunk) { - Dimension::setChunk(chunk); - attemptMeshChunk(chunk); + Dimension::setChunk(chunk); + attemptMeshChunk(chunk); } bool LocalDimension::setBlock(glm::ivec3 pos, unsigned int block) { - bool exists = Dimension::setBlock(pos, block); - if (!exists) return false; - - auto chunkPos = Space::Chunk::world::fromBlock(pos); - auto chunk = getChunk(chunkPos); - - chunk->setDirty(true); - - auto lp = Space::Block::relative::toChunk(pos); - auto cp = Space::Chunk::world::fromBlock(pos); - - std::shared_ptr tempChunk; - if (lp.x == 15 && (tempChunk = getChunk(cp + glm::ivec3 {1, 0, 0}))) tempChunk->setDirty(true); - else if (lp.x == 0 && (tempChunk = getChunk(cp + glm::ivec3 {-1, 0, 0}))) tempChunk->setDirty(true); - if (lp.y == 15 && (tempChunk = getChunk(cp + glm::ivec3 {0, 1, 0}))) tempChunk->setDirty(true); - else if (lp.y == 0 && (tempChunk = getChunk(cp + glm::ivec3 {0, -1, 0}))) tempChunk->setDirty(true); - if (lp.z == 15 && (tempChunk = getChunk(cp + glm::ivec3 {0, 0, 1}))) tempChunk->setDirty(true); - else if (lp.z == 0 && (tempChunk = getChunk(cp + glm::ivec3 {0, 0, -1}))) tempChunk->setDirty(true); - - attemptMeshChunk(chunk, true); - return true; + bool exists = Dimension::setBlock(pos, block); + if (!exists) return false; + + auto chunkPos = Space::Chunk::world::fromBlock(pos); + auto chunk = getChunk(chunkPos); + + chunk->setDirty(true); + + auto lp = Space::Block::relative::toChunk(pos); + auto cp = Space::Chunk::world::fromBlock(pos); + + std::shared_ptr tempChunk; + if (lp.x == 15 && (tempChunk = getChunk(cp + glm::ivec3{ 1, 0, 0 }))) tempChunk->setDirty(true); + else if (lp.x == 0 && (tempChunk = getChunk(cp + glm::ivec3{ -1, 0, 0 }))) tempChunk->setDirty(true); + if (lp.y == 15 && (tempChunk = getChunk(cp + glm::ivec3{ 0, 1, 0 }))) tempChunk->setDirty(true); + else if (lp.y == 0 && (tempChunk = getChunk(cp + glm::ivec3{ 0, -1, 0 }))) tempChunk->setDirty(true); + if (lp.z == 15 && (tempChunk = getChunk(cp + glm::ivec3{ 0, 0, 1 }))) tempChunk->setDirty(true); + else if (lp.z == 0 && (tempChunk = getChunk(cp + glm::ivec3{ 0, 0, -1 }))) tempChunk->setDirty(true); + + attemptMeshChunk(chunk, true); + return true; } -void LocalDimension::blockPlace(const Target &target, PlayerPtr player) { - std::tuple, sol::optional> res = game->getParser().safe_function( - game->getParser().core["block_place"], Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); - - static_cast(world).getNet().blockPlace(target); - - auto stack = std::get>(res); - if (!stack) return; - - auto inv = player.l()->getInventory(); - if (inv->hasList(player->getWieldList())) - inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); +void LocalDimension::blockPlace(const Target& target, PlayerPtr player) { + std::tuple, sol::optional> res = game->getParser().safe_function( + game->getParser().core["block_place"], Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); + + static_cast(world).getNet().blockPlace(target); + + auto stack = std::get>(res); + if (!stack) return; + + auto inv = player.l()->getInventory(); + if (inv->hasList(player->getWieldList())) + inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); } -void LocalDimension::blockInteract(const Target &target, PlayerPtr player) { - game->getParser().safe_function(game->getParser().core["block_interact"], - Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); - - static_cast(world).getNet().blockInteract(target); +void LocalDimension::blockInteract(const Target& target, PlayerPtr player) { + game->getParser().safe_function(game->getParser().core["block_interact"], + Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); + + static_cast(world).getNet().blockInteract(target); } -void LocalDimension::blockPlaceOrInteract(const Target &target, PlayerPtr player) { - std::tuple, sol::optional> res = game->getParser().safe_function( - game->getParser().core["block_interact_or_place"], Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); - - static_cast(world).getNet().blockPlaceOrInteract(target); - - auto stack = std::get>(res); - if (!stack) return; - - auto inv = player.l()->getInventory(); - if (inv->hasList(player->getWieldList())) - inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); +void LocalDimension::blockPlaceOrInteract(const Target& target, PlayerPtr player) { + std::tuple, sol::optional> res = game->getParser().safe_function( + game->getParser().core["block_interact_or_place"], Api::Usertype::LocalPlayer(player.l()), + Api::Usertype::Target(target)); + + static_cast(world).getNet().blockPlaceOrInteract(target); + + auto stack = std::get>(res); + if (!stack) return; + + auto inv = player.l()->getInventory(); + if (inv->hasList(player->getWieldList())) + inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); } -double LocalDimension::blockHit(const Target &target, PlayerPtr player) { - double timeout = 0, damage = 0; - sol::tie(damage, timeout) = game->getParser().safe_function(game->getParser().core["block_hit"], - Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); - - static_cast(world).getNet().blockHit(target); - - return timeout; +double LocalDimension::blockHit(const Target& target, PlayerPtr player) { + double timeout = 0, damage = 0; + sol::tie(damage, timeout) = game->getParser().safe_function(game->getParser().core["block_hit"], + Api::Usertype::LocalPlayer(player.l()), Api::Usertype::Target(target)); + + static_cast(world).getNet().blockHit(target); + + return timeout; } void LocalDimension::setMeshChunk(std::shared_ptr meshChunk) { - if (renderRefs.count(meshChunk->getPos())) removeMeshChunk(meshChunk->getPos()); - renderElems.push_back(std::static_pointer_cast(meshChunk)); - renderRefs.emplace(meshChunk->getPos(), --renderElems.end()); + if (renderRefs.count(meshChunk->getPos())) removeMeshChunk(meshChunk->getPos()); + renderElems.push_back(std::static_pointer_cast(meshChunk)); + renderRefs.emplace(meshChunk->getPos(), --renderElems.end()); } void LocalDimension::removeMeshChunk(const glm::ivec3& pos) { - if (!renderRefs.count(pos)) return; - auto refIter = renderRefs.at(pos); - - if (!refIter->get()->updateChunkUse(pos, false)) { - renderElems.erase(refIter); - renderRefs.erase(pos); - } + if (!renderRefs.count(pos)) return; + auto refIter = renderRefs.at(pos); + + if (!refIter->get()->updateChunkUse(pos, false)) { + renderElems.erase(refIter); + renderRefs.erase(pos); + } } void LocalDimension::addLocalEntity(Api::Usertype::Entity entity) { - unsigned int id = entity.get_id(); - localEntities.push_back(entity); - localEntityRefs.emplace(id, --localEntities.end()); + unsigned int id = entity.get_id(); + localEntities.push_back(entity); + localEntityRefs.emplace(id, --localEntities.end()); } void LocalDimension::removeLocalEntity(Api::Usertype::Entity entity) { - unsigned int id = entity.get_id(); - - if (!localEntityRefs.count(id)) return; - auto refIter = localEntityRefs.at(id); - - localEntities.erase(refIter); - localEntityRefs.erase(id); + unsigned int id = entity.get_id(); + + if (!localEntityRefs.count(id)) return; + auto refIter = localEntityRefs.at(id); + + localEntities.erase(refIter); + localEntityRefs.erase(id); } void LocalDimension::serverEntitiesInfo(Deserializer& e) { - bool boolean; - unsigned int x, y; - std::string type, a, b; - - e.read(); - - while (!e.atEnd()) { - std::string dat = e.read(); - Deserializer d(dat); - - unsigned int id = d.read(); - std::shared_ptr activeEntity; - if (serverEntityRefs.count(id)) activeEntity = serverEntityRefs.at(id)->entity.l(); - else { - auto ent = std::make_shared(game, world.getDimension(getInd())); - auto entity = Api::Usertype::Entity(ent); - ent->setId(id); - serverEntities.push_back(entity); - serverEntityRefs.emplace(id, --serverEntities.end()); - activeEntity = ent; - } - - while (!d.atEnd()) { - switch (d.readE()) { - case NetField::DIM: activeEntity->setDim(world.getDimension(d.read())); break; - case NetField::POS: activeEntity->setPos(d.read()); break; - case NetField::VEL: activeEntity->setVel(d.read()); break; - case NetField::ROT: activeEntity->setRot(d.read()); break; - case NetField::SCALE: activeEntity->setScale(d.read()); break; - case NetField::VISUAL_OFF: activeEntity->setVisualOffset(d.read()); break; - case NetField::ANIM_STATE: d.read(boolean); activeEntity->animation.setPlaying(boolean); break; - case NetField::DISPLAY: d.read(type).read(a).read(b); activeEntity->setAppearance(type, a, b); break; - case NetField::ANIM_RANGE: d.read(x).read(y).read(boolean); activeEntity->animation.setAnim(glm::ivec2 {x, y}, 10, boolean); break; - } - } - } + bool boolean; + unsigned int x, y; + std::string type, a, b; + + e.read(); + + while (!e.atEnd()) { + std::string dat = e.read(); + Deserializer d(dat); + + unsigned int id = d.read(); + std::shared_ptr activeEntity; + if (serverEntityRefs.count(id)) activeEntity = serverEntityRefs.at(id)->entity.l(); + else { + auto ent = std::make_shared(game, world.getDimension(getInd())); + auto entity = Api::Usertype::Entity(ent); + ent->setId(id); + serverEntities.push_back(entity); + serverEntityRefs.emplace(id, --serverEntities.end()); + activeEntity = ent; + } + + while (!d.atEnd()) { + switch (d.readE()) { + case NetField::DIM: activeEntity->setDim(world.getDimension(d.read())); + break; + case NetField::POS: activeEntity->setPos(d.read()); + break; + case NetField::VEL: activeEntity->setVel(d.read()); + break; + case NetField::ROT: activeEntity->setRot(d.read()); + break; + case NetField::SCALE: activeEntity->setScale(d.read()); + break; + case NetField::VISUAL_OFF: activeEntity->setVisualOffset(d.read()); + break; + case NetField::ANIM_STATE: d.read(boolean); + activeEntity->animation.setPlaying(boolean); + break; + case NetField::DISPLAY: d.read(type).read(a).read(b); + activeEntity->setAppearance(type, a, b); + break; + case NetField::ANIM_RANGE: d.read(x).read(y).read(boolean); + activeEntity->animation.setAnim(glm::ivec2{ x, y }, 10, boolean); + break; + } + } + } } void LocalDimension::serverEntitiesRemoved(Deserializer& d) { - d.read(); - while (!d.atEnd()) { - unsigned int id = d.read(); - if (!serverEntityRefs.count(id)) continue; - auto refIter = serverEntityRefs.at(id); - serverEntities.erase(refIter); - serverEntityRefs.erase(id); - } + d.read(); + while (!d.atEnd()) { + unsigned int id = d.read(); + if (!serverEntityRefs.count(id)) continue; + auto refIter = serverEntityRefs.at(id); + serverEntities.erase(refIter); + serverEntityRefs.erase(id); + } } -int LocalDimension::renderChunks(Renderer &renderer) { - int count = 0; - for (auto &renderElement : renderElems) { - FrustumAABB bbox(renderElement->getPos() * glm::vec3(16), glm::vec3(16)); - if (renderer.camera.inFrustum(bbox) != Frustum::OUTSIDE) { - renderElement->draw(renderer); - count++; - } - } - return count; +int LocalDimension::renderChunks(Renderer& renderer) { + int count = 0; + for (auto& renderElement : renderElems) { + FrustumAABB bbox(renderElement->getPos() * glm::vec3(16), glm::vec3(16)); + if (renderer.camera.inFrustum(bbox) != Frustum::OUTSIDE) { + renderElement->draw(renderer); + count++; + } + } + return count; } -void LocalDimension::renderEntities(Renderer &renderer) { - for (auto& entity : localEntities) entity.entity.l()->draw(renderer); - for (auto& entity : serverEntities) entity.entity.l()->draw(renderer); - for (auto& entity : playerEntities) entity.draw(renderer); +void LocalDimension::renderEntities(Renderer& renderer) { + for (auto& entity : localEntities) entity.entity.l()->draw(renderer); + for (auto& entity : serverEntities) entity.entity.l()->draw(renderer); + for (auto& entity : playerEntities) entity.draw(renderer); } int LocalDimension::getMeshChunkCount() { - return static_cast(renderElems.size()); + return static_cast(renderElems.size()); } std::unordered_set LocalDimension::propogateAddNodes() { - auto updated = Dimension::propogateAddNodes(); - for (auto& update : updated) attemptMeshChunk(getChunk(update)); - return {}; + auto updated = Dimension::propogateAddNodes(); + for (auto& update : updated) attemptMeshChunk(getChunk(update)); + return {}; } std::unordered_set LocalDimension::propogateRemoveNodes() { - auto updated = Dimension::propogateRemoveNodes(); - for (auto& update : updated) attemptMeshChunk(getChunk(update)); - return {}; + auto updated = Dimension::propogateRemoveNodes(); + for (auto& update : updated) attemptMeshChunk(getChunk(update)); + return {}; } void LocalDimension::finishMeshes() { - lastMeshUpdates = 0; - auto finishedMeshes = meshGenStream->update(); - - for (ChunkMeshDetails* meshDetails : finishedMeshes) { - if (!meshDetails->vertices.empty()) { - auto meshChunk = std::make_shared(); - meshChunk->create(meshDetails->vertices, meshDetails->indices); - meshChunk->setPos(meshDetails->pos); - - setMeshChunk(meshChunk); - lastMeshUpdates++; - } - else removeMeshChunk(meshDetails->pos); - - delete meshDetails; - } + lastMeshUpdates = 0; + auto finishedMeshes = meshGenStream->update(); + + for (ChunkMeshDetails* meshDetails : finishedMeshes) { + if (!meshDetails->vertices.empty()) { + auto meshChunk = std::make_shared(); + meshChunk->create(meshDetails->vertices, meshDetails->indices); + meshChunk->setPos(meshDetails->pos); + + setMeshChunk(meshChunk); + lastMeshUpdates++; + } + else removeMeshChunk(meshDetails->pos); + + delete meshDetails; + } } void LocalDimension::attemptMeshChunk(const std::shared_ptr& chunk, bool priority, bool updateAdjacents) { - bool renderable = true; - for (auto dir : Vec::TO_VEC) if (!getAdjacentExists(chunk->getPos() + dir, updateAdjacents)) renderable = false; - if (!renderable) return; - - if (!chunk->isDirty()) return; - if (!chunk->chunkShouldRender()) removeMeshChunk(chunk->getPos()); - - meshGenStream->queue(chunk->getPos(), priority); - chunk->setDirty(false); + bool renderable = true; + for (auto dir : Vec::TO_VEC) if (!getAdjacentExists(chunk->getPos() + dir, updateAdjacents)) renderable = false; + if (!renderable) return; + + if (!chunk->isDirty()) return; + if (!chunk->chunkShouldRender()) removeMeshChunk(chunk->getPos()); + + meshGenStream->queue(chunk->getPos(), priority); + chunk->setDirty(false); } bool LocalDimension::getAdjacentExists(glm::vec3 pos, bool updateAdjacents) { - auto chunk = getChunk(pos); - if (chunk == nullptr) return false; - if (updateAdjacents) attemptMeshChunk(chunk, false, false); - return true; + auto chunk = getChunk(pos); + if (chunk == nullptr) return false; + if (updateAdjacents) attemptMeshChunk(chunk, false, false); + return true; } \ No newline at end of file diff --git a/src/world/dim/LocalDimension.h b/src/world/dim/LocalDimension.h index 8f0a4049..0f36582a 100644 --- a/src/world/dim/LocalDimension.h +++ b/src/world/dim/LocalDimension.h @@ -13,67 +13,84 @@ #include "client/entity/PlayerEntity.h" class Renderer; + class MeshChunk; + class Deserializer; + class MeshGenStream; + class ChunkRenderElem; class LocalDimension : public Dimension { -public: - const static int MB_STORE_H = 6; - const static int MB_STORE_V = 4; - - LocalDimension(SubgamePtr game, LocalWorld& world, const std::string& identifier, unsigned int ind, std::shared_ptr mapGen); - - void deactivate(); - void update(double delta) override; - - void setChunk(std::shared_ptr chunk) override; - bool setBlock(glm::ivec3 pos, unsigned int block) override; - - virtual void blockPlace(const Target &target, PlayerPtr player) override; - virtual void blockPlaceOrInteract(const Target &target, PlayerPtr player) override; - virtual void blockInteract(const Target &target, PlayerPtr player) override; - virtual double blockHit(const Target &target, PlayerPtr player) override; - - void setMeshChunk(std::shared_ptr chunk); - void removeMeshChunk(const glm::ivec3& pos); - - void addLocalEntity(Api::Usertype::Entity entity); - void removeLocalEntity(Api::Usertype::Entity entity); - - void serverEntitiesInfo(Deserializer& d); - void serverEntitiesRemoved(Deserializer& d); - - int renderChunks(Renderer &renderer); - void renderEntities(Renderer &renderer); - int getMeshChunkCount(); - - int lastMeshUpdates = 0; - std::vector playerEntities; - -protected: - std::unordered_set propogateAddNodes() override; - std::unordered_set propogateRemoveNodes() override; - -private: - typedef std::list::iterator ent_ref; - typedef std::list>::iterator chunk_ref; - - void finishMeshes(); - - void attemptMeshChunk(const std::shared_ptr& chunk, bool priority = false, bool updateAdjacents = true); - bool getAdjacentExists(glm::vec3 pos, bool updateAdjacents); - - std::shared_ptr meshGenStream; - - std::unordered_map localEntityRefs {}; - std::list localEntities {}; - - std::unordered_map serverEntityRefs {}; - std::list serverEntities {}; - - std::unordered_map renderRefs {}; - std::list> renderElems {}; + public: + const static int MB_STORE_H = 6; + const static int MB_STORE_V = 4; + + LocalDimension(SubgamePtr game, LocalWorld& world, const std::string& identifier, unsigned int ind, + std::shared_ptr mapGen); + + void deactivate(); + + void update(double delta) override; + + void setChunk(std::shared_ptr chunk) override; + + bool setBlock(glm::ivec3 pos, unsigned int block) override; + + virtual void blockPlace(const Target& target, PlayerPtr player) override; + + virtual void blockPlaceOrInteract(const Target& target, PlayerPtr player) override; + + virtual void blockInteract(const Target& target, PlayerPtr player) override; + + virtual double blockHit(const Target& target, PlayerPtr player) override; + + void setMeshChunk(std::shared_ptr chunk); + + void removeMeshChunk(const glm::ivec3& pos); + + void addLocalEntity(Api::Usertype::Entity entity); + + void removeLocalEntity(Api::Usertype::Entity entity); + + void serverEntitiesInfo(Deserializer& d); + + void serverEntitiesRemoved(Deserializer& d); + + int renderChunks(Renderer& renderer); + + void renderEntities(Renderer& renderer); + + int getMeshChunkCount(); + + int lastMeshUpdates = 0; + std::vector playerEntities; + + protected: + std::unordered_set propogateAddNodes() override; + + std::unordered_set propogateRemoveNodes() override; + + private: + typedef std::list::iterator ent_ref; + typedef std::list>::iterator chunk_ref; + + void finishMeshes(); + + void attemptMeshChunk(const std::shared_ptr& chunk, bool priority = false, bool updateAdjacents = true); + + bool getAdjacentExists(glm::vec3 pos, bool updateAdjacents); + + std::shared_ptr meshGenStream; + + std::unordered_map localEntityRefs{}; + std::list localEntities{}; + + std::unordered_map serverEntityRefs{}; + std::list serverEntities{}; + + std::unordered_map renderRefs{}; + std::list> renderElems{}; }; diff --git a/src/world/dim/ServerDimension.cpp b/src/world/dim/ServerDimension.cpp index fcf7038d..bc7883e9 100644 --- a/src/world/dim/ServerDimension.cpp +++ b/src/world/dim/ServerDimension.cpp @@ -17,102 +17,105 @@ #include "world/dim/ent/ServerLuaEntity.h" ServerDimension::ServerDimension(SubgamePtr game, ServerWorld& world, const std::string& identifier, - unsigned int ind, std::shared_ptr mapGen) : - Dimension(game, static_cast(world), identifier, ind, std::move(mapGen)) {} + unsigned int ind, std::shared_ptr mapGen) : + Dimension(game, static_cast(world), identifier, ind, std::move(mapGen)) {} void ServerDimension::update(double delta) { - for (auto& entity : luaEntities) entity.entity.s()->update(delta); - - for (const auto& region : regions) { - for (unsigned short i = 0; i < 64; i++) { - auto mb = region.second->get(i); - if (!mb) continue; - - bool clientNearby = false; - for (auto& player : static_cast(world).getClients().players) { - // TODO: Re-enable then **once** file saving is implemented. + for (auto& entity : luaEntities) entity.entity.s()->update(delta); + + for (const auto& region : regions) { + for (unsigned short i = 0; i < 64; i++) { + auto mb = region.second->get(i); + if (!mb) continue; + + bool clientNearby = false; + for (auto& player : static_cast(world).getClients().players) { + // TODO: Re-enable then **once** file saving is implemented. // if (player->getDim()->getInd() == ind) { - auto clientPos = Space::MapBlock::world::fromBlock(player->getPos()); - if (abs(clientPos.x - mb->pos.x) <= discardRange.x + 1 - && abs(clientPos.y - mb->pos.y) <= discardRange.y + 1 - && abs(clientPos.z - mb->pos.z) <= discardRange.x + 1) { - clientNearby = true; - break; - } + auto clientPos = Space::MapBlock::world::fromBlock(player->getPos()); + if (abs(clientPos.x - mb->pos.x) <= discardRange.x + 1 + && abs(clientPos.y - mb->pos.y) <= discardRange.y + 1 + && abs(clientPos.z - mb->pos.z) <= discardRange.x + 1) { + clientNearby = true; + break; + } // } - } - - if (!clientNearby) region.second->remove(i); - } - } + } + + if (!clientNearby) region.second->remove(i); + } + } } -double ServerDimension::blockHit(const Target &target, PlayerPtr player) { - double timeout = 0, damage = 0; - sol::tie(damage, timeout) = game->getParser().safe_function(game->getParser().core["block_hit"], - Api::Usertype::ServerPlayer(player), Api::Usertype::Target(target)); - - return timeout; +double ServerDimension::blockHit(const Target& target, PlayerPtr player) { + double timeout = 0, damage = 0; + sol::tie(damage, timeout) = game->getParser().safe_function(game->getParser().core["block_hit"], + Api::Usertype::ServerPlayer(player), Api::Usertype::Target(target)); + + return timeout; } -void ServerDimension::blockPlace(const Target &target, PlayerPtr player) { - std::tuple, sol::optional> res = game->getParser().safe_function( - game->getParser().core["block_place"], Api::Usertype::ServerPlayer(player.s()), Api::Usertype::Target(target)); - - auto stack = std::get>(res); - if (!stack) return; - - auto inv = player->getInventory(); - if (inv->hasList(player->getWieldList())) inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); +void ServerDimension::blockPlace(const Target& target, PlayerPtr player) { + std::tuple, sol::optional> res = game->getParser().safe_function( + game->getParser().core["block_place"], Api::Usertype::ServerPlayer(player.s()), Api::Usertype::Target(target)); + + auto stack = std::get>(res); + if (!stack) return; + + auto inv = player->getInventory(); + if (inv->hasList(player->getWieldList())) + inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); } -void ServerDimension::blockInteract(const Target &target, PlayerPtr player) { - game->getParser().safe_function(game->getParser().core["block_interact"], - Api::Usertype::ServerPlayer(player), Api::Usertype::Target(target)); +void ServerDimension::blockInteract(const Target& target, PlayerPtr player) { + game->getParser().safe_function(game->getParser().core["block_interact"], + Api::Usertype::ServerPlayer(player), Api::Usertype::Target(target)); } -void ServerDimension::blockPlaceOrInteract(const Target &target, PlayerPtr player) { - std::tuple, sol::optional> res = game->getParser().safe_function( - game->getParser().core["block_interact_or_place"], Api::Usertype::ServerPlayer(player), Api::Usertype::Target(target)); - - auto stack = std::get>(res); - if (!stack) return; - - auto inv = player.s()->getInventory(); - if (inv->hasList(player->getWieldList())) inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); +void ServerDimension::blockPlaceOrInteract(const Target& target, PlayerPtr player) { + std::tuple, sol::optional> res = game->getParser().safe_function( + game->getParser().core["block_interact_or_place"], Api::Usertype::ServerPlayer(player), + Api::Usertype::Target(target)); + + auto stack = std::get>(res); + if (!stack) return; + + auto inv = player.s()->getInventory(); + if (inv->hasList(player->getWieldList())) + inv->getList(player->getWieldList())->setStack(player->getWieldIndex(), ItemStack(*stack, game)); } void ServerDimension::setChunk(std::shared_ptr chunk) { - std::shared_ptr existing = getChunk(chunk->getPos()); - if (existing != nullptr) chunk = combinePartials(chunk, existing); - Dimension::setChunk(chunk); + std::shared_ptr existing = getChunk(chunk->getPos()); + if (existing != nullptr) chunk = combinePartials(chunk, existing); + Dimension::setChunk(chunk); } void ServerDimension::addLuaEntity(Api::Usertype::Entity entity) { - unsigned int id = entity.get_id(); - luaEntities.push_back(std::move(entity)); - luaEntityRefs.emplace(id, --luaEntities.end()); + unsigned int id = entity.get_id(); + luaEntities.push_back(std::move(entity)); + luaEntityRefs.emplace(id, --luaEntities.end()); } void ServerDimension::removeLuaEntity(Api::Usertype::Entity entity) { - unsigned int id = entity.get_id(); - if (!luaEntityRefs.count(id)) return; - - auto refIter = luaEntityRefs.at(id); - removedEntities.push_back(id); - - luaEntities.erase(refIter); - luaEntityRefs.erase(id); + unsigned int id = entity.get_id(); + if (!luaEntityRefs.count(id)) return; + + auto refIter = luaEntityRefs.at(id); + removedEntities.push_back(id); + + luaEntities.erase(refIter); + luaEntityRefs.erase(id); } -std::list &ServerDimension::getLuaEntities() { - return luaEntities; +std::list& ServerDimension::getLuaEntities() { + return luaEntities; } -const std::list &ServerDimension::getRemovedEntities() const { - return removedEntities; +const std::list& ServerDimension::getRemovedEntities() const { + return removedEntities; } void ServerDimension::clearRemovedEntities() { - removedEntities.clear(); + removedEntities.clear(); } \ No newline at end of file diff --git a/src/world/dim/ServerDimension.h b/src/world/dim/ServerDimension.h index c72737b9..1b64052e 100644 --- a/src/world/dim/ServerDimension.h +++ b/src/world/dim/ServerDimension.h @@ -11,35 +11,45 @@ #include "lua/usertype/Entity.h" class ServerWorld; + class ServerPlayer; + class ServerSubgame; class ServerDimension : public Dimension { -public: - ServerDimension(SubgamePtr game, ServerWorld& world, const std::string& identifier, unsigned int ind, std::shared_ptr mapGen); - - virtual void update(double delta) override; - - void setChunk(std::shared_ptr chunk) override; - - virtual void blockPlace(const Target &target, PlayerPtr player) override; - virtual void blockPlaceOrInteract(const Target &target, PlayerPtr player) override; - virtual void blockInteract(const Target &target, PlayerPtr player) override; - virtual double blockHit(const Target &target, PlayerPtr player) override; - - void addLuaEntity(Api::Usertype::Entity entity); - void removeLuaEntity(Api::Usertype::Entity entity); - - std::list& getLuaEntities(); - const std::list& getRemovedEntities() const; - void clearRemovedEntities(); -private: - typedef std::list::iterator luaent_ref; - - std::unordered_map luaEntityRefs {}; - std::list luaEntities {}; - std::list removedEntities {}; - - const glm::ivec2 discardRange = {20, 20}; + public: + ServerDimension(SubgamePtr game, ServerWorld& world, const std::string& identifier, unsigned int ind, + std::shared_ptr mapGen); + + virtual void update(double delta) override; + + void setChunk(std::shared_ptr chunk) override; + + virtual void blockPlace(const Target& target, PlayerPtr player) override; + + virtual void blockPlaceOrInteract(const Target& target, PlayerPtr player) override; + + virtual void blockInteract(const Target& target, PlayerPtr player) override; + + virtual double blockHit(const Target& target, PlayerPtr player) override; + + void addLuaEntity(Api::Usertype::Entity entity); + + void removeLuaEntity(Api::Usertype::Entity entity); + + std::list& getLuaEntities(); + + const std::list& getRemovedEntities() const; + + void clearRemovedEntities(); + + private: + typedef std::list::iterator luaent_ref; + + std::unordered_map luaEntityRefs{}; + std::list luaEntities{}; + std::list removedEntities{}; + + const glm::ivec2 discardRange = { 20, 20 }; }; diff --git a/src/world/dim/chunk/Chunk.cpp b/src/world/dim/chunk/Chunk.cpp index 189ebda9..3951f3e2 100644 --- a/src/world/dim/chunk/Chunk.cpp +++ b/src/world/dim/chunk/Chunk.cpp @@ -14,121 +14,122 @@ #include "game/atlas/DefinitionAtlas.h" Chunk::Chunk(const Chunk& o) : - pos(o.pos), - dirty(o.dirty), - blocks(o.blocks), - biomes(o.biomes), - partial(o.partial), - sunLight(o.sunLight), - generated(o.generated), - blockLight(o.blockLight), - shouldRender(o.shouldRender), - renderableBlocks(o.renderableBlocks) {} + pos(o.pos), + dirty(o.dirty), + blocks(o.blocks), + biomes(o.biomes), + partial(o.partial), + sunLight(o.sunLight), + generated(o.generated), + blockLight(o.blockLight), + shouldRender(o.shouldRender), + renderableBlocks(o.renderableBlocks) {} Chunk::Chunk(glm::ivec3 pos, bool partial) : pos(pos), partial(partial) {} Chunk::Chunk(glm::ivec3 pos, const std::vector& blocks, const std::vector& biomes) : - blocks(std::move(blocks)), biomes(std::move(biomes)), - generated(true), pos(pos) { - countRenderableBlocks(); + blocks(std::move(blocks)), biomes(std::move(biomes)), + generated(true), pos(pos) { + countRenderableBlocks(); } bool Chunk::setBlock(unsigned int ind, unsigned int blk) { - auto l = getWriteLock(); - if (!RIE::write(ind, blk, blocks, 4096)) return false; - l.unlock(); - - if (blk == DefinitionAtlas::AIR) { - renderableBlocks = std::max(renderableBlocks - 1, 0); - if (renderableBlocks == 0) shouldRender = false; - } - else { - shouldRender = true; - renderableBlocks++; - } - - return true; + auto l = getWriteLock(); + if (!RIE::write(ind, blk, blocks, 4096)) return false; + l.unlock(); + + if (blk == DefinitionAtlas::AIR) { + renderableBlocks = std::max(renderableBlocks - 1, 0); + if (renderableBlocks == 0) shouldRender = false; + } + else { + shouldRender = true; + renderableBlocks++; + } + + return true; } -const std::vector &Chunk::cGetBlocks() const { - return blocks; +const std::vector& Chunk::cGetBlocks() const { + return blocks; } -const std::vector &Chunk::cGetBiomes() const { - return biomes; +const std::vector& Chunk::cGetBiomes() const { + return biomes; } std::string Chunk::serialize() { - auto l = getReadLock(); - - std::vector blockLight = std::vector(4096); - std::vector sunLight = std::vector(2048); - - for (unsigned short i = 0; i < 4096; i++) { - blocklight_union bl; - bl.b = this->blockLight[i]; - blockLight[i] = bl.sh; - } - - for (unsigned short i = 0; i < 2048; i++) { - sunlight_union sl; - sl.s = this->sunLight[i]; - sunLight[i] = sl.ch; - } - - l.unlock(); - - Serializer s; - std::string temp = Serializer().append(pos).append(blocks).append(biomes).append(blockLight).append(sunLight).data; - s.append(gzip::compress(temp.data(), temp.size())); - - return s.data; + auto l = getReadLock(); + + std::vector blockLight = std::vector(4096); + std::vector sunLight = std::vector(2048); + + for (unsigned short i = 0; i < 4096; i++) { + blocklight_union bl; + bl.b = this->blockLight[i]; + blockLight[i] = bl.sh; + } + + for (unsigned short i = 0; i < 2048; i++) { + sunlight_union sl; + sl.s = this->sunLight[i]; + sunLight[i] = sl.ch; + } + + l.unlock(); + + Serializer s; + std::string temp = Serializer().append(pos).append(blocks).append(biomes).append(blockLight).append(sunLight).data; + s.append(gzip::compress(temp.data(), temp.size())); + + return s.data; } void Chunk::deserialize(Deserializer& d) { - auto l = getWriteLock(); - - std::string gzipped = d.read(); - if (!gzip::is_compressed(gzipped.data(), gzipped.length())) throw std::runtime_error("Chunk contains invalid gzipped data."); - - std::vector sunLight {}; - std::vector blockLight {}; - Deserializer(gzip::decompress(gzipped.data(), gzipped.length())) - .read(pos) - .read>(blocks) - .read>(biomes) - .read>(blockLight) - .read>(sunLight); - - for (unsigned short i = 0; i < 4096; i++) { - blocklight_union bl; - bl.sh = blockLight[i]; - this->blockLight[i] = bl.b; - } - - for (unsigned short i = 0; i < 2048; i++) { - sunlight_union sl; - sl.ch = sunLight[i]; - this->sunLight[i] = sl.s; - } - - l.unlock(); - countRenderableBlocks(); + auto l = getWriteLock(); + + std::string gzipped = d.read(); + if (!gzip::is_compressed(gzipped.data(), gzipped.length())) + throw std::runtime_error("Chunk contains invalid gzipped data."); + + std::vector sunLight{}; + std::vector blockLight{}; + Deserializer(gzip::decompress(gzipped.data(), gzipped.length())) + .read(pos) + .read>(blocks) + .read>(biomes) + .read>(blockLight) + .read>(sunLight); + + for (unsigned short i = 0; i < 4096; i++) { + blocklight_union bl; + bl.sh = blockLight[i]; + this->blockLight[i] = bl.b; + } + + for (unsigned short i = 0; i < 2048; i++) { + sunlight_union sl; + sl.ch = sunLight[i]; + this->sunLight[i] = sl.s; + } + + l.unlock(); + countRenderableBlocks(); } void Chunk::countRenderableBlocks() { - auto _ = getReadLock(); - - shouldRender = false; - renderableBlocks = 0; - - for (unsigned int i = 0; i < blocks.size(); i += 2) { - unsigned int nInd = (i == blocks.size() - 2 ? 4095 : blocks[i + 2]); - unsigned int cInd = blocks[i]; - - if (blocks[i + 1] > DefinitionAtlas::AIR) { - renderableBlocks += nInd - cInd; - shouldRender = true; - } - } + auto _ = getReadLock(); + + shouldRender = false; + renderableBlocks = 0; + + for (unsigned int i = 0; i < blocks.size(); i += 2) { + unsigned int nInd = (i == blocks.size() - 2 ? 4095 : blocks[i + 2]); + unsigned int cInd = blocks[i]; + + if (blocks[i + 1] > DefinitionAtlas::AIR) { + renderableBlocks += nInd - cInd; + shouldRender = true; + } + } } \ No newline at end of file diff --git a/src/world/dim/chunk/Chunk.h b/src/world/dim/chunk/Chunk.h index 16841074..8cfca00b 100644 --- a/src/world/dim/chunk/Chunk.h +++ b/src/world/dim/chunk/Chunk.h @@ -18,88 +18,112 @@ class Deserializer; class Chunk : public Lockable { -public: - friend class MapGen; - - struct BlockLight { - // 16 bits - 1 short - unsigned char r: 5; - unsigned char g: 5; - unsigned char b: 5, :1; - }; - typedef union { short sh; BlockLight b; } blocklight_union; - - struct SunLight { - // 8 bits for two values - 1 char - unsigned char a: 4; - unsigned char b: 4; - }; - typedef union { char ch; SunLight s; } sunlight_union; - - Chunk() = default; - Chunk(const Chunk& o); - Chunk(glm::ivec3 pos, bool partial = false); - Chunk(glm::ivec3 pos, const std::vector& blocks, const std::vector& biomes); - - inline glm::ivec3 getPos() const; - inline void setPos(glm::ivec3 pos); - - inline bool isDirty() const; - inline void setDirty(bool dirty); - - inline bool chunkShouldRender() const; - inline void setShouldRender(bool shouldRender); - - inline bool isPartial() const; - inline void setPartial(bool partial); - - inline bool isGenerated() const; - inline void setGenerated(bool generated); - - inline unsigned int getBlock(unsigned int ind) const; - bool setBlock(unsigned int ind, unsigned int blk); - - inline unsigned int getBlock(const glm::ivec3& pos) const; - inline bool setBlock(const glm::ivec3& pos, unsigned int blk); - - inline unsigned short getBiome(unsigned int ind) const; - inline bool setBiome(unsigned int ind, unsigned short bio); - - inline unsigned short getBiome(const glm::ivec3& pos) const; - inline bool setBiome(const glm::ivec3& pos, unsigned short bio); - - const std::vector& cGetBlocks() const; - const std::vector& cGetBiomes() const; - - inline glm::ivec4 getLight(unsigned int ind); - inline void setLight(unsigned int ind, glm::ivec4 light); - - inline unsigned char getLight(unsigned int ind, unsigned char channel); - inline void setLight(unsigned int ind, unsigned char channel, unsigned char light); - - std::string serialize(); - void deserialize(Deserializer& d); - - void countRenderableBlocks(); -private: - glm::ivec3 pos {}; - - bool partial = false; - bool generated = false; - - bool dirty = true; - bool shouldRender = true; - - std::vector blocks {0, 0}; - std::vector biomes {0, 0}; - - std::array sunLight {}; - std::array blockLight {}; - - unsigned short renderableBlocks = 0; - - inline unsigned char getSunlight(unsigned int ind); - inline void setSunlight(unsigned int ind, unsigned char val); + public: + friend class MapGen; + + struct BlockLight { + // 16 bits - 1 short + unsigned char r: 5; + unsigned char g: 5; + unsigned char b: 5, : 1; + }; + typedef union { + short sh; + BlockLight b; + } blocklight_union; + + struct SunLight { + // 8 bits for two values - 1 char + unsigned char a: 4; + unsigned char b: 4; + }; + typedef union { + char ch; + SunLight s; + } sunlight_union; + + Chunk() = default; + + Chunk(const Chunk& o); + + Chunk(glm::ivec3 pos, bool partial = false); + + Chunk(glm::ivec3 pos, const std::vector& blocks, const std::vector& biomes); + + inline glm::ivec3 getPos() const; + + inline void setPos(glm::ivec3 pos); + + inline bool isDirty() const; + + inline void setDirty(bool dirty); + + inline bool chunkShouldRender() const; + + inline void setShouldRender(bool shouldRender); + + inline bool isPartial() const; + + inline void setPartial(bool partial); + + inline bool isGenerated() const; + + inline void setGenerated(bool generated); + + inline unsigned int getBlock(unsigned int ind) const; + + bool setBlock(unsigned int ind, unsigned int blk); + + inline unsigned int getBlock(const glm::ivec3& pos) const; + + inline bool setBlock(const glm::ivec3& pos, unsigned int blk); + + inline unsigned short getBiome(unsigned int ind) const; + + inline bool setBiome(unsigned int ind, unsigned short bio); + + inline unsigned short getBiome(const glm::ivec3& pos) const; + + inline bool setBiome(const glm::ivec3& pos, unsigned short bio); + + const std::vector& cGetBlocks() const; + + const std::vector& cGetBiomes() const; + + inline glm::ivec4 getLight(unsigned int ind); + + inline void setLight(unsigned int ind, glm::ivec4 light); + + inline unsigned char getLight(unsigned int ind, unsigned char channel); + + inline void setLight(unsigned int ind, unsigned char channel, unsigned char light); + + std::string serialize(); + + void deserialize(Deserializer& d); + + void countRenderableBlocks(); + + private: + glm::ivec3 pos{}; + + bool partial = false; + bool generated = false; + + bool dirty = true; + bool shouldRender = true; + + std::vector blocks{ 0, 0 }; + std::vector biomes{ 0, 0 }; + + std::array sunLight{}; + std::array blockLight{}; + + unsigned short renderableBlocks = 0; + + inline unsigned char getSunlight(unsigned int ind); + + inline void setSunlight(unsigned int ind, unsigned char val); }; #include "Chunk.inl" \ No newline at end of file diff --git a/src/world/dim/chunk/Chunk.inl b/src/world/dim/chunk/Chunk.inl index 8a82125d..b4bb1b7a 100644 --- a/src/world/dim/chunk/Chunk.inl +++ b/src/world/dim/chunk/Chunk.inl @@ -1,128 +1,128 @@ glm::ivec3 Chunk::getPos() const { - auto l = getReadLock(); - return pos; + auto l = getReadLock(); + return pos; } void Chunk::setPos(glm::ivec3 pos) { - auto l = getWriteLock(); - this->pos = pos; + auto l = getWriteLock(); + this->pos = pos; } bool Chunk::isDirty() const { - auto l = getReadLock(); - return dirty; + auto l = getReadLock(); + return dirty; } void Chunk::setDirty(bool dirty) { - auto l = getWriteLock(); - this->dirty = dirty; + auto l = getWriteLock(); + this->dirty = dirty; } bool Chunk::chunkShouldRender() const { - auto l = getReadLock(); - return shouldRender; + auto l = getReadLock(); + return shouldRender; } void Chunk::setShouldRender(bool shouldRender) { - auto l = getWriteLock(); - this->shouldRender = shouldRender; + auto l = getWriteLock(); + this->shouldRender = shouldRender; } bool Chunk::isPartial() const { - auto l = getReadLock(); - return partial; + auto l = getReadLock(); + return partial; } void Chunk::setPartial(bool partial) { - auto l = getWriteLock(); - this->partial = partial; + auto l = getWriteLock(); + this->partial = partial; }; bool Chunk::isGenerated() const { - auto l = getReadLock(); - return generated; + auto l = getReadLock(); + return generated; } void Chunk::setGenerated(bool generated) { - auto l = getWriteLock(); - this->generated = generated; + auto l = getWriteLock(); + this->generated = generated; } inline unsigned int Chunk::getBlock(unsigned int ind) const { - auto l = getReadLock(); - if (ind >= 4096) return 0; // Invalid - return RIE::read(ind, blocks, 4096); + auto l = getReadLock(); + if (ind >= 4096) return 0; // Invalid + return RIE::read(ind, blocks, 4096); } inline unsigned int Chunk::getBlock(const glm::ivec3& pos) const { - if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return 0; // Invalid - return getBlock(Space::Block::index(pos)); + if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return 0; // Invalid + return getBlock(Space::Block::index(pos)); } inline bool Chunk::setBlock(const glm::ivec3& pos, unsigned int blk) { - if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false; - return setBlock(Space::Block::index(pos), blk); + if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false; + return setBlock(Space::Block::index(pos), blk); } inline unsigned short Chunk::getBiome(unsigned int ind) const { - auto l = getReadLock(); - if (ind >= 4096) return 0; // Invalid - return RIE::read(ind, biomes, 4096); + auto l = getReadLock(); + if (ind >= 4096) return 0; // Invalid + return RIE::read(ind, biomes, 4096); } inline unsigned short Chunk::getBiome(const glm::ivec3& pos) const { - if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return 0; // Invalid - return getBiome(Space::Block::index(pos)); + if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return 0; // Invalid + return getBiome(Space::Block::index(pos)); } inline bool Chunk::setBiome(unsigned int ind, unsigned short bio) { - auto l = getWriteLock(); - return RIE::write(ind, bio, biomes, 4096); + auto l = getWriteLock(); + return RIE::write(ind, bio, biomes, 4096); } inline bool Chunk::setBiome(const glm::ivec3& pos, unsigned short bio) { - if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false; - return setBiome(Space::Block::index(pos), bio); + if (pos.x > 15 || pos.x < 0 || pos.y > 15 || pos.y < 0 || pos.z > 15 || pos.z < 0) return false; + return setBiome(Space::Block::index(pos), bio); } inline glm::ivec4 Chunk::getLight(unsigned int ind) { - auto l = getReadLock(); - return { blockLight[ind].r, blockLight[ind].g, blockLight[ind].b, getSunlight(ind) }; + auto l = getReadLock(); + return { blockLight[ind].r, blockLight[ind].g, blockLight[ind].b, getSunlight(ind) }; } inline void Chunk::setLight(unsigned int ind, glm::ivec4 light) { - auto l = getWriteLock(); - blockLight[ind].r = light.x; - blockLight[ind].g = light.y; - blockLight[ind].b = light.z; - l.unlock(); - setSunlight(ind, light.w); + auto l = getWriteLock(); + blockLight[ind].r = light.x; + blockLight[ind].g = light.y; + blockLight[ind].b = light.z; + l.unlock(); + setSunlight(ind, light.w); } inline unsigned char Chunk::getLight(unsigned int ind, unsigned char channel) { - auto l = getReadLock(); - return channel == 0 ? blockLight[ind].r : - channel == 1 ? blockLight[ind].g : - channel == 2 ? blockLight[ind].b : - (l.unlock(), getSunlight(ind)); + auto l = getReadLock(); + return channel == 0 ? blockLight[ind].r : + channel == 1 ? blockLight[ind].g : + channel == 2 ? blockLight[ind].b : + (l.unlock(), getSunlight(ind)); } inline void Chunk::setLight(unsigned int ind, unsigned char channel, unsigned char light) { - auto l = getWriteLock(); - channel == 0 ? blockLight[ind].r = light : - channel == 1 ? blockLight[ind].g = light : - channel == 2 ? blockLight[ind].b = light : - (l.unlock(), setSunlight(ind,light), 0); + auto l = getWriteLock(); + channel == 0 ? blockLight[ind].r = light : + channel == 1 ? blockLight[ind].g = light : + channel == 2 ? blockLight[ind].b = light : + (l.unlock(), setSunlight(ind, light), 0); } inline unsigned char Chunk::getSunlight(unsigned int ind) { - auto l = getReadLock(); - if (ind % 2 == 0) return sunLight[ind / 2].a; - else return sunLight[ind / 2].b; + auto l = getReadLock(); + if (ind % 2 == 0) return sunLight[ind / 2].a; + else return sunLight[ind / 2].b; } inline void Chunk::setSunlight(unsigned int ind, unsigned char val) { - auto l = getWriteLock(); - if (ind % 2 == 0) sunLight[ind / 2].a = val; - else sunLight[ind / 2].b = val; + auto l = getWriteLock(); + if (ind % 2 == 0) sunLight[ind / 2].a = val; + else sunLight[ind / 2].b = val; } \ No newline at end of file diff --git a/src/world/dim/chunk/MapBlock.cpp b/src/world/dim/chunk/MapBlock.cpp index 7535473f..b454ee06 100644 --- a/src/world/dim/chunk/MapBlock.cpp +++ b/src/world/dim/chunk/MapBlock.cpp @@ -8,23 +8,23 @@ #include "util/net/Deserializer.h" MapBlock::MapBlock(glm::ivec3 pos) : - pos(pos) { - for(unsigned short i = 0; i < 64; i++) chunks[i] = nullptr; + pos(pos) { + for (unsigned short i = 0; i < 64; i++) chunks[i] = nullptr; } std::shared_ptr MapBlock::get(unsigned short index) const { - auto _ = getReadLock(); - return chunks[index]; + auto _ = getReadLock(); + return chunks[index]; } void MapBlock::set(unsigned short index, std::shared_ptr chunk) { - auto _ = getWriteLock(); - if (chunks[index] == nullptr) count++; - chunks[index] = chunk; + auto _ = getWriteLock(); + if (chunks[index] == nullptr) count++; + chunks[index] = chunk; } void MapBlock::remove(unsigned short index) { - auto _ = getWriteLock(); - if (chunks[index] != nullptr) count--; - chunks[index] = nullptr; + auto _ = getWriteLock(); + if (chunks[index] != nullptr) count--; + chunks[index] = nullptr; } \ No newline at end of file diff --git a/src/world/dim/chunk/MapBlock.h b/src/world/dim/chunk/MapBlock.h index 94b0595b..0b41bb3c 100644 --- a/src/world/dim/chunk/MapBlock.h +++ b/src/world/dim/chunk/MapBlock.h @@ -13,19 +13,22 @@ #include "util/Lockable.h" class Chunk; + class Deserializer; class MapBlock : Lockable { -public: - MapBlock(glm::ivec3 pos); - - std::shared_ptr get(unsigned short index) const; - void set(unsigned short index, std::shared_ptr chunk); - void remove(unsigned short index); - - glm::ivec3 pos {}; - bool generated = false; - unsigned short count = 0; -private: - std::array, 64> chunks; + public: + MapBlock(glm::ivec3 pos); + + std::shared_ptr get(unsigned short index) const; + + void set(unsigned short index, std::shared_ptr chunk); + + void remove(unsigned short index); + + glm::ivec3 pos{}; + bool generated = false; + unsigned short count = 0; + private: + std::array, 64> chunks; }; diff --git a/src/world/dim/chunk/Region.cpp b/src/world/dim/chunk/Region.cpp index d397d1e0..e401157e 100644 --- a/src/world/dim/chunk/Region.cpp +++ b/src/world/dim/chunk/Region.cpp @@ -7,23 +7,23 @@ #include "MapBlock.h" Region::Region(glm::ivec3 pos) : - pos(pos) { - for(unsigned short i = 0; i < 64; i++) mapBlocks[i] = nullptr; + pos(pos) { + for (unsigned short i = 0; i < 64; i++) mapBlocks[i] = nullptr; } std::shared_ptr Region::get(unsigned short index) const { - auto _ = getReadLock(); - return mapBlocks[index]; + auto _ = getReadLock(); + return mapBlocks[index]; } void Region::set(unsigned short index, std::shared_ptr block) { - auto _ = getWriteLock(); - if (mapBlocks[index] == nullptr) count++; - mapBlocks[index] = block; + auto _ = getWriteLock(); + if (mapBlocks[index] == nullptr) count++; + mapBlocks[index] = block; } void Region::remove(unsigned short index) { - auto _ = getWriteLock(); - if (mapBlocks[index] != nullptr) count--; - mapBlocks[index] = nullptr; + auto _ = getWriteLock(); + if (mapBlocks[index] != nullptr) count--; + mapBlocks[index] = nullptr; } diff --git a/src/world/dim/chunk/Region.h b/src/world/dim/chunk/Region.h index c559b7a7..b974c61a 100644 --- a/src/world/dim/chunk/Region.h +++ b/src/world/dim/chunk/Region.h @@ -14,15 +14,17 @@ class MapBlock; class Region : Lockable { -public: - Region(glm::ivec3 pos); - - std::shared_ptr get(unsigned short index) const; - void set(unsigned short index, std::shared_ptr block); - void remove(unsigned short index); - - glm::ivec3 pos {}; - unsigned short count = 0; -private: - std::array, 64> mapBlocks {}; + public: + Region(glm::ivec3 pos); + + std::shared_ptr get(unsigned short index) const; + + void set(unsigned short index, std::shared_ptr block); + + void remove(unsigned short index); + + glm::ivec3 pos{}; + unsigned short count = 0; + private: + std::array, 64> mapBlocks{}; }; diff --git a/src/world/dim/ent/AnimChannel.cpp b/src/world/dim/ent/AnimChannel.cpp index 45564a85..c16c4079 100644 --- a/src/world/dim/ent/AnimChannel.cpp +++ b/src/world/dim/ent/AnimChannel.cpp @@ -5,5 +5,5 @@ #include "AnimChannel.h" AnimChannel::AnimChannel(unsigned int index, const std::string& name) : - index(index), - name(name) {} + index(index), + name(name) {} diff --git a/src/world/dim/ent/AnimChannel.h b/src/world/dim/ent/AnimChannel.h index 06a4e3b7..7532a46d 100644 --- a/src/world/dim/ent/AnimChannel.h +++ b/src/world/dim/ent/AnimChannel.h @@ -10,14 +10,15 @@ #include class AnimChannel { -public: - AnimChannel() = default; - AnimChannel(unsigned int index, const std::string& name); - - int index = -1; - std::string name = ""; - - std::vector> positionKeys {}; - std::vector> scaleKeys {}; - std::vector> rotationKeys {}; + public: + AnimChannel() = default; + + AnimChannel(unsigned int index, const std::string& name); + + int index = -1; + std::string name = ""; + + std::vector> positionKeys{}; + std::vector> scaleKeys{}; + std::vector> rotationKeys{}; }; diff --git a/src/world/dim/ent/AnimationSegment.h b/src/world/dim/ent/AnimationSegment.h index 9f02c320..b19bb274 100644 --- a/src/world/dim/ent/AnimationSegment.h +++ b/src/world/dim/ent/AnimationSegment.h @@ -7,6 +7,6 @@ #include struct AnimationSegment { - std::string name; - glm::ivec2 range; + std::string name; + glm::ivec2 range; }; diff --git a/src/world/dim/ent/AnimationState.cpp b/src/world/dim/ent/AnimationState.cpp index a32fbde2..a143e040 100644 --- a/src/world/dim/ent/AnimationState.cpp +++ b/src/world/dim/ent/AnimationState.cpp @@ -8,64 +8,64 @@ #include "client/graph/ModelAnimation.h" #include "AnimationSegment.h" -AnimationState::AnimationState(Model &source) { - const ModelAnimation& animation = source.getAnimation(); - ticksPerSecond = animation.ticksPerSecond; - duration = animation.duration; - range = {0, duration}; +AnimationState::AnimationState(Model& source) { + const ModelAnimation& animation = source.getAnimation(); + ticksPerSecond = animation.ticksPerSecond; + duration = animation.duration; + range = { 0, duration }; } -void AnimationState::setAnimations(const std::vector &anims) { - for (auto& anim : anims) defineAnimation(anim.name, anim.range); +void AnimationState::setAnimations(const std::vector& anims) { + for (auto& anim : anims) defineAnimation(anim.name, anim.range); } void AnimationState::defineAnimation(const std::string& name, glm::ivec2 range) { - animations.emplace(name, AnimationSegment {name, range}); + animations.emplace(name, AnimationSegment{ name, range }); } void AnimationState::update(double delta) { - if (playing) { - float frame = currentFrame + (delta * ticksPerSecond); - if (loop) frame = fmod(frame - range.x, range.y - range.x) + range.x; - else frame = fmin(frame, range.y); - - if (frame == range.y) playing = false; - - currentFrame = frame; - } + if (playing) { + float frame = currentFrame + (delta * ticksPerSecond); + if (loop) frame = fmod(frame - range.x, range.y - range.x) + range.x; + else frame = fmin(frame, range.y); + + if (frame == range.y) playing = false; + + currentFrame = frame; + } } bool AnimationState::isLooping() { - return loop; + return loop; } void AnimationState::setAnim(const std::string& name, double interp, bool loop) { - auto& anim = animations[name]; - setAnim(anim.range, interp, loop); + auto& anim = animations[name]; + setAnim(anim.range, interp, loop); } void AnimationState::setAnim(glm::ivec2 range, double interp, bool loop) { - this->range = range; - this->loop = loop; - currentFrame = range.x; + this->range = range; + this->loop = loop; + currentFrame = range.x; } bool AnimationState::isPlaying() { - return playing; + return playing; } void AnimationState::setPlaying(bool playing) { - this->playing = playing; + this->playing = playing; } void AnimationState::setFrame(double frame) { - currentFrame = frame; + currentFrame = frame; } double AnimationState::getFrame() { - return currentFrame; + return currentFrame; } glm::ivec2 AnimationState::getBounds() { - return range; + return range; } diff --git a/src/world/dim/ent/AnimationState.h b/src/world/dim/ent/AnimationState.h index 6fa8b2c6..48c1b6ce 100644 --- a/src/world/dim/ent/AnimationState.h +++ b/src/world/dim/ent/AnimationState.h @@ -14,36 +14,42 @@ class Model; class AnimationState { -public: - AnimationState() = default; - explicit AnimationState(Model& source); - - void update(double delta); - - void setAnimations(const std::vector& anims); - void defineAnimation(const std::string& name, glm::ivec2 range); - - bool isLooping(); - void setAnim(const std::string& name, double interp, bool loop); - void setAnim(glm::ivec2 range, double interp, bool loop); - - bool isPlaying(); - void setPlaying(bool playing); - - double getFrame(); - void setFrame(double frame); - - glm::ivec2 getBounds(); - -private: - std::map animations; - - glm::ivec2 range; - - bool loop = false; - bool playing = false; - - double currentFrame = 0; - double ticksPerSecond = 0; - unsigned int duration = 0; + public: + AnimationState() = default; + + explicit AnimationState(Model& source); + + void update(double delta); + + void setAnimations(const std::vector& anims); + + void defineAnimation(const std::string& name, glm::ivec2 range); + + bool isLooping(); + + void setAnim(const std::string& name, double interp, bool loop); + + void setAnim(glm::ivec2 range, double interp, bool loop); + + bool isPlaying(); + + void setPlaying(bool playing); + + double getFrame(); + + void setFrame(double frame); + + glm::ivec2 getBounds(); + + private: + std::map animations; + + glm::ivec2 range; + + bool loop = false; + bool playing = false; + + double currentFrame = 0; + double ticksPerSecond = 0; + unsigned int duration = 0; }; diff --git a/src/world/dim/ent/Collision.cpp b/src/world/dim/ent/Collision.cpp index 61514d3d..b304add8 100644 --- a/src/world/dim/ent/Collision.cpp +++ b/src/world/dim/ent/Collision.cpp @@ -13,117 +13,120 @@ #include "game/def/mesh/SelectionBox.h" bool Collision::isOnGround(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3 pos, glm::vec3 vel) { - pos.y -= 0.05f; - return collidesAt(game, dim, collision, pos) && vel.y <= 0; + pos.y -= 0.05f; + return collidesAt(game, dim, collision, pos) && vel.y <= 0; } -void Collision::moveCollide(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, glm::vec3& vel, float stepUpAmount) { - const static double increment = 0.05; - - double moved = 0; - for (int i = 0; i < std::abs(vel.y) / increment; i++) { - double move = std::max(std::min(increment, std::abs(vel.y) - moved), 0.); - moved += increment; - - glm::vec3 newPos = pos; - newPos.y += move * (vel.y < 0 ? -1 : 1); - - if (!collidesAt(game, dim, collision, newPos)) pos = newPos; - else if (vel.y > 0) vel.y = 0; - } - - moved = 0; - for (int i = 0; i < std::abs(vel.x) / increment; i++) { - double move = std::max(std::min(increment,std::abs(vel.x) - moved), 0.); - moved += increment; - - glm::vec3 newPos = pos; - newPos.x += move * (vel.x < 0 ? -1 : 1); - - if (!collidesAt(game, dim, collision, newPos, stepUpAmount)) pos = newPos; - else vel.x = 0; - } - - moved = 0; - for (int i = 0; i < std::abs(vel.z) / increment; i++) { - double move = std::max(std::min(increment, std::abs(vel.z) - moved), 0.); - moved += increment; - - glm::vec3 newPos = pos; - newPos.z += move * (vel.z < 0 ? -1 : 1); - - if (!collidesAt(game, dim, collision, newPos, stepUpAmount)) pos = newPos; - else vel.z = 0; - } +void Collision::moveCollide(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, glm::vec3& vel, + float stepUpAmount) { + const static double increment = 0.05; + + double moved = 0; + for (int i = 0; i < std::abs(vel.y) / increment; i++) { + double move = std::max(std::min(increment, std::abs(vel.y) - moved), 0.); + moved += increment; + + glm::vec3 newPos = pos; + newPos.y += move * (vel.y < 0 ? -1 : 1); + + if (!collidesAt(game, dim, collision, newPos)) pos = newPos; + else if (vel.y > 0) vel.y = 0; + } + + moved = 0; + for (int i = 0; i < std::abs(vel.x) / increment; i++) { + double move = std::max(std::min(increment, std::abs(vel.x) - moved), 0.); + moved += increment; + + glm::vec3 newPos = pos; + newPos.x += move * (vel.x < 0 ? -1 : 1); + + if (!collidesAt(game, dim, collision, newPos, stepUpAmount)) pos = newPos; + else vel.x = 0; + } + + moved = 0; + for (int i = 0; i < std::abs(vel.z) / increment; i++) { + double move = std::max(std::min(increment, std::abs(vel.z) - moved), 0.); + moved += increment; + + glm::vec3 newPos = pos; + newPos.z += move * (vel.z < 0 ? -1 : 1); + + if (!collidesAt(game, dim, collision, newPos, stepUpAmount)) pos = newPos; + else vel.z = 0; + } } -bool Collision::collidesAt(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, float stepUpMax) { - - // Find the minimum vertical increase needed to step up - float stepUpAmount = 0; - if (stepUpMax > 0) { - glm::vec3 offset {}; - - offset.x = collision.a.x; - while (true) { - offset.y = collision.a.y; - while (true) { - offset.z = collision.a.z; - while (true) { - glm::vec3 offsetPos = glm::floor(pos + offset); - auto &def = game->getDefs().blockFromId(dim->getBlock(offsetPos)); - - if (def.solid) - for (auto &cBox : def.cBoxes) - stepUpAmount = std::fmax(cBox.b.y + offsetPos.y - pos.y, stepUpAmount); - - if (offset.z == collision.b.z) break; - offset.z = std::fmin(std::floor(offset.z + 1), collision.b.z); - } - if (offset.y == collision.a.y + stepUpMax + 0.025f) break; // Hack for precision errors - offset.y = std::fmin(std::floor(offset.y + 1), collision.a.y + stepUpMax + 0.025f); - } - if (offset.x == collision.b.x) break; - offset.x = std::fmin(std::floor(offset.x + 1), collision.b.x); - } - } - - // Step up if possible, or return false - if (stepUpAmount > stepUpMax) return true; - if (stepUpAmount > 0) pos.y += stepUpAmount + 0.025; // Hack for precision errors - - SelectionBox collidableBox = {collision.a + pos, collision.b + pos}; - glm::vec3 offset {}; - - // Regular collision check - offset.x = collision.a.x; - while (true) { - offset.y = collision.a.y; - while (true) { - offset.z = collision.a.z; - while (true) { - glm::vec3 offsetPos = glm::floor(pos + offset); - auto& def = game->getDefs().blockFromId(dim->getBlock(offsetPos)); - - if (def.solid) { - for (auto &cBox : def.cBoxes) { - SelectionBox blockBox = {cBox.a + offsetPos, cBox.b + offsetPos}; - - if ((blockBox.a.x <= collidableBox.b.x && blockBox.b.x >= collidableBox.a.x) && - (blockBox.a.y <= collidableBox.b.y && blockBox.b.y >= collidableBox.a.y) && - (blockBox.a.z <= collidableBox.b.z && blockBox.b.z >= collidableBox.a.z)) return true; - } - } - - if (offset.z == collision.b.z) break; - offset.z = (std::min)(std::floor(offset.z + 1), collision.b.z); - } - if (offset.y == collision.b.y) break; - offset.y = (std::min)(std::floor(offset.y + 1), collision.b.y); - } - if (offset.x == collision.b.x) break; - offset.x = (std::min)(std::floor(offset.x + 1), collision.b.x); - } - - return false; +bool +Collision::collidesAt(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, float stepUpMax) { + + // Find the minimum vertical increase needed to step up + float stepUpAmount = 0; + if (stepUpMax > 0) { + glm::vec3 offset{}; + + offset.x = collision.a.x; + while (true) { + offset.y = collision.a.y; + while (true) { + offset.z = collision.a.z; + while (true) { + glm::vec3 offsetPos = glm::floor(pos + offset); + auto& def = game->getDefs().blockFromId(dim->getBlock(offsetPos)); + + if (def.solid) + for (auto& cBox : def.cBoxes) + stepUpAmount = std::fmax(cBox.b.y + offsetPos.y - pos.y, stepUpAmount); + + if (offset.z == collision.b.z) break; + offset.z = std::fmin(std::floor(offset.z + 1), collision.b.z); + } + if (offset.y == collision.a.y + stepUpMax + 0.025f) break; // Hack for precision errors + offset.y = std::fmin(std::floor(offset.y + 1), collision.a.y + stepUpMax + 0.025f); + } + if (offset.x == collision.b.x) break; + offset.x = std::fmin(std::floor(offset.x + 1), collision.b.x); + } + } + + // Step up if possible, or return false + if (stepUpAmount > stepUpMax) return true; + if (stepUpAmount > 0) pos.y += stepUpAmount + 0.025; // Hack for precision errors + + SelectionBox collidableBox = { collision.a + pos, collision.b + pos }; + glm::vec3 offset{}; + + // Regular collision check + offset.x = collision.a.x; + while (true) { + offset.y = collision.a.y; + while (true) { + offset.z = collision.a.z; + while (true) { + glm::vec3 offsetPos = glm::floor(pos + offset); + auto& def = game->getDefs().blockFromId(dim->getBlock(offsetPos)); + + if (def.solid) { + for (auto& cBox : def.cBoxes) { + SelectionBox blockBox = { cBox.a + offsetPos, cBox.b + offsetPos }; + + if ((blockBox.a.x <= collidableBox.b.x && blockBox.b.x >= collidableBox.a.x) && + (blockBox.a.y <= collidableBox.b.y && blockBox.b.y >= collidableBox.a.y) && + (blockBox.a.z <= collidableBox.b.z && blockBox.b.z >= collidableBox.a.z)) + return true; + } + } + + if (offset.z == collision.b.z) break; + offset.z = (std::min)(std::floor(offset.z + 1), collision.b.z); + } + if (offset.y == collision.b.y) break; + offset.y = (std::min)(std::floor(offset.y + 1), collision.b.y); + } + if (offset.x == collision.b.x) break; + offset.x = (std::min)(std::floor(offset.x + 1), collision.b.x); + } + + return false; } \ No newline at end of file diff --git a/src/world/dim/ent/Collision.h b/src/world/dim/ent/Collision.h index 258e797c..02f49b76 100644 --- a/src/world/dim/ent/Collision.h +++ b/src/world/dim/ent/Collision.h @@ -9,12 +9,18 @@ #include "util/CovariantPtr.h" class Subgame; + class Dimension; + class SelectionBox; class Collision { -public: - static bool isOnGround(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3 pos, glm::vec3 vel); - static void moveCollide(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, glm::vec3& vel, float stepUpAmount = 0); - static bool collidesAt(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, float stepUpMax = 0); + public: + static bool isOnGround(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3 pos, glm::vec3 vel); + + static void moveCollide(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, glm::vec3& vel, + float stepUpAmount = 0); + + static bool + collidesAt(SubgamePtr game, DimensionPtr dim, SelectionBox& collision, glm::vec3& pos, float stepUpMax = 0); }; diff --git a/src/world/dim/ent/DrawableEntity.cpp b/src/world/dim/ent/DrawableEntity.cpp index 3ac7a7aa..cad975d6 100644 --- a/src/world/dim/ent/DrawableEntity.cpp +++ b/src/world/dim/ent/DrawableEntity.cpp @@ -13,130 +13,130 @@ DrawableEntity::DrawableEntity(SubgamePtr game, DimensionPtr dim) : - Entity(game, dim), - model(std::make_shared()) {} + Entity(game, dim), + model(std::make_shared()) {} DrawableEntity::DrawableEntity(SubgamePtr game, DimensionPtr dim, std::shared_ptr model) : - Entity(game, dim), - model(model) {} + Entity(game, dim), + model(model) {} void DrawableEntity::setModel(std::shared_ptr model) { - animation = AnimationState(*model); - this->model = std::move(model); - animation.setPlaying(true); + animation = AnimationState(*model); + this->model = std::move(model); + animation.setPlaying(true); } void DrawableEntity::update(double delta) { - Entity::update(delta); - - float factor = static_cast(fmin(delta * 8, 1)); - - visualPosition = visualPosition * (1 - factor) + pos * factor; - visualVisualOffset = visualVisualOffset * (1 - factor) + visualOff * factor; - visualRotation = visualRotation * (1 - factor) + rot * factor; - visualScale = visualScale * (1 - factor) + scale * factor; + Entity::update(delta); + + float factor = static_cast(fmin(delta * 8, 1)); + + visualPosition = visualPosition * (1 - factor) + pos * factor; + visualVisualOffset = visualVisualOffset * (1 - factor) + visualOff * factor; + visualRotation = visualRotation * (1 - factor) + rot * factor; + visualScale = visualScale * (1 - factor) + scale * factor; } void DrawableEntity::setPos(glm::vec3 position) { - visualPosition = position; - Entity::setPos(position); + visualPosition = position; + Entity::setPos(position); } void DrawableEntity::interpPos(glm::vec3 position) { - Entity::setPos(position); + Entity::setPos(position); } void DrawableEntity::setVisualOffset(glm::vec3 vs) { - visualVisualOffset = vs; - Entity::setVisualOffset(vs); + visualVisualOffset = vs; + Entity::setVisualOffset(vs); } void DrawableEntity::interpVisualOffset(glm::vec3 vs) { - Entity::setVisualOffset(vs); + Entity::setVisualOffset(vs); } void DrawableEntity::setRotateX(float rotation) { - visualRotation.x = rotation; - Entity::setRotateX(rotation); + visualRotation.x = rotation; + Entity::setRotateX(rotation); } void DrawableEntity::interpRotateX(float rotation) { - Entity::setRotateX(rotation); + Entity::setRotateX(rotation); } void DrawableEntity::setRotateY(float rotation) { - visualRotation.y = rotation; - Entity::setRotateY(rotation); + visualRotation.y = rotation; + Entity::setRotateY(rotation); } void DrawableEntity::interpRotateY(float rotation) { - Entity::setRotateY(rotation); + Entity::setRotateY(rotation); } void DrawableEntity::setRotateZ(float rotation) { - visualRotation.z = rotation; - Entity::setRotateZ(rotation); - + visualRotation.z = rotation; + Entity::setRotateZ(rotation); + } void DrawableEntity::interpRotateZ(float rotation) { - Entity::setRotateZ(rotation); + Entity::setRotateZ(rotation); } void DrawableEntity::setScale(float scale) { - visualScale = glm::vec3(scale); - Entity::setScale(scale); + visualScale = glm::vec3(scale); + Entity::setScale(scale); } void DrawableEntity::interpScale(float scale) { - Entity::setScale(scale); + Entity::setScale(scale); } void DrawableEntity::setScale(glm::vec3 scale) { - visualScale = scale; - Entity::setScale(scale); - + visualScale = scale; + Entity::setScale(scale); + } void DrawableEntity::interpScale(glm::vec3 scale) { - Entity::setScale(scale); + Entity::setScale(scale); } void DrawableEntity::draw(Renderer& renderer) { - if (visible) { - renderer.setModelMatrix(getModelMatrix()); - - model->getTransformsByFrame(animation.getFrame(), animation.getBounds(), transforms); - renderer.setBones(transforms); - - for (const auto& mesh : model->meshes) mesh->draw(); - } + if (visible) { + renderer.setModelMatrix(getModelMatrix()); + + model->getTransformsByFrame(animation.getFrame(), animation.getBounds(), transforms); + renderer.setBones(transforms); + + for (const auto& mesh : model->meshes) mesh->draw(); + } } glm::mat4 DrawableEntity::getModelMatrix() { - glm::mat4 model = glm::mat4(1.0); - - model = glm::translate(model, visualPosition + visualVisualOffset); - model = model * getRotationMatrix(); - model = glm::scale(model, visualScale); - - return model; + glm::mat4 model = glm::mat4(1.0); + + model = glm::translate(model, visualPosition + visualVisualOffset); + model = model * getRotationMatrix(); + model = glm::scale(model, visualScale); + + return model; } glm::mat4 DrawableEntity::getRotationMatrix() { - glm::mat4 parentMatrix = (parent != nullptr ? parent->getRotationMatrix() : glm::mat4(1.0f)); - glm::mat4 rotMatrix = glm::mat4(1.0f); - rotMatrix = glm::rotate(rotMatrix, glm::radians(visualRotation.x), {1, 0, 0}); - rotMatrix = glm::rotate(rotMatrix, glm::radians(visualRotation.y), {0, 1, 0}); - rotMatrix = glm::rotate(rotMatrix, glm::radians(visualRotation.z), {0, 0, 1}); - return parentMatrix * rotMatrix; + glm::mat4 parentMatrix = (parent != nullptr ? parent->getRotationMatrix() : glm::mat4(1.0f)); + glm::mat4 rotMatrix = glm::mat4(1.0f); + rotMatrix = glm::rotate(rotMatrix, glm::radians(visualRotation.x), { 1, 0, 0 }); + rotMatrix = glm::rotate(rotMatrix, glm::radians(visualRotation.y), { 0, 1, 0 }); + rotMatrix = glm::rotate(rotMatrix, glm::radians(visualRotation.z), { 0, 0, 1 }); + return parentMatrix * rotMatrix; } void DrawableEntity::cleanup() { - model = nullptr; + model = nullptr; } DrawableEntity::~DrawableEntity() { - cleanup(); + cleanup(); } \ No newline at end of file diff --git a/src/world/dim/ent/DrawableEntity.h b/src/world/dim/ent/DrawableEntity.h index eca8f10b..67d17f3e 100644 --- a/src/world/dim/ent/DrawableEntity.h +++ b/src/world/dim/ent/DrawableEntity.h @@ -13,51 +13,65 @@ #include "client/graph/Drawable.h" class DrawableEntity : virtual public Entity, public Drawable { -public: - DrawableEntity(const DrawableEntity& o) = delete; - DrawableEntity() = default; - DrawableEntity(SubgamePtr game, DimensionPtr dim); - explicit DrawableEntity(SubgamePtr game, DimensionPtr dim, std::shared_ptr model); - - void update(double delta) override; - void setModel(std::shared_ptr model); - - virtual void setPos(glm::vec3 position) override; - virtual void interpPos(glm::vec3 position); - - virtual void setVisualOffset(glm::vec3 vs) override; - virtual void interpVisualOffset(glm::vec3 vs); - - virtual void setRotateX(float rotation) override; - virtual void interpRotateX(float rotation); - - virtual void setRotateY(float rotation) override; - virtual void interpRotateY(float rotation); - - virtual void setRotateZ(float rotation) override; - virtual void interpRotateZ(float rotation); - - virtual void setScale(float scale) override; - virtual void interpScale(float scale); - virtual void setScale(glm::vec3 scale) override; - virtual void interpScale(glm::vec3 scale); - - void draw(Renderer& renderer) override; - - void cleanup(); - ~DrawableEntity() override; - - DrawableEntity* parent = nullptr; -protected: - glm::mat4 getModelMatrix(); - glm::mat4 getRotationMatrix(); - - glm::vec3 visualPosition {}; - glm::vec3 visualVisualOffset {}; - glm::vec3 visualRotation {}; - glm::vec3 visualScale {1, 1, 1}; - - std::shared_ptr model; - std::vector transforms {}; + public: + DrawableEntity(const DrawableEntity& o) = delete; + + DrawableEntity() = default; + + DrawableEntity(SubgamePtr game, DimensionPtr dim); + + explicit DrawableEntity(SubgamePtr game, DimensionPtr dim, std::shared_ptr model); + + void update(double delta) override; + + void setModel(std::shared_ptr model); + + virtual void setPos(glm::vec3 position) override; + + virtual void interpPos(glm::vec3 position); + + virtual void setVisualOffset(glm::vec3 vs) override; + + virtual void interpVisualOffset(glm::vec3 vs); + + virtual void setRotateX(float rotation) override; + + virtual void interpRotateX(float rotation); + + virtual void setRotateY(float rotation) override; + + virtual void interpRotateY(float rotation); + + virtual void setRotateZ(float rotation) override; + + virtual void interpRotateZ(float rotation); + + virtual void setScale(float scale) override; + + virtual void interpScale(float scale); + + virtual void setScale(glm::vec3 scale) override; + + virtual void interpScale(glm::vec3 scale); + + void draw(Renderer& renderer) override; + + void cleanup(); + + ~DrawableEntity() override; + + DrawableEntity* parent = nullptr; + protected: + glm::mat4 getModelMatrix(); + + glm::mat4 getRotationMatrix(); + + glm::vec3 visualPosition{}; + glm::vec3 visualVisualOffset{}; + glm::vec3 visualRotation{}; + glm::vec3 visualScale{ 1, 1, 1 }; + + std::shared_ptr model; + std::vector transforms{}; }; diff --git a/src/world/dim/ent/Entity.cpp b/src/world/dim/ent/Entity.cpp index ff558dd1..1367fd9d 100644 --- a/src/world/dim/ent/Entity.cpp +++ b/src/world/dim/ent/Entity.cpp @@ -5,93 +5,93 @@ #include "Entity.h" unsigned int Entity::getId() { - return id; + return id; } void Entity::setId(unsigned int id) { - this->id = id; + this->id = id; } glm::vec3 Entity::getPos() { - return pos; + return pos; } void Entity::setPos(glm::vec3 position) { - this->pos = position; + this->pos = position; } glm::vec3 Entity::getVel() { - return vel; + return vel; } void Entity::setVel(glm::vec3 velocity) { - this->vel = velocity; + this->vel = velocity; } glm::vec3 Entity::getRot() { - return rot; + return rot; } void Entity::setRot(glm::vec3 rot) { - this->rot = rot; + this->rot = rot; } glm::vec3 Entity::getVisualOffset() { - return visualOff; + return visualOff; } void Entity::setVisualOffset(glm::vec3 vs) { - this->visualOff = vs; + this->visualOff = vs; } float Entity::getRotateX() { - return rot.x; + return rot.x; } void Entity::setRotateX(float rotation) { - this->rot.x = rotation; + this->rot.x = rotation; } float Entity::getRotateY() { - return rot.y; + return rot.y; } void Entity::setRotateY(float rotation) { - this->rot.y = rotation; + this->rot.y = rotation; } float Entity::getRotateZ() { - return rot.z; + return rot.z; } void Entity::setRotateZ(float rotation) { - this->rot.z = rotation; + this->rot.z = rotation; } glm::vec3 Entity::getScale() { - return scale; + return scale; } void Entity::setScale(float scale) { - this->scale = glm::vec3(scale); + this->scale = glm::vec3(scale); } void Entity::setScale(glm::vec3 scale) { - this->scale = scale; + this->scale = scale; } DimensionPtr Entity::getDim() { - return dim; + return dim; } void Entity::setDim(DimensionPtr dim) { - this->dim = dim; + this->dim = dim; } SubgamePtr Entity::getGame() { - return game; + return game; } void Entity::update(double delta) { - animation.update(delta); + animation.update(delta); } diff --git a/src/world/dim/ent/Entity.h b/src/world/dim/ent/Entity.h index 591c3e8b..8cd38da9 100644 --- a/src/world/dim/ent/Entity.h +++ b/src/world/dim/ent/Entity.h @@ -11,57 +11,69 @@ #include "game/def/mesh/SelectionBox.h" class Entity { -public: - Entity() = default; - Entity(SubgamePtr game, DimensionPtr dim) : game(game), dim(dim) {}; - - virtual void update(double delta); - - virtual glm::vec3 getPos(); - virtual void setPos(glm::vec3 position); - - virtual glm::vec3 getVel(); - virtual void setVel(glm::vec3 velocity); - - virtual glm::vec3 getRot(); - virtual void setRot(glm::vec3 rot); - - virtual glm::vec3 getVisualOffset(); - virtual void setVisualOffset(glm::vec3 vs); - - virtual float getRotateX(); - virtual void setRotateX(float rotation); - - virtual float getRotateY(); - virtual void setRotateY(float rotation); - - virtual float getRotateZ(); - virtual void setRotateZ(float rotation); - - virtual glm::vec3 getScale(); - virtual void setScale(float scale); - virtual void setScale(glm::vec3 scale); - - virtual unsigned int getId(); - virtual void setId(unsigned int id); - - virtual DimensionPtr getDim(); - virtual void setDim(DimensionPtr dim); - - SubgamePtr getGame(); - - AnimationState animation {}; -protected: - SubgamePtr game = nullptr; - DimensionPtr dim = nullptr; - - unsigned int id = 0; - - glm::vec3 pos {}; - glm::vec3 vel {}; - glm::vec3 rot {}; - glm::vec3 visualOff {}; - glm::vec3 scale {1, 1, 1}; - - SelectionBox collision; + public: + Entity() = default; + + Entity(SubgamePtr game, DimensionPtr dim) : game(game), dim(dim) {}; + + virtual void update(double delta); + + virtual glm::vec3 getPos(); + + virtual void setPos(glm::vec3 position); + + virtual glm::vec3 getVel(); + + virtual void setVel(glm::vec3 velocity); + + virtual glm::vec3 getRot(); + + virtual void setRot(glm::vec3 rot); + + virtual glm::vec3 getVisualOffset(); + + virtual void setVisualOffset(glm::vec3 vs); + + virtual float getRotateX(); + + virtual void setRotateX(float rotation); + + virtual float getRotateY(); + + virtual void setRotateY(float rotation); + + virtual float getRotateZ(); + + virtual void setRotateZ(float rotation); + + virtual glm::vec3 getScale(); + + virtual void setScale(float scale); + + virtual void setScale(glm::vec3 scale); + + virtual unsigned int getId(); + + virtual void setId(unsigned int id); + + virtual DimensionPtr getDim(); + + virtual void setDim(DimensionPtr dim); + + SubgamePtr getGame(); + + AnimationState animation{}; + protected: + SubgamePtr game = nullptr; + DimensionPtr dim = nullptr; + + unsigned int id = 0; + + glm::vec3 pos{}; + glm::vec3 vel{}; + glm::vec3 rot{}; + glm::vec3 visualOff{}; + glm::vec3 scale{ 1, 1, 1 }; + + SelectionBox collision; }; diff --git a/src/world/dim/ent/LocalLuaEntity.cpp b/src/world/dim/ent/LocalLuaEntity.cpp index 619984e6..db41040c 100644 --- a/src/world/dim/ent/LocalLuaEntity.cpp +++ b/src/world/dim/ent/LocalLuaEntity.cpp @@ -9,17 +9,17 @@ #include "game/atlas/DefinitionAtlas.h" LocalLuaEntity::LocalLuaEntity(SubgamePtr game, DimensionPtr dim) : - LuaEntity(game, dim), DrawableEntity(game, dim), Entity(game, dim) {} + LuaEntity(game, dim), DrawableEntity(game, dim), Entity(game, dim) {} -void LocalLuaEntity::setAppearance(const std::string &dMode, const std::string &argA, const std::string &argB) { - if (dMode == "gameobject" && (argA == "block" || argA == "craftitem")) { - ItemDef& def = getGame()->getDefs().fromStr(argB); - setModel(def.entityModel); - } - else if (dMode == "model" && !argB.empty()) { - auto model = std::make_shared(); - model->fromSerialized(getGame().l()->models.models[argA], { getGame().l()->textures[argB] }); - setModel(model); - } - else throw std::runtime_error("Invalid appearance arguments specified."); +void LocalLuaEntity::setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) { + if (dMode == "gameobject" && (argA == "block" || argA == "craftitem")) { + ItemDef& def = getGame()->getDefs().fromStr(argB); + setModel(def.entityModel); + } + else if (dMode == "model" && !argB.empty()) { + auto model = std::make_shared(); + model->fromSerialized(getGame().l()->models.models[argA], { getGame().l()->textures[argB] }); + setModel(model); + } + else throw std::runtime_error("Invalid appearance arguments specified."); } \ No newline at end of file diff --git a/src/world/dim/ent/LocalLuaEntity.h b/src/world/dim/ent/LocalLuaEntity.h index a324e9a7..aaa18696 100644 --- a/src/world/dim/ent/LocalLuaEntity.h +++ b/src/world/dim/ent/LocalLuaEntity.h @@ -8,8 +8,8 @@ #include "DrawableEntity.h" class LocalLuaEntity : public virtual DrawableEntity, public LuaEntity { -public: - LocalLuaEntity(SubgamePtr game, DimensionPtr dim); - - virtual void setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) override; + public: + LocalLuaEntity(SubgamePtr game, DimensionPtr dim); + + virtual void setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) override; }; diff --git a/src/world/dim/ent/LuaEntity.h b/src/world/dim/ent/LuaEntity.h index 4e988925..1dcbf79f 100644 --- a/src/world/dim/ent/LuaEntity.h +++ b/src/world/dim/ent/LuaEntity.h @@ -7,8 +7,8 @@ #include "Entity.h" class LuaEntity : public virtual Entity { -public: - LuaEntity(SubgamePtr game, DimensionPtr dim); - - virtual void setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) = 0; + public: + LuaEntity(SubgamePtr game, DimensionPtr dim); + + virtual void setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) = 0; }; diff --git a/src/world/dim/ent/ServerLuaEntity.cpp b/src/world/dim/ent/ServerLuaEntity.cpp index 87a4c17b..96cd4a1d 100644 --- a/src/world/dim/ent/ServerLuaEntity.cpp +++ b/src/world/dim/ent/ServerLuaEntity.cpp @@ -10,85 +10,89 @@ #include "util/net/Serializer.h" void ServerLuaEntity::setDim(DimensionPtr dim) { - Entity::setDim(dim); - dirtyFields.emplace(NetField::DIM); + Entity::setDim(dim); + dirtyFields.emplace(NetField::DIM); } void ServerLuaEntity::setPos(glm::vec3 position) { - Entity::setPos(position); - dirtyFields.emplace(NetField::POS); + Entity::setPos(position); + dirtyFields.emplace(NetField::POS); } void ServerLuaEntity::setVel(glm::vec3 vel) { - Entity::setVel(rot); - dirtyFields.emplace(NetField::VEL); + Entity::setVel(rot); + dirtyFields.emplace(NetField::VEL); } void ServerLuaEntity::setRot(glm::vec3 rot) { - Entity::setRot(rot); - dirtyFields.emplace(NetField::ROT); + Entity::setRot(rot); + dirtyFields.emplace(NetField::ROT); } void ServerLuaEntity::setScale(float scale) { - Entity::setScale(scale); - dirtyFields.emplace(NetField::SCALE); + Entity::setScale(scale); + dirtyFields.emplace(NetField::SCALE); } void ServerLuaEntity::setScale(glm::vec3 scale) { - Entity::setScale(scale); - dirtyFields.emplace(NetField::SCALE); + Entity::setScale(scale); + dirtyFields.emplace(NetField::SCALE); } void ServerLuaEntity::setRotateX(float rotation) { - Entity::setRotateX(rotation); - dirtyFields.emplace(NetField::ROT); + Entity::setRotateX(rotation); + dirtyFields.emplace(NetField::ROT); } void ServerLuaEntity::setRotateY(float rotation) { - Entity::setRotateY(rotation); - dirtyFields.emplace(NetField::ROT); + Entity::setRotateY(rotation); + dirtyFields.emplace(NetField::ROT); } void ServerLuaEntity::setRotateZ(float rotation) { - Entity::setRotateZ(rotation); - dirtyFields.emplace(NetField::ROT); + Entity::setRotateZ(rotation); + dirtyFields.emplace(NetField::ROT); } void ServerLuaEntity::setVisualOffset(glm::vec3 vs) { - Entity::setVisualOffset(vs); - dirtyFields.emplace(NetField::VISUAL_OFF); + Entity::setVisualOffset(vs); + dirtyFields.emplace(NetField::VISUAL_OFF); } void ServerLuaEntity::setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) { - this->dMode = dMode; - this->dArgA = argA; - this->dArgB = argB; - dirtyFields.emplace(NetField::DISPLAY); + this->dMode = dMode; + this->dArgA = argA; + this->dArgB = argB; + dirtyFields.emplace(NetField::DISPLAY); } void ServerLuaEntity::dirtyField(NetField field) { - dirtyFields.emplace(field); + dirtyFields.emplace(field); } std::string ServerLuaEntity::serialize() { - if (dirtyFields.empty() && !fullSend) return {}; - - Serializer s; - s.append(id); - - if (dirtyFields.count(NetField::DIM) || fullSend) s.appendE(NetField::DIM) .append(dim->getInd()); - if (dirtyFields.count(NetField::POS) || fullSend) s.appendE(NetField::POS) .append(pos); - if (dirtyFields.count(NetField::VEL) || fullSend) s.appendE(NetField::VEL) .append(vel); - if (dirtyFields.count(NetField::SCALE) || fullSend) s.appendE(NetField::SCALE) .append(scale); - if (dirtyFields.count(NetField::ROT) || fullSend) s.appendE(NetField::ROT) .append(rot); - if (dirtyFields.count(NetField::VISUAL_OFF) || fullSend) s.appendE(NetField::VISUAL_OFF).append(visualOff); - if (dirtyFields.count(NetField::ANIM_STATE) || fullSend) s.appendE(NetField::ANIM_STATE).append(animation.isPlaying()); - if (dirtyFields.count(NetField::DISPLAY) || fullSend) s.appendE(NetField::DISPLAY) .append(dMode).append(dArgA).append(dArgB); - if (dirtyFields.count(NetField::ANIM_RANGE) || fullSend) s.appendE(NetField::ANIM_RANGE) - .append(animation.getBounds().x).append(animation.getBounds().y).append(animation.isLooping()); - - dirtyFields.clear(); - fullSend = false; - - return s.data; + if (dirtyFields.empty() && !fullSend) return {}; + + Serializer s; + s.append(id); + + if (dirtyFields.count(NetField::DIM) || fullSend) s.appendE(NetField::DIM).append(dim->getInd()); + if (dirtyFields.count(NetField::POS) || fullSend) s.appendE(NetField::POS).append(pos); + if (dirtyFields.count(NetField::VEL) || fullSend) s.appendE(NetField::VEL).append(vel); + if (dirtyFields.count(NetField::SCALE) || fullSend) s.appendE(NetField::SCALE).append(scale); + if (dirtyFields.count(NetField::ROT) || fullSend) s.appendE(NetField::ROT).append(rot); + if (dirtyFields.count(NetField::VISUAL_OFF) || fullSend) s.appendE(NetField::VISUAL_OFF).append(visualOff); + if (dirtyFields.count(NetField::ANIM_STATE) || fullSend) + s.appendE(NetField::ANIM_STATE).append(animation.isPlaying()); + if (dirtyFields.count(NetField::DISPLAY) || fullSend) + s.appendE(NetField::DISPLAY).append(dMode).append(dArgA).append(dArgB); + if (dirtyFields.count(NetField::ANIM_RANGE) || fullSend) + s.appendE(NetField::ANIM_RANGE) + .append(animation.getBounds().x).append(animation.getBounds().y).append( + animation.isLooping()); + + dirtyFields.clear(); + fullSend = false; + + return s.data; } \ No newline at end of file diff --git a/src/world/dim/ent/ServerLuaEntity.h b/src/world/dim/ent/ServerLuaEntity.h index fe81fd1b..92b41c8f 100644 --- a/src/world/dim/ent/ServerLuaEntity.h +++ b/src/world/dim/ent/ServerLuaEntity.h @@ -14,32 +14,44 @@ #include "util/net/NetField.h" class ServerLuaEntity : public LuaEntity { -public: - explicit ServerLuaEntity(SubgamePtr game, DimensionPtr dim, unsigned int id) : - LuaEntity(game, dim), Entity(game, dim) { - setId(id); }; - - virtual void setDim(DimensionPtr dim) override; - virtual void setPos(glm::vec3 position) override; - virtual void setVel(glm::vec3 vel) override; - virtual void setRot(glm::vec3 rot) override; - virtual void setScale(float scale) override; - virtual void setScale(glm::vec3 scale) override; - virtual void setRotateX(float rotation) override; - virtual void setRotateY(float rotation) override; - virtual void setRotateZ(float rotation) override; - virtual void setVisualOffset(glm::vec3 vs) override; - - void setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) override; - void dirtyField(NetField field); - - std::string serialize(); -protected: - std::string dMode = ""; - std::string dArgA = ""; - std::string dArgB = ""; - - std::set dirtyFields; - bool fullSend = true; + public: + explicit ServerLuaEntity(SubgamePtr game, DimensionPtr dim, unsigned int id) : + LuaEntity(game, dim), Entity(game, dim) { + setId(id); + }; + + virtual void setDim(DimensionPtr dim) override; + + virtual void setPos(glm::vec3 position) override; + + virtual void setVel(glm::vec3 vel) override; + + virtual void setRot(glm::vec3 rot) override; + + virtual void setScale(float scale) override; + + virtual void setScale(glm::vec3 scale) override; + + virtual void setRotateX(float rotation) override; + + virtual void setRotateY(float rotation) override; + + virtual void setRotateZ(float rotation) override; + + virtual void setVisualOffset(glm::vec3 vs) override; + + void setAppearance(const std::string& dMode, const std::string& argA, const std::string& argB) override; + + void dirtyField(NetField field); + + std::string serialize(); + + protected: + std::string dMode = ""; + std::string dArgA = ""; + std::string dArgB = ""; + + std::set dirtyFields; + bool fullSend = true; }; diff --git a/src/world/dim/file/FileManipulator.cpp b/src/world/dim/file/FileManipulator.cpp index 61d8531c..3a3d277d 100644 --- a/src/world/dim/file/FileManipulator.cpp +++ b/src/world/dim/file/FileManipulator.cpp @@ -20,99 +20,101 @@ #include "util/net/Deserializer.h" #include "world/dim/chunk/Chunk.h" -FileManipulator::FileManipulator(const std::string &worldPath) : - path(worldPath) { +FileManipulator::FileManipulator(const std::string& worldPath) : + path(worldPath) { } -void FileManipulator::commitChunk(Chunk &chunk) { - glm::ivec3 reg = Space::Region::world::fromChunk(chunk.getPos()); - unsigned int chunkInd = Space::Chunk::index(chunk.getPos()); - - std::string fileName = std::to_string(reg.x) + "_" + std::to_string(reg.y) + "_" + std::to_string(reg.z); - std::string filePath = path + "/" + fileName; - createRegionFileIfNotExists(reg); - - std::string chunkData = chunk.serialize(); - unsigned int dataBlockSize = floor(chunkData.length() / BLOCK_SIZE); - - std::fstream file(filePath, std::ios::in|std::ios::out|std::ios::binary); - if (!file.is_open()) throw std::runtime_error("Couldn't open file."); - - std::array chunkOffsets {}; - populateChunkOffsets(file, chunkOffsets); - - unsigned int currentBlock = chunkOffsets[chunkInd]; - unsigned int nextBlock = (chunkInd == 63 ? 10000 : chunkOffsets[chunkInd + 1]); - - if (dataBlockSize > nextBlock - currentBlock) - shiftChunks(file, chunkOffsets, chunkInd + 1, dataBlockSize - (nextBlock - currentBlock)); - writeChunk(file, chunkOffsets[chunkInd], chunkData); - - file.close(); +void FileManipulator::commitChunk(Chunk& chunk) { + glm::ivec3 reg = Space::Region::world::fromChunk(chunk.getPos()); + unsigned int chunkInd = Space::Chunk::index(chunk.getPos()); + + std::string fileName = std::to_string(reg.x) + "_" + std::to_string(reg.y) + "_" + std::to_string(reg.z); + std::string filePath = path + "/" + fileName; + createRegionFileIfNotExists(reg); + + std::string chunkData = chunk.serialize(); + unsigned int dataBlockSize = floor(chunkData.length() / BLOCK_SIZE); + + std::fstream file(filePath, std::ios::in | std::ios::out | std::ios::binary); + if (!file.is_open()) throw std::runtime_error("Couldn't open file."); + + std::array chunkOffsets{}; + populateChunkOffsets(file, chunkOffsets); + + unsigned int currentBlock = chunkOffsets[chunkInd]; + unsigned int nextBlock = (chunkInd == 63 ? 10000 : chunkOffsets[chunkInd + 1]); + + if (dataBlockSize > nextBlock - currentBlock) + shiftChunks(file, chunkOffsets, chunkInd + 1, dataBlockSize - (nextBlock - currentBlock)); + writeChunk(file, chunkOffsets[chunkInd], chunkData); + + file.close(); } void FileManipulator::writeChunk(std::fstream& file, unsigned int offset, const std::string& data) { - file.seekp(META_OFFSET + offset * BLOCK_SIZE); - file.write(data.data(), data.length()); + file.seekp(META_OFFSET + offset * BLOCK_SIZE); + file.write(data.data(), data.length()); } -void FileManipulator::shiftChunks(std::fstream &file, std::array& offsets, unsigned int ind, unsigned int amt) { - std::cout << "Shifting by " << amt << std::endl; - - unsigned int startPos = offsets[ind] * BLOCK_SIZE + META_OFFSET; - unsigned int endPos; { - char *buff = new char[4]; - file.seekg(META_OFFSET + offsets[63] * BLOCK_SIZE); - file.read(buff, 4); - endPos = META_OFFSET + BLOCK_SIZE * offsets[63] + Deserializer(buff, 4).read(); - } - - unsigned int len = endPos - startPos; - char* buff = new char[len]; - file.seekg(offsets[ind]); - file.read(buff, len); - file.seekp(offsets[ind] + amt * BLOCK_SIZE); - file.write(buff, len); - delete[] buff; - - for (unsigned int i = ind; i < 4096; i++) { - offsets[i] += amt; - Serializer s; - s.append(offsets[i]); - file.seekp(12 + i * 2); - file.write(s.data.data(), s.data.length()); - file.close(); - } - - std::cout << "Shift done" << std::endl; +void +FileManipulator::shiftChunks(std::fstream& file, std::array& offsets, unsigned int ind, unsigned int amt) { + std::cout << "Shifting by " << amt << std::endl; + + unsigned int startPos = offsets[ind] * BLOCK_SIZE + META_OFFSET; + unsigned int endPos; + { + char* buff = new char[4]; + file.seekg(META_OFFSET + offsets[63] * BLOCK_SIZE); + file.read(buff, 4); + endPos = META_OFFSET + BLOCK_SIZE * offsets[63] + Deserializer(buff, 4).read(); + } + + unsigned int len = endPos - startPos; + char* buff = new char[len]; + file.seekg(offsets[ind]); + file.read(buff, len); + file.seekp(offsets[ind] + amt * BLOCK_SIZE); + file.write(buff, len); + delete[] buff; + + for (unsigned int i = ind; i < 4096; i++) { + offsets[i] += amt; + Serializer s; + s.append(offsets[i]); + file.seekp(12 + i * 2); + file.write(s.data.data(), s.data.length()); + file.close(); + } + + std::cout << "Shift done" << std::endl; } void FileManipulator::populateChunkOffsets(std::fstream& file, std::array& offsets) { - file.seekg(12); - char* buff = new char[2]; - for (unsigned int i = 0; i < 4096; i++) { - file.read(buff, 2); - offsets[i] = Deserializer(buff, 2).read(); - } - delete[] buff; + file.seekg(12); + char* buff = new char[2]; + for (unsigned int i = 0; i < 4096; i++) { + file.read(buff, 2); + offsets[i] = Deserializer(buff, 2).read(); + } + delete[] buff; } void FileManipulator::createRegionFileIfNotExists(glm::ivec3 pos) { - std::string fileName = std::to_string(pos.x) + "_" + std::to_string(pos.y) + "_" + std::to_string(pos.z); - std::string filePath = path + fileName; - - if (cf_file_exists(filePath.data())) return; - - std::fstream file(filePath, std::ios::out|std::ios::binary); - if (!file.is_open()) throw std::runtime_error("Couldn't open file."); - file.seekp(0); - - Serializer s; - s.append(pos); - for (int i = 0; i < 4096; i++) s.append(i); - for (int i = 0; i < 4096 * BLOCK_SIZE; i++) s.append(0); - - file.write(s.data.data(), s.data.length()); - file.close(); + std::string fileName = std::to_string(pos.x) + "_" + std::to_string(pos.y) + "_" + std::to_string(pos.z); + std::string filePath = path + fileName; + + if (cf_file_exists(filePath.data())) return; + + std::fstream file(filePath, std::ios::out | std::ios::binary); + if (!file.is_open()) throw std::runtime_error("Couldn't open file."); + file.seekp(0); + + Serializer s; + s.append(pos); + for (int i = 0; i < 4096; i++) s.append(i); + for (int i = 0; i < 4096 * BLOCK_SIZE; i++) s.append(0); + + file.write(s.data.data(), s.data.length()); + file.close(); } \ No newline at end of file diff --git a/src/world/dim/file/FileManipulator.h b/src/world/dim/file/FileManipulator.h index aadc53df..9842e41a 100644 --- a/src/world/dim/file/FileManipulator.h +++ b/src/world/dim/file/FileManipulator.h @@ -13,18 +13,21 @@ class Chunk; class FileManipulator { - static constexpr unsigned int META_OFFSET = 12 + 2 * 4096; - static constexpr unsigned int BLOCK_SIZE = 256; -public: - FileManipulator(const std::string& worldPath); - - void commitChunk(Chunk& chunk); - -private: - static void writeChunk(std::fstream& file, unsigned int offset, const std::string& data); - static void shiftChunks(std::fstream& file, std::array& offsets, unsigned int ind, unsigned int amt); - static void populateChunkOffsets(std::fstream& file, std::array& offsets); - void createRegionFileIfNotExists(glm::ivec3 pos); - - std::string path; + static constexpr unsigned int META_OFFSET = 12 + 2 * 4096; + static constexpr unsigned int BLOCK_SIZE = 256; + public: + FileManipulator(const std::string& worldPath); + + void commitChunk(Chunk& chunk); + + private: + static void writeChunk(std::fstream& file, unsigned int offset, const std::string& data); + + static void shiftChunks(std::fstream& file, std::array& offsets, unsigned int ind, unsigned int amt); + + static void populateChunkOffsets(std::fstream& file, std::array& offsets); + + void createRegionFileIfNotExists(glm::ivec3 pos); + + std::string path; }; diff --git a/src/world/gen/MapGen.cpp b/src/world/gen/MapGen.cpp index 1ad509b4..179406f0 100644 --- a/src/world/gen/MapGen.cpp +++ b/src/world/gen/MapGen.cpp @@ -18,28 +18,29 @@ #include "util/Schematic.h" MapGen::MapGen(Subgame& game, World& world, unsigned int seed, std::unordered_set biomes) : - game(game), world(world), props(seed) { + game(game), world(world), props(seed) { - std::unordered_set biomeIndices {}; - for (const auto& str : biomes) { - if (str[0] == '#') { - for (auto& biome : game.getBiomes().biomesFromTag(str.substr(1, str.length() - 1))) { - biomeIndices.insert(biome->index); - } - } - else biomeIndices.insert(game.getBiomes().biomeFromStr(str).index); - } - - generateVoronoi(biomeIndices); + std::unordered_set biomeIndices{}; + for (const auto& str : biomes) { + if (str[0] == '#') { + for (auto& biome : game.getBiomes().biomesFromTag(str.substr(1, str.length() - 1))) { + biomeIndices.insert(biome->index); + } + } + else biomeIndices.insert(game.getBiomes().biomeFromStr(str).index); + } + + generateVoronoi(biomeIndices); } void MapGen::generateVoronoi(const std::unordered_set& biomes) { - std::vector> points {}; + std::vector> points{}; for (auto biomeInd : biomes) { auto& biome = game.getBiomes().biomeFromId(biomeInd); - points.emplace_back(glm::vec3 { - static_cast(std::fmin(voronoiSize - 1, std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))), + points.emplace_back(glm::vec3{ + static_cast(std::fmin(voronoiSize - 1, + std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))), static_cast(std::fmin(voronoiSize - 1, std::fmax(0, biome.humidity * voronoiSize))), static_cast(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize))) }, biomeInd); @@ -56,225 +57,234 @@ unsigned int MapGen::getBiomeAt(float temperature, float humidity, float roughne } std::unique_ptr MapGen::generateChunk(unsigned int dim, glm::ivec3 pos) { - return generateArea(dim, pos, 1); + return generateArea(dim, pos, 1); } std::unique_ptr MapGen::generateMapBlock(unsigned int dim, glm::ivec3 pos) { - return generateArea(dim, Space::Chunk::world::fromMapBlock(glm::vec3(pos)), 4); + return generateArea(dim, Space::Chunk::world::fromMapBlock(glm::vec3(pos)), 4); } std::unique_ptr MapGen::generateArea(unsigned int dim, glm::ivec3 origin, unsigned int size) { Job job(origin, size); - - // Build Biome Prop Maps - - const auto fill = [&](const noise::module::Module& s) { - return [&](glm::vec3 pos) { - glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast(job.size); - return s.GetValue(worldPos.x, 0, worldPos.z); - }; - }; - - job.temperature.populate(fill(props.temperature)); - job.roughness.populate(fill(props.roughness)); - job.humidity.populate(fill(props.humidity)); - - // Generate Biome Topmap - - std::vector biomeMap {}; - biomeMap.resize((job.size * 16 + 1) * (job.size * 16 + 1)); - - for (unsigned short i = 0; i < biomeMap.size(); i++) { - glm::vec3 indPos = { i / (job.size * 16 + 1), 0, i % (job.size * 16 + 1)}; - glm::vec3 queryPos = indPos / 16.f / static_cast(job.size); - biomeMap[i] = getBiomeAt(job.temperature.get(queryPos), - job.humidity.get(queryPos), job.roughness.get(queryPos)); - } - - // Generate Heightmap and Volume - - job.heightmap.populate([&](glm::vec3 pos) { - glm::ivec3 blockPos = glm::ivec3(pos * 16.f * static_cast(job.size)); - auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z)); - glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast(job.size); - return biome.heightmap[biome.heightmap.size() - 1]->GetValue(worldPos.x, 0, worldPos.z); - }); - - job.volume.populate([&](glm::vec3 pos) { - glm::ivec3 blockPos = glm::ivec3(pos * 16.f * static_cast(job.size)); - auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z)); - glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast(job.size); - return biome.volume[biome.volume.size() - 1]->GetValue(worldPos.x, worldPos.y, worldPos.z); - }); - - // Generate Chunks - - glm::ivec3 pos {}; - for (pos.x = 0; pos.x < job.size; pos.x++) - for (pos.z = 0; pos.z < job.size; pos.z++) { - std::unique_ptr densityAbove = nullptr; - for (pos.y = job.size; pos.y >= 0; pos.y--) { - if (pos.y == job.size) { densityAbove = populateChunkDensity(job, pos); continue; } - - std::unique_ptr density = populateChunkDensity(job, pos); - std::unique_ptr depth = populateChunkDepth(job, density, std::move(densityAbove)); - - generateChunkBlocks(job, pos, biomeMap, *depth); - generateChunkStructures(job, pos, biomeMap, *depth); - - densityAbove = std::move(density); - } - } + // Build Biome Prop Maps + + const auto fill = [&](const noise::module::Module& s) { + return [&](glm::vec3 pos) { + glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast(job.size); + return s.GetValue(worldPos.x, 0, worldPos.z); + }; + }; + + job.temperature.populate(fill(props.temperature)); + job.roughness.populate(fill(props.roughness)); + job.humidity.populate(fill(props.humidity)); + + // Generate Biome Topmap + + std::vector biomeMap{}; + biomeMap.resize((job.size * 16 + 1) * (job.size * 16 + 1)); + + for (unsigned short i = 0; i < biomeMap.size(); i++) { + glm::vec3 indPos = { i / (job.size * 16 + 1), 0, i % (job.size * 16 + 1) }; + glm::vec3 queryPos = indPos / 16.f / static_cast(job.size); + + biomeMap[i] = getBiomeAt(job.temperature.get(queryPos), + job.humidity.get(queryPos), job.roughness.get(queryPos)); + } + + // Generate Heightmap and Volume + + job.heightmap.populate([&](glm::vec3 pos) { + glm::ivec3 blockPos = glm::ivec3(pos * 16.f * static_cast(job.size)); + auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z)); + glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast(job.size); + return biome.heightmap[biome.heightmap.size() - 1]->GetValue(worldPos.x, 0, worldPos.z); + }); + + job.volume.populate([&](glm::vec3 pos) { + glm::ivec3 blockPos = glm::ivec3(pos * 16.f * static_cast(job.size)); + auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z)); + glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast(job.size); + return biome.volume[biome.volume.size() - 1]->GetValue(worldPos.x, worldPos.y, worldPos.z); + }); + + // Generate Chunks + + glm::ivec3 pos{}; + for (pos.x = 0; pos.x < job.size; pos.x++) + for (pos.z = 0; pos.z < job.size; pos.z++) { + std::unique_ptr densityAbove = nullptr; + for (pos.y = job.size; pos.y >= 0; pos.y--) { + if (pos.y == job.size) { + densityAbove = populateChunkDensity(job, pos); + continue; + } + + std::unique_ptr density = populateChunkDensity(job, pos); + std::unique_ptr depth = populateChunkDepth(job, density, std::move(densityAbove)); + + generateChunkBlocks(job, pos, biomeMap, *depth); + generateChunkStructures(job, pos, biomeMap, *depth); + + densityAbove = std::move(density); + } + } // generateSunlight(chunks, mbPos); - - auto created = std::make_unique(); - for (const auto& chunk : *job.chunks) { - created->emplace(chunk.first); - world.getDimension(dim)->setChunk(chunk.second); - } - + + auto created = std::make_unique(); + for (const auto& chunk : *job.chunks) { + created->emplace(chunk.first); + world.getDimension(dim)->setChunk(chunk.second); + } + return std::move(created); } -std::unique_ptr MapGen::populateChunkDensity(MapGen::Job &job, glm::ivec3 localPos) { - auto data = std::make_unique(); - - for (int i = 0; i < 4096; i++) { - glm::ivec3 indPos = Space::Block::fromIndex(i); - glm::vec3 queryPos = (glm::vec3(localPos) + glm::vec3(indPos) / 16.f) / static_cast(job.size); - (*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({queryPos.x, 0, queryPos.z})) - ((job.pos.y + localPos.y) * 16 + indPos.y); - } - - return data; +std::unique_ptr MapGen::populateChunkDensity(MapGen::Job& job, glm::ivec3 localPos) { + auto data = std::make_unique(); + + for (int i = 0; i < 4096; i++) { + glm::ivec3 indPos = Space::Block::fromIndex(i); + glm::vec3 queryPos = (glm::vec3(localPos) + glm::vec3(indPos) / 16.f) / static_cast(job.size); + (*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({ queryPos.x, 0, queryPos.z })) - + ((job.pos.y + localPos.y) * 16 + indPos.y); + } + + return data; } -std::unique_ptr MapGen::populateChunkDepth(Job& job, std::unique_ptr& chunkDensity, std::unique_ptr chunkDensityAbove) { - auto data = std::make_unique(); - - for (unsigned short i = 0; i < 256; i++) { - glm::ivec2 pos = { i / 16, i % 16 }; - short depth = 16; - - if ((*chunkDensity)[Space::Block::index({pos.x, 15, pos.y})] > 0) { - for (unsigned char j = 0; j < 16; j++) { - if ((*chunkDensityAbove)[Space::Block::index({pos.x, j, pos.y})] <= 0) { - depth = j; - break; - } - } - } - else { - depth = 0; - } - - for (char y = 15; y >= 0; y--) { - unsigned int ind = Space::Block::index({pos.x, y, pos.y}); - depth = ((*chunkDensity)[ind] > 0 ? std::min(depth + 1, 16) : 0); - (*data)[ind] = depth + ((*chunkDensity)[ind] - static_cast((*chunkDensity)[ind])); - } - } - - return data; +std::unique_ptr MapGen::populateChunkDepth(Job& job, std::unique_ptr& chunkDensity, + std::unique_ptr chunkDensityAbove) { + auto data = std::make_unique(); + + for (unsigned short i = 0; i < 256; i++) { + glm::ivec2 pos = { i / 16, i % 16 }; + short depth = 16; + + if ((*chunkDensity)[Space::Block::index({ pos.x, 15, pos.y })] > 0) { + for (unsigned char j = 0; j < 16; j++) { + if ((*chunkDensityAbove)[Space::Block::index({ pos.x, j, pos.y })] <= 0) { + depth = j; + break; + } + } + } + else { + depth = 0; + } + + for (char y = 15; y >= 0; y--) { + unsigned int ind = Space::Block::index({ pos.x, y, pos.y }); + depth = ((*chunkDensity)[ind] > 0 ? std::min(depth + 1, 16) : 0); + (*data)[ind] = depth + ((*chunkDensity)[ind] - static_cast((*chunkDensity)[ind])); + } + } + + return data; } -void MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap) { - glm::ivec3 chunkPos = job.pos + localPos; - - auto partial = (job.chunks->count(chunkPos) ? job.chunks->at(chunkPos) : nullptr); - if (partial) job.chunks->erase(chunkPos); - - auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared(chunkPos)).first).second; - - unsigned int cBlockID = 0; - unsigned int cBiomeID = 0; - - unsigned int partialBlock = DefinitionAtlas::INVALID; - int partialInd = -1; - unsigned int partialNextAt = 0; - - for (unsigned short i = 0; i < 4096; i++) { - glm::ivec3 indPos = Space::Block::fromIndex(i); - - unsigned int biomeID = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)]; - auto& biome = game.getBiomes().biomeFromId(biomeID); - - if (partial && i >= partialNextAt) { - partialInd++; - partialBlock = partial->blocks[partialInd * 2 + 1]; - partialNextAt = (partialInd * 2 + 2 >= partial->blocks.size()) ? 4096 : partial->blocks[partialInd * 2 + 2]; - } - - float depth = depthMap[i]; - unsigned int blockID - = partialBlock != DefinitionAtlas::INVALID ? partialBlock - : depth <= 1 ? DefinitionAtlas::AIR - : depth <= 2 ? biome.topBlock - : depth <= 4 ? biome.soilBlock - : biome.rockBlock; - - if (biomeID != cBiomeID) { - chunk.biomes.emplace_back(i); - chunk.biomes.emplace_back(biomeID); - cBiomeID = biomeID; - } - - if (blockID != cBlockID) { - chunk.blocks.emplace_back(i); - chunk.blocks.emplace_back(blockID); - cBlockID = blockID; - } - } - - chunk.countRenderableBlocks(); - chunk.generated = true; +void +MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap) { + glm::ivec3 chunkPos = job.pos + localPos; + + auto partial = (job.chunks->count(chunkPos) ? job.chunks->at(chunkPos) : nullptr); + if (partial) job.chunks->erase(chunkPos); + + auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared(chunkPos)).first).second; + + unsigned int cBlockID = 0; + unsigned int cBiomeID = 0; + + unsigned int partialBlock = DefinitionAtlas::INVALID; + int partialInd = -1; + unsigned int partialNextAt = 0; + + for (unsigned short i = 0; i < 4096; i++) { + glm::ivec3 indPos = Space::Block::fromIndex(i); + + unsigned int biomeID = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + + (localPos.z * 16 + indPos.z)]; + auto& biome = game.getBiomes().biomeFromId(biomeID); + + if (partial && i >= partialNextAt) { + partialInd++; + partialBlock = partial->blocks[partialInd * 2 + 1]; + partialNextAt = (partialInd * 2 + 2 >= partial->blocks.size()) ? 4096 : partial->blocks[partialInd * 2 + 2]; + } + + float depth = depthMap[i]; + unsigned int blockID + = partialBlock != DefinitionAtlas::INVALID ? partialBlock + : depth <= 1 ? DefinitionAtlas::AIR + : depth <= 2 ? biome.topBlock + : depth <= 4 ? biome.soilBlock + : biome.rockBlock; + + if (biomeID != cBiomeID) { + chunk.biomes.emplace_back(i); + chunk.biomes.emplace_back(biomeID); + cBiomeID = biomeID; + } + + if (blockID != cBlockID) { + chunk.blocks.emplace_back(i); + chunk.blocks.emplace_back(blockID); + cBlockID = blockID; + } + } + + chunk.countRenderableBlocks(); + chunk.generated = true; } -void MapGen::generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap) { - glm::vec3 posFloat = job.pos + localPos; - std::default_random_engine generator(posFloat.x + posFloat.y / M_PI + posFloat.z / (M_PI*2)); - std::uniform_real_distribution distribution(0, 1); - - auto& chunk = job.chunks->at(job.pos + localPos); - - for (unsigned short i = 0; i < 256; i++) { - glm::ivec3 indPos = { i / 16, 0, i % 16 }; - if (distribution(generator) > 0.97) { - for (indPos.y = 0; indPos.y < 16; indPos.y++) { - - unsigned short ind = Space::Block::index(indPos); - if (depthMap[ind] > 0 && depthMap[ind] <= 1.1) { - - glm::ivec3 pos = (job.pos + localPos) * 16 + indPos; - - unsigned int biomeID = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)]; - auto& biome = game.getBiomes().biomeFromId(biomeID); - - auto schematic = biome.schematics.size() > 0 ? biome.schematics[0] : nullptr; - if (schematic) { - if (!schematic->processed) schematic->process(game.getDefs()); - for (unsigned int j = 0; j < schematic->length(); j++) { - glm::ivec3 off = schematic->getOffset(j); - setBlock(job, pos + off - schematic->origin, schematic->blocks[j], chunk); - } - } - } - } - } - } +void MapGen::generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector biomeMap, + ChunkData& depthMap) { + glm::vec3 posFloat = job.pos + localPos; + std::default_random_engine generator(posFloat.x + posFloat.y / M_PI + posFloat.z / (M_PI * 2)); + std::uniform_real_distribution distribution(0, 1); + + auto& chunk = job.chunks->at(job.pos + localPos); + + for (unsigned short i = 0; i < 256; i++) { + glm::ivec3 indPos = { i / 16, 0, i % 16 }; + if (distribution(generator) > 0.97) { + for (indPos.y = 0; indPos.y < 16; indPos.y++) { + + unsigned short ind = Space::Block::index(indPos); + if (depthMap[ind] > 0 && depthMap[ind] <= 1.1) { + + glm::ivec3 pos = (job.pos + localPos) * 16 + indPos; + + unsigned int biomeID = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + + (localPos.z * 16 + indPos.z)]; + auto& biome = game.getBiomes().biomeFromId(biomeID); + + auto schematic = biome.schematics.size() > 0 ? biome.schematics[0] : nullptr; + if (schematic) { + if (!schematic->processed) schematic->process(game.getDefs()); + for (unsigned int j = 0; j < schematic->length(); j++) { + glm::ivec3 off = schematic->getOffset(j); + setBlock(job, pos + off - schematic->origin, schematic->blocks[j], chunk); + } + } + } + } + } + } } -void MapGen::setBlock(MapGen::Job &job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr hint) { - if (block == DefinitionAtlas::INVALID) return; - - glm::ivec3 chunkPos = Space::Chunk::world::fromBlock(worldPos); - auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared(chunkPos, true)).first).second; +void MapGen::setBlock(MapGen::Job& job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr hint) { + if (block == DefinitionAtlas::INVALID) return; + + glm::ivec3 chunkPos = Space::Chunk::world::fromBlock(worldPos); + auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared(chunkPos, true)).first).second; // if (!job.chunks->count(chunkPos)) return; // auto& chunk = *job.chunks->at(chunkPos); - - unsigned int ind = Space::Block::index(worldPos); - if (chunk.getBlock(ind) <= DefinitionAtlas::AIR) chunk.setBlock(ind, block); + + unsigned int ind = Space::Block::index(worldPos); + if (chunk.getBlock(ind) <= DefinitionAtlas::AIR) chunk.setBlock(ind, block); } //void MapGen::generateSunlight(MapGen::chunk_partials_map &chunks, glm::ivec3 mbPos) { diff --git a/src/world/gen/MapGen.h b/src/world/gen/MapGen.h index 0eab067a..fddc6272 100644 --- a/src/world/gen/MapGen.h +++ b/src/world/gen/MapGen.h @@ -17,66 +17,80 @@ #include "util/Voronoi3D.h" class World; + class Chunk; + class Subgame; + class BiomeDef; + class BiomeAtlas; + class DefinitionAtlas; class MapGen { -public: - constexpr static unsigned int BIOP = 4; // Biome Prop Precision - constexpr static unsigned int TERP = 4; // Terrain Map Precision - - typedef std::unordered_map, Vec::ivec3> ChunkMap; - typedef std::unordered_set CreatedSet; - - struct Job { - Job(glm::ivec3 pos, unsigned int size) : - pos(pos), size(size), - volume {{size * TERP, (size + 1) * TERP}, {1, 1.25}}, heightmap {{size * TERP, 0}}, - temperature {{size * BIOP, 0}}, roughness {{size * BIOP, 0}}, humidity {{size * BIOP, 0}} {} - - glm::ivec3 pos {}; - unsigned int size {}; - - std::unique_ptr chunks = std::make_unique(); - - NoiseSample volume, heightmap; - NoiseSample temperature, humidity, roughness; - }; - - typedef std::array ChunkData; - - MapGen(const MapGen& o) = delete; + public: + constexpr static unsigned int BIOP = 4; // Biome Prop Precision + constexpr static unsigned int TERP = 4; // Terrain Map Precision + + typedef std::unordered_map, Vec::ivec3> ChunkMap; + typedef std::unordered_set CreatedSet; + + struct Job { + Job(glm::ivec3 pos, unsigned int size) : + pos(pos), size(size), + volume{{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap{{ size * TERP, 0 }}, + temperature{{ size * BIOP, 0 }}, roughness{{ size * BIOP, 0 }}, humidity{{ size * BIOP, 0 }} {} + + glm::ivec3 pos{}; + unsigned int size{}; + + std::unique_ptr chunks = std::make_unique(); + + NoiseSample volume, heightmap; + NoiseSample temperature, humidity, roughness; + }; + + typedef std::array ChunkData; + + MapGen(const MapGen& o) = delete; + MapGen(Subgame& game, World& world, unsigned int seed, std::unordered_set biomes); - - std::unique_ptr generateChunk(unsigned int dim, glm::ivec3 pos); - std::unique_ptr generateMapBlock(unsigned int dim, glm::ivec3 pos); - std::unique_ptr generateArea(unsigned int dim, glm::ivec3 origin, unsigned int size = 1); -private: + + std::unique_ptr generateChunk(unsigned int dim, glm::ivec3 pos); + + std::unique_ptr generateMapBlock(unsigned int dim, glm::ivec3 pos); + + std::unique_ptr generateArea(unsigned int dim, glm::ivec3 origin, unsigned int size = 1); + + private: unsigned int getBiomeAt(float temperature, float humidity, float roughness); + void generateVoronoi(const std::unordered_set& biomes); - - static std::unique_ptr populateChunkDensity(Job& job, glm::ivec3 localPos); - static std::unique_ptr populateChunkDepth(Job& job, std::unique_ptr& chunkDensity, std::unique_ptr chunkDensityAbove); - - void generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap); - void generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap); - - static void setBlock(Job& job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr hint); + + static std::unique_ptr populateChunkDensity(Job& job, glm::ivec3 localPos); + + static std::unique_ptr populateChunkDepth(Job& job, std::unique_ptr& chunkDensity, + std::unique_ptr chunkDensityAbove); + + void generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap); + + void + generateChunkStructures(Job& job, glm::ivec3 localPos, std::vector biomeMap, ChunkData& depthMap); + + static void setBlock(Job& job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr hint); // // Generate sunlight on the mapgen threads to speed up perf // void generateSunlight(ChunkMap& chunks, glm::ivec3 mbPos); // static bool containsWorldPos(Chunk *chunk, glm::ivec3 pos); // void propogateSunlightNodes(ChunkMap& chunks, std::queue& queue); - - MapGenProps props; + + MapGenProps props; unsigned int seed = 0; constexpr const static unsigned short voronoiSize = 64; - Voronoi3D voronoi {voronoiSize}; - + Voronoi3D voronoi{ voronoiSize }; + Subgame& game; World& world; }; \ No newline at end of file diff --git a/src/world/gen/MapGenProps.cpp b/src/world/gen/MapGenProps.cpp index baaad9e6..ac242781 100644 --- a/src/world/gen/MapGenProps.cpp +++ b/src/world/gen/MapGenProps.cpp @@ -5,36 +5,36 @@ #include "MapGenProps.h" MapGenProps::MapGenProps(unsigned int seed) : seed(seed) { - temperatureBase.SetSeed(seed); - temperatureBase.SetFrequency(0.02); - temperatureBase.SetOctaveCount(4); - temperatureTurbulence.SetSeed(seed); - temperatureTurbulence.SetSourceModule(0, temperatureBase); - temperatureTurbulence.SetRoughness(4); - temperatureTurbulence.SetFrequency(0.2); - temperature.SetSourceModule(0, temperatureTurbulence); - temperature.SetScale(0.35); - temperature.SetBias(0.25); - - humidityBase.SetSeed(seed + 1); - humidityBase.SetFrequency(0.02); - humidityBase.SetOctaveCount(4); - humidityTurbulence.SetSeed(seed + 1); - humidityTurbulence.SetSourceModule(0, humidityBase); - humidityTurbulence.SetRoughness(4); - humidityTurbulence.SetFrequency(0.2); - humidity.SetSourceModule(0, humidityTurbulence); - humidity.SetScale(0.5); - humidity.SetBias(0.5); - - roughnessBase.SetSeed(seed - 1); - roughnessBase.SetFrequency(0.02); - roughnessBase.SetOctaveCount(4); - roughnessTurbulence.SetSeed(seed - 1); - roughnessTurbulence.SetSourceModule(0, roughnessBase); - roughnessTurbulence.SetRoughness(4); - roughnessTurbulence.SetFrequency(0.2); - roughness.SetSourceModule(0, roughnessTurbulence); - roughness.SetScale(0.5); - roughness.SetBias(0.5); + temperatureBase.SetSeed(seed); + temperatureBase.SetFrequency(0.02); + temperatureBase.SetOctaveCount(4); + temperatureTurbulence.SetSeed(seed); + temperatureTurbulence.SetSourceModule(0, temperatureBase); + temperatureTurbulence.SetRoughness(4); + temperatureTurbulence.SetFrequency(0.2); + temperature.SetSourceModule(0, temperatureTurbulence); + temperature.SetScale(0.35); + temperature.SetBias(0.25); + + humidityBase.SetSeed(seed + 1); + humidityBase.SetFrequency(0.02); + humidityBase.SetOctaveCount(4); + humidityTurbulence.SetSeed(seed + 1); + humidityTurbulence.SetSourceModule(0, humidityBase); + humidityTurbulence.SetRoughness(4); + humidityTurbulence.SetFrequency(0.2); + humidity.SetSourceModule(0, humidityTurbulence); + humidity.SetScale(0.5); + humidity.SetBias(0.5); + + roughnessBase.SetSeed(seed - 1); + roughnessBase.SetFrequency(0.02); + roughnessBase.SetOctaveCount(4); + roughnessTurbulence.SetSeed(seed - 1); + roughnessTurbulence.SetSourceModule(0, roughnessBase); + roughnessTurbulence.SetRoughness(4); + roughnessTurbulence.SetFrequency(0.2); + roughness.SetSourceModule(0, roughnessTurbulence); + roughness.SetScale(0.5); + roughness.SetBias(0.5); } diff --git a/src/world/gen/MapGenProps.h b/src/world/gen/MapGenProps.h index 6e286857..c48291df 100644 --- a/src/world/gen/MapGenProps.h +++ b/src/world/gen/MapGenProps.h @@ -7,20 +7,20 @@ #include class MapGenProps { -public: - MapGenProps(unsigned int seed); - - unsigned int seed; - - noise::module::Perlin temperatureBase; - noise::module::Turbulence temperatureTurbulence; - noise::module::ScaleBias temperature; - - noise::module::Perlin humidityBase; - noise::module::Turbulence humidityTurbulence; - noise::module::ScaleBias humidity; - - noise::module::Perlin roughnessBase; - noise::module::Turbulence roughnessTurbulence; - noise::module::ScaleBias roughness; + public: + MapGenProps(unsigned int seed); + + unsigned int seed; + + noise::module::Perlin temperatureBase; + noise::module::Turbulence temperatureTurbulence; + noise::module::ScaleBias temperature; + + noise::module::Perlin humidityBase; + noise::module::Turbulence humidityTurbulence; + noise::module::ScaleBias humidity; + + noise::module::Perlin roughnessBase; + noise::module::Turbulence roughnessTurbulence; + noise::module::ScaleBias roughness; }; diff --git a/src/world/gen/NoiseSample.cpp b/src/world/gen/NoiseSample.cpp index 70027407..30e2a769 100644 --- a/src/world/gen/NoiseSample.cpp +++ b/src/world/gen/NoiseSample.cpp @@ -4,21 +4,22 @@ #include "NoiseSample.h" -NoiseSample::NoiseSample(unsigned int precision, float scaleBy) : NoiseSample({precision, precision}, {scaleBy, scaleBy}) {} +NoiseSample::NoiseSample(unsigned int precision, float scaleBy) : NoiseSample({ precision, precision }, + { scaleBy, scaleBy }) {} NoiseSample::NoiseSample(glm::ivec2 precision, glm::vec2 scaleBy) : - precision(precision.x, precision.y, precision.x), - scaleBy(scaleBy.x, scaleBy.y, scaleBy.x) { - data.resize((this->precision.x + 1) * (this->precision.y + 1) * (this->precision.z + 1)); + precision(precision.x, precision.y, precision.x), + scaleBy(scaleBy.x, scaleBy.y, scaleBy.x) { + data.resize((this->precision.x + 1) * (this->precision.y + 1) * (this->precision.z + 1)); } -void NoiseSample::populate(const NoiseSample::fill_function &fn) { - glm::vec3 pos; - for (pos.x = 0; pos.x <= precision.x; pos.x++) - for (pos.y = 0; pos.y <= precision.y; pos.y++) - for (pos.z = 0; pos.z <= precision.z; pos.z++) { - glm::vec3 queryPos = pos / glm::vec3(precision) * scaleBy; - if (queryPos.y == NAN) queryPos.y = 0; - data[index(pos.x, pos.y, pos.z)] = fn(queryPos); - } +void NoiseSample::populate(const NoiseSample::fill_function& fn) { + glm::vec3 pos; + for (pos.x = 0; pos.x <= precision.x; pos.x++) + for (pos.y = 0; pos.y <= precision.y; pos.y++) + for (pos.z = 0; pos.z <= precision.z; pos.z++) { + glm::vec3 queryPos = pos / glm::vec3(precision) * scaleBy; + if (queryPos.y == NAN) queryPos.y = 0; + data[index(pos.x, pos.y, pos.z)] = fn(queryPos); + } } diff --git a/src/world/gen/NoiseSample.h b/src/world/gen/NoiseSample.h index 26467e84..e3bd6d13 100644 --- a/src/world/gen/NoiseSample.h +++ b/src/world/gen/NoiseSample.h @@ -11,49 +11,52 @@ #include "util/Interp.h" class NoiseSample { -public: - typedef std::function fill_function; - - NoiseSample(unsigned int precision, float scaleBy = 1); - NoiseSample(glm::ivec2 precision, glm::vec2 scaleBy = {1, 1}); - - void populate(const fill_function& fn); - - inline float get(glm::vec3 pos) { - glm::vec3 scaled = pos * glm::vec3(precision) / scaleBy; - - glm::ivec3 a = { scaled.x, scaled.y, scaled.z }; - glm::vec3 factor = { scaled.x - a.x, scaled.y - a.y, scaled.z - a.z }; - glm::ivec3 b = { NoiseSample::min(int(std::ceil(scaled.x)), precision.x), - NoiseSample::min(int(std::ceil(scaled.y)), precision.y), - NoiseSample::min(int(std::ceil(scaled.z)), precision.z)}; + public: + typedef std::function fill_function; + + NoiseSample(unsigned int precision, float scaleBy = 1); + + NoiseSample(glm::ivec2 precision, glm::vec2 scaleBy = { 1, 1 }); + + void populate(const fill_function& fn); + + inline float get(glm::vec3 pos) { + glm::vec3 scaled = pos * glm::vec3(precision) / scaleBy; + + glm::ivec3 a = { scaled.x, scaled.y, scaled.z }; + glm::vec3 factor = { scaled.x - a.x, scaled.y - a.y, scaled.z - a.z }; + glm::ivec3 b = { NoiseSample::min(int(std::ceil(scaled.x)), precision.x), + NoiseSample::min(int(std::ceil(scaled.y)), precision.y), + NoiseSample::min(int(std::ceil(scaled.z)), precision.z) }; // assert(a.x + factor.x <= precision.x && a.y + factor.y <= precision.y && a.z + factor.z <= precision.z); - - // No vertical interpolation - if (precision.y == 0) return Interp::bilerp( - data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)], - data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)], - factor.x, factor.z); - - return Interp::trilerp( - data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)], - data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)], - data[index(a.x, b.y, a.z)], data[index(b.x, b.y, a.z)], - data[index(a.x, b.y, b.z)], data[index(b.x, b.y, b.z)], - factor.x, factor.z, factor.y); - } -private: - inline unsigned int index(int x, int y, int z) { - return x * (precision.x + 1) * (precision.y + 1) + y * (precision.x + 1) + z; - }; - - static inline int min(int a, int b) { - return (a < b ? a : b); - } - - std::vector data {}; - glm::ivec3 precision {}; - glm::vec3 scaleBy; + + // No vertical interpolation + if (precision.y == 0) + return Interp::bilerp( + data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)], + data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)], + factor.x, factor.z); + + return Interp::trilerp( + data[index(a.x, a.y, a.z)], data[index(b.x, a.y, a.z)], + data[index(a.x, a.y, b.z)], data[index(b.x, a.y, b.z)], + data[index(a.x, b.y, a.z)], data[index(b.x, b.y, a.z)], + data[index(a.x, b.y, b.z)], data[index(b.x, b.y, b.z)], + factor.x, factor.z, factor.y); + } + + private: + inline unsigned int index(int x, int y, int z) { + return x * (precision.x + 1) * (precision.y + 1) + y * (precision.x + 1) + z; + }; + + static inline int min(int a, int b) { + return (a < b ? a : b); + } + + std::vector data{}; + glm::ivec3 precision{}; + glm::vec3 scaleBy; }; diff --git a/src/world/inv/Inventory.cpp b/src/world/inv/Inventory.cpp index 3da1abd3..76ebf73e 100644 --- a/src/world/inv/Inventory.cpp +++ b/src/world/inv/Inventory.cpp @@ -8,15 +8,15 @@ Inventory::Inventory(SubgamePtr game, const std::string& name) : game(game), name(name) {} -bool Inventory::hasList(const std::string &name) { - return lists.count(name); +bool Inventory::hasList(const std::string& name) { + return lists.count(name); } -void Inventory::removeList(const std::string &name) { - lists.erase(name); +void Inventory::removeList(const std::string& name) { + lists.erase(name); } -InventoryListPtr Inventory::getList(const std::string &name) { - if (lists.count(name)) return InventoryListPtr(lists[name]); - throw std::runtime_error("List " + name + " doesn't exist in inventory " + this->name + "."); +InventoryListPtr Inventory::getList(const std::string& name) { + if (lists.count(name)) return InventoryListPtr(lists[name]); + throw std::runtime_error("List " + name + " doesn't exist in inventory " + this->name + "."); } \ No newline at end of file diff --git a/src/world/inv/Inventory.h b/src/world/inv/Inventory.h index 917e7972..8b5319b8 100644 --- a/src/world/inv/Inventory.h +++ b/src/world/inv/Inventory.h @@ -10,23 +10,27 @@ #include "util/CovariantPtr.h" class Subgame; + class InventoryList; class Inventory { -public: - Inventory(const Inventory& o) = delete; - explicit Inventory(SubgamePtr game, const std::string& name); - - virtual bool hasList(const std::string& name); - virtual InventoryListPtr getList(const std::string& name); - - virtual void createList(const std::string& name, unsigned short length, unsigned short width) = 0; - virtual void removeList(const std::string& name); - - -protected: - SubgamePtr game; - - std::string name; - std::map> lists; + public: + Inventory(const Inventory& o) = delete; + + explicit Inventory(SubgamePtr game, const std::string& name); + + virtual bool hasList(const std::string& name); + + virtual InventoryListPtr getList(const std::string& name); + + virtual void createList(const std::string& name, unsigned short length, unsigned short width) = 0; + + virtual void removeList(const std::string& name); + + + protected: + SubgamePtr game; + + std::string name; + std::map> lists; }; diff --git a/src/world/inv/InventoryRefs.cpp b/src/world/inv/InventoryRefs.cpp index 5214c3f3..d075a423 100644 --- a/src/world/inv/InventoryRefs.cpp +++ b/src/world/inv/InventoryRefs.cpp @@ -8,11 +8,11 @@ InventoryRefs::InventoryRefs(SubgamePtr game) : game(game) {} -bool InventoryRefs::hasInventory(const std::string &inv) { - return inventories.count(inv); +bool InventoryRefs::hasInventory(const std::string& inv) { + return inventories.count(inv); } -InventoryPtr InventoryRefs::getInventory(const std::string &inv) { - if (!inventories.count(inv)) throw std::runtime_error("Inventory " + inv + " doesn't exist~!"); - return inventories.at(inv); +InventoryPtr InventoryRefs::getInventory(const std::string& inv) { + if (!inventories.count(inv)) throw std::runtime_error("Inventory " + inv + " doesn't exist~!"); + return inventories.at(inv); } diff --git a/src/world/inv/InventoryRefs.h b/src/world/inv/InventoryRefs.h index 82345c4e..052d246d 100644 --- a/src/world/inv/InventoryRefs.h +++ b/src/world/inv/InventoryRefs.h @@ -11,19 +11,23 @@ #include "util/CovariantPtr.h" class Subgame; + class Inventory; class InventoryRefs { -public: - InventoryRefs(const InventoryRefs& o) = delete; - explicit InventoryRefs(SubgamePtr game); - - virtual bool hasInventory(const std::string& inv); - virtual InventoryPtr createInventory(const std::string& inv) = 0; - virtual InventoryPtr getInventory(const std::string& inv); - -protected: - SubgamePtr game; - - std::unordered_map> inventories {}; + public: + InventoryRefs(const InventoryRefs& o) = delete; + + explicit InventoryRefs(SubgamePtr game); + + virtual bool hasInventory(const std::string& inv); + + virtual InventoryPtr createInventory(const std::string& inv) = 0; + + virtual InventoryPtr getInventory(const std::string& inv); + + protected: + SubgamePtr game; + + std::unordered_map> inventories{}; }; diff --git a/src/world/inv/ItemStack.cpp b/src/world/inv/ItemStack.cpp index 43c4bebb..34768aea 100644 --- a/src/world/inv/ItemStack.cpp +++ b/src/world/inv/ItemStack.cpp @@ -10,17 +10,17 @@ #include "lua/usertype/ItemStack.h" ItemStack::ItemStack(Api::Usertype::ItemStack& stack, SubgamePtr game) : - id((stack.get_count() == 0) ? DefinitionAtlas::AIR : game->getDefs().fromStr(stack.get_name()).index), - count((this->id == DefinitionAtlas::AIR) ? 0 : stack.get_count()) {} + id((stack.get_count() == 0) ? DefinitionAtlas::AIR : game->getDefs().fromStr(stack.get_name()).index), + count((this->id == DefinitionAtlas::AIR) ? 0 : stack.get_count()) {} ItemStack::ItemStack(unsigned int id, unsigned short count) : - id((count == 0) ? DefinitionAtlas::AIR : id), - count((this->id == DefinitionAtlas::AIR) ? 0 : count) {} + id((count == 0) ? DefinitionAtlas::AIR : id), + count((this->id == DefinitionAtlas::AIR) ? 0 : count) {} -bool ItemStack::operator!=(const ItemStack &b) const { - return (b.count != this->count || b.id != this->id); +bool ItemStack::operator!=(const ItemStack& b) const { + return (b.count != this->count || b.id != this->id); } -bool ItemStack::operator==(const ItemStack &b) const { - return (b.count == this->count && b.id == this->id); +bool ItemStack::operator==(const ItemStack& b) const { + return (b.count == this->count && b.id == this->id); } diff --git a/src/world/inv/ItemStack.h b/src/world/inv/ItemStack.h index 23b6127b..878bb582 100644 --- a/src/world/inv/ItemStack.h +++ b/src/world/inv/ItemStack.h @@ -10,14 +10,17 @@ #include "lua/usertype/ItemStack.h" class ItemStack { -public: - ItemStack() = default; - ItemStack(unsigned int id, unsigned short count); - ItemStack(Api::Usertype::ItemStack& stack, SubgamePtr game); - - bool operator!=(const ItemStack& b) const; - bool operator==(const ItemStack& b) const; - - unsigned int id = 0; // Invalid - unsigned short count = 0; + public: + ItemStack() = default; + + ItemStack(unsigned int id, unsigned short count); + + ItemStack(Api::Usertype::ItemStack& stack, SubgamePtr game); + + bool operator!=(const ItemStack& b) const; + + bool operator==(const ItemStack& b) const; + + unsigned int id = 0; // Invalid + unsigned short count = 0; }; \ No newline at end of file diff --git a/src/world/inv/LocalInventory.cpp b/src/world/inv/LocalInventory.cpp index 98f584c4..d48e5e7c 100644 --- a/src/world/inv/LocalInventory.cpp +++ b/src/world/inv/LocalInventory.cpp @@ -7,38 +7,38 @@ #include "LocalInventoryList.cpp" #include "client/conn/ClientNetworkInterpreter.h" -InventoryListPtr LocalInventory::getList(const std::string &name) { - if (!hasList(name)) createList(name, 0, 0); - return Inventory::getList(name); +InventoryListPtr LocalInventory::getList(const std::string& name) { + if (!hasList(name)) createList(name, 0, 0); + return Inventory::getList(name); } -void LocalInventory::createList(const std::string &name, unsigned short length, unsigned short width) { - lists.emplace(name, std::make_shared(game, name, this->name, length, width, net)); - net.invWatch(this->name, name); +void LocalInventory::createList(const std::string& name, unsigned short length, unsigned short width) { + lists.emplace(name, std::make_shared(game, name, this->name, length, width, net)); + net.invWatch(this->name, name); } -void LocalInventory::setPersistant(const std::string &list, bool persistant) { - if (!lists.count(name)) return; - std::static_pointer_cast(lists[list])->persistant = persistant; +void LocalInventory::setPersistant(const std::string& list, bool persistant) { + if (!lists.count(name)) return; + std::static_pointer_cast(lists[list])->persistant = persistant; } bool LocalInventory::pruneLists(double time) { - for (auto lIt = lists.begin(); lIt != lists.end();) { - auto list = std::static_pointer_cast(lIt->second); - if (!list->persistant) { - // Start the timeout for Inventories that aren't being used. - if (list->decayTime == 0 && list.use_count() == 2) list->decayTime = time + 15; - // Remove the timeout for Inventories that are being used. - else if (list->decayTime != 0 && list.use_count() > 2) list->decayTime = 0; - // Delete InventoryLists that have passed their timeout. - else if (list->decayTime != 0 && list->decayTime <= time) { - net.invUnwatch(name, lIt->first); - lIt = lists.erase(lIt); - } - else lIt++; - } - else lIt++; - } - - return lists.size() == 0; + for (auto lIt = lists.begin(); lIt != lists.end();) { + auto list = std::static_pointer_cast(lIt->second); + if (!list->persistant) { + // Start the timeout for Inventories that aren't being used. + if (list->decayTime == 0 && list.use_count() == 2) list->decayTime = time + 15; + // Remove the timeout for Inventories that are being used. + else if (list->decayTime != 0 && list.use_count() > 2) list->decayTime = 0; + // Delete InventoryLists that have passed their timeout. + else if (list->decayTime != 0 && list->decayTime <= time) { + net.invUnwatch(name, lIt->first); + lIt = lists.erase(lIt); + } + else lIt++; + } + else lIt++; + } + + return lists.size() == 0; } diff --git a/src/world/inv/LocalInventory.h b/src/world/inv/LocalInventory.h index e12298c6..999868cb 100644 --- a/src/world/inv/LocalInventory.h +++ b/src/world/inv/LocalInventory.h @@ -15,20 +15,22 @@ #include "game/LocalSubgame.h" class DefinitionAtlas; + class ClientNetworkInterpreter; class LocalInventory : public Inventory { -public: - LocalInventory(SubgamePtr game, const std::string& name, ClientNetworkInterpreter& net) : - Inventory(game, name), net(net) {} - - virtual InventoryListPtr getList(const std::string& name) override; - - virtual void createList(const std::string& name, unsigned short length, unsigned short width) override; - - void setPersistant(const std::string& list, bool persistant); - bool pruneLists(double time); - -private: - ClientNetworkInterpreter& net; + public: + LocalInventory(SubgamePtr game, const std::string& name, ClientNetworkInterpreter& net) : + Inventory(game, name), net(net) {} + + virtual InventoryListPtr getList(const std::string& name) override; + + virtual void createList(const std::string& name, unsigned short length, unsigned short width) override; + + void setPersistant(const std::string& list, bool persistant); + + bool pruneLists(double time); + + private: + ClientNetworkInterpreter& net; }; diff --git a/src/world/inv/LocalInventoryList.cpp b/src/world/inv/LocalInventoryList.cpp index 1f982300..fb449a53 100644 --- a/src/world/inv/LocalInventoryList.cpp +++ b/src/world/inv/LocalInventoryList.cpp @@ -7,38 +7,38 @@ #include "client/conn/ClientNetworkInterpreter.h" LocalInventoryList::LocalInventoryList(SubgamePtr game, const std::string& name, - const std::string& invName, unsigned short size, unsigned short width, - ClientNetworkInterpreter& net) : - InventoryList(game, name, invName, size, width), - net(net) {} + const std::string& invName, unsigned short size, unsigned short width, + ClientNetworkInterpreter& net) : + InventoryList(game, name, invName, size, width), + net(net) {} void LocalInventoryList::interact(InventoryListPtr hand, bool primary, unsigned short ind) { - InventoryList::interact(hand, primary, ind); - net.invInteract(invName, name, primary, ind); + InventoryList::interact(hand, primary, ind); + net.invInteract(invName, name, primary, ind); } void LocalInventoryList::setData(unsigned int newWidth, const std::vector& newItems) { width = newWidth; - items = newItems; - manipulated(); + items = newItems; + manipulated(); } void LocalInventoryList::addGuiCallback(std::shared_ptr> cb) { - guiCallbacks.push_back(cb); + guiCallbacks.push_back(cb); } void LocalInventoryList::removeGuiCallback(std::shared_ptr> cb) { - for (auto it = guiCallbacks.begin(); it != guiCallbacks.end();) { - if (cb == (*it)) { - guiCallbacks.erase(it); - return; - } - it++; - } - - throw std::runtime_error("Failed to remove callback."); + for (auto it = guiCallbacks.begin(); it != guiCallbacks.end();) { + if (cb == (*it)) { + guiCallbacks.erase(it); + return; + } + it++; + } + + throw std::runtime_error("Failed to remove callback."); } void LocalInventoryList::manipulated() { - for (auto& cb : guiCallbacks) (*cb)(); + for (auto& cb : guiCallbacks) (*cb)(); } \ No newline at end of file diff --git a/src/world/inv/LocalInventoryList.h b/src/world/inv/LocalInventoryList.h index e2c5bf29..5a304ef8 100644 --- a/src/world/inv/LocalInventoryList.h +++ b/src/world/inv/LocalInventoryList.h @@ -11,23 +11,25 @@ class ClientNetworkInterpreter; class LocalInventoryList : public InventoryList { -public: - LocalInventoryList(SubgamePtr game, const std::string& name, - const std::string& invName, unsigned short size, unsigned short width, - ClientNetworkInterpreter& net); - - void interact(InventoryListPtr hand, bool primary, unsigned short ind) override; - - void setData(unsigned int newWidth, const std::vector& newItems); - void addGuiCallback(std::shared_ptr> cb); - void removeGuiCallback(std::shared_ptr> cb); - - bool persistant = false; - double decayTime = 0; -private: - void manipulated() override; - - ClientNetworkInterpreter& net; - - std::list>> guiCallbacks {}; + public: + LocalInventoryList(SubgamePtr game, const std::string& name, + const std::string& invName, unsigned short size, unsigned short width, + ClientNetworkInterpreter& net); + + void interact(InventoryListPtr hand, bool primary, unsigned short ind) override; + + void setData(unsigned int newWidth, const std::vector& newItems); + + void addGuiCallback(std::shared_ptr> cb); + + void removeGuiCallback(std::shared_ptr> cb); + + bool persistant = false; + double decayTime = 0; + private: + void manipulated() override; + + ClientNetworkInterpreter& net; + + std::list>> guiCallbacks{}; }; diff --git a/src/world/inv/LocalInventoryRefs.cpp b/src/world/inv/LocalInventoryRefs.cpp index 9aad78f2..d170e420 100644 --- a/src/world/inv/LocalInventoryRefs.cpp +++ b/src/world/inv/LocalInventoryRefs.cpp @@ -12,87 +12,87 @@ #include "client/conn/ClientNetworkInterpreter.h" LocalInventoryRefs::LocalInventoryRefs(SubgamePtr game, ClientNetworkInterpreter& net) : InventoryRefs(game), net(net) { - createInventory("current_player"); - getInventory("current_player")->createList("cursor", 1, 1); + createInventory("current_player"); + getInventory("current_player")->createList("cursor", 1, 1); } void LocalInventoryRefs::init() { - watch("current_player", "cursor"); + watch("current_player", "cursor"); } void LocalInventoryRefs::update(double delta, ClientNetworkInterpreter& net) { - time += delta; - - for (auto mIt = inventories.begin(); mIt != inventories.end();) { - if (std::static_pointer_cast(mIt->second)->pruneLists(time)) mIt = inventories.erase(mIt); - else mIt++; - } + time += delta; + + for (auto mIt = inventories.begin(); mIt != inventories.end();) { + if (std::static_pointer_cast(mIt->second)->pruneLists(time)) mIt = inventories.erase(mIt); + else mIt++; + } } -InventoryPtr LocalInventoryRefs::createInventory(const std::string &inv) { - if (!inventories.count(inv)) inventories.emplace(inv, std::make_shared(game, inv, net)); - return inventories[inv]; +InventoryPtr LocalInventoryRefs::createInventory(const std::string& inv) { + if (!inventories.count(inv)) inventories.emplace(inv, std::make_shared(game, inv, net)); + return inventories[inv]; } void LocalInventoryRefs::packetReceived(std::unique_ptr p) { - std::string source = p->d.read(); - std::string list = p->d.read(); - if (strncmp(source.data(), "player:", 7) == 0) source = "current_player"; - - if (!inventories.count(source)) return; - if (!inventories[source]->hasList(list)) return; - - unsigned int size = p->d.read(); - unsigned int width = p->d.read(); - - std::vector stacks {}; - stacks.reserve(size); - - while (!p->d.atEnd()) { - unsigned short count = p->d.read(); - unsigned int id = p->d.read(); - stacks.push_back({id, count}); - } - - inventories[source]->getList(list).l()->setData(width, stacks); + std::string source = p->d.read(); + std::string list = p->d.read(); + if (strncmp(source.data(), "player:", 7) == 0) source = "current_player"; + + if (!inventories.count(source)) return; + if (!inventories[source]->hasList(list)) return; + + unsigned int size = p->d.read(); + unsigned int width = p->d.read(); + + std::vector stacks{}; + stacks.reserve(size); + + while (!p->d.atEnd()) { + unsigned short count = p->d.read(); + unsigned int id = p->d.read(); + stacks.push_back({ id, count }); + } + + inventories[source]->getList(list).l()->setData(width, stacks); } -void LocalInventoryRefs::watch(const std::string &inv, const std::string &list, bool persistant) { - if (!inventories.count(inv)) inventories.insert({inv, {}}); - if (!inventories[inv]->hasList(list)) { - inventories[inv]->createList(list, 0, 0); - net.invWatch(inv, list); - } - std::static_pointer_cast(inventories[inv])->setPersistant(list, persistant); +void LocalInventoryRefs::watch(const std::string& inv, const std::string& list, bool persistant) { + if (!inventories.count(inv)) inventories.insert({ inv, {}}); + if (!inventories[inv]->hasList(list)) { + inventories[inv]->createList(list, 0, 0); + net.invWatch(inv, list); + } + std::static_pointer_cast(inventories[inv])->setPersistant(list, persistant); } -void LocalInventoryRefs::unWatch(const std::string &inv, const std::string &list) { - if (inventories.count(inv) && inventories[inv]->hasList(list)) inventories[inv]->removeList(list); - net.invUnwatch(inv, list); +void LocalInventoryRefs::unWatch(const std::string& inv, const std::string& list) { + if (inventories.count(inv) && inventories[inv]->hasList(list)) inventories[inv]->removeList(list); + net.invUnwatch(inv, list); } std::shared_ptr LocalInventoryRefs::getHandList() { - return handList; + return handList; } -void LocalInventoryRefs::setHandList(const std::string &list) { - if (handList && list == handList->getName()) return; - if (handList) unWatch("current_player", handList->getName()); - handList = getInventory("current_player")->getList(list).l(); - getInventory("current_player").l()->setPersistant(list, true); +void LocalInventoryRefs::setHandList(const std::string& list) { + if (handList && list == handList->getName()) return; + if (handList) unWatch("current_player", handList->getName()); + handList = getInventory("current_player")->getList(list).l(); + getInventory("current_player").l()->setPersistant(list, true); } std::shared_ptr LocalInventoryRefs::getWieldList() { - return wieldList; + return wieldList; } -void LocalInventoryRefs::setWieldList(const std::string &list) { - if (wieldList && list == wieldList->getName()) return; - if (wieldList) unWatch("current_player", wieldList->getName()); - wieldList = getInventory("current_player")->getList(list).l(); - getInventory("current_player").l()->setPersistant(list, true); +void LocalInventoryRefs::setWieldList(const std::string& list) { + if (wieldList && list == wieldList->getName()) return; + if (wieldList) unWatch("current_player", wieldList->getName()); + wieldList = getInventory("current_player")->getList(list).l(); + getInventory("current_player").l()->setPersistant(list, true); } std::shared_ptr LocalInventoryRefs::getCursorList() { - return inventories["current_player"]->getList("cursor").l(); + return inventories["current_player"]->getList("cursor").l(); } \ No newline at end of file diff --git a/src/world/inv/LocalInventoryRefs.h b/src/world/inv/LocalInventoryRefs.h index 853dae69..03612c16 100644 --- a/src/world/inv/LocalInventoryRefs.h +++ b/src/world/inv/LocalInventoryRefs.h @@ -13,33 +13,43 @@ #include "LocalInventory.h" class Packet; + class PacketView; + class LocalInventoryList; + class ClientNetworkInterpreter; class LocalInventoryRefs : public InventoryRefs { -public: - LocalInventoryRefs(SubgamePtr game, ClientNetworkInterpreter& net); - void packetReceived(std::unique_ptr p); - void init(); - - void update(double delta, ClientNetworkInterpreter& net); - - virtual InventoryPtr createInventory(const std::string &inv) override; - - void watch(const std::string& inv, const std::string& list, bool persistant = false); - void unWatch(const std::string& inv, const std::string& list); - - std::shared_ptr getHandList(); - void setHandList(const std::string& list); - std::shared_ptr getWieldList(); - void setWieldList(const std::string& list); - std::shared_ptr getCursorList(); - -private: - std::shared_ptr handList = nullptr; - std::shared_ptr wieldList = nullptr; - - ClientNetworkInterpreter& net; - double time = 0; + public: + LocalInventoryRefs(SubgamePtr game, ClientNetworkInterpreter& net); + + void packetReceived(std::unique_ptr p); + + void init(); + + void update(double delta, ClientNetworkInterpreter& net); + + virtual InventoryPtr createInventory(const std::string& inv) override; + + void watch(const std::string& inv, const std::string& list, bool persistant = false); + + void unWatch(const std::string& inv, const std::string& list); + + std::shared_ptr getHandList(); + + void setHandList(const std::string& list); + + std::shared_ptr getWieldList(); + + void setWieldList(const std::string& list); + + std::shared_ptr getCursorList(); + + private: + std::shared_ptr handList = nullptr; + std::shared_ptr wieldList = nullptr; + + ClientNetworkInterpreter& net; + double time = 0; }; diff --git a/src/world/inv/ServerInventory.cpp b/src/world/inv/ServerInventory.cpp index f3e8b4fa..ec2db7cf 100644 --- a/src/world/inv/ServerInventory.cpp +++ b/src/world/inv/ServerInventory.cpp @@ -6,13 +6,13 @@ #include "ServerInventoryList.h" -void ServerInventory::createList(const std::string &name, unsigned short length, unsigned short width) { - lists.emplace(name, std::make_shared(game, clients, name, this->name, length, width)); +void ServerInventory::createList(const std::string& name, unsigned short length, unsigned short width) { + lists.emplace(name, std::make_shared(game, clients, name, this->name, length, width)); } void ServerInventory::sendDirtyLists() { - for (auto& l : lists) { - auto list = std::static_pointer_cast(l.second); - if (list->dirty) list->sendToAll(); - } + for (auto& l : lists) { + auto list = std::static_pointer_cast(l.second); + if (list->dirty) list->sendToAll(); + } } \ No newline at end of file diff --git a/src/world/inv/ServerInventory.h b/src/world/inv/ServerInventory.h index 1136a4be..f8583764 100644 --- a/src/world/inv/ServerInventory.h +++ b/src/world/inv/ServerInventory.h @@ -16,13 +16,14 @@ class ServerClients; class ServerInventory : public Inventory { -public: - ServerInventory(SubgamePtr game, const std::string& name, ServerClients& clients) : - Inventory(game, name), clients(clients) {}; - - virtual void createList(const std::string& name, unsigned short length, unsigned short width) override; - - void sendDirtyLists(); -private: - ServerClients& clients; + public: + ServerInventory(SubgamePtr game, const std::string& name, ServerClients& clients) : + Inventory(game, name), clients(clients) {}; + + virtual void createList(const std::string& name, unsigned short length, unsigned short width) override; + + void sendDirtyLists(); + + private: + ServerClients& clients; }; diff --git a/src/world/inv/ServerInventoryList.cpp b/src/world/inv/ServerInventoryList.cpp index 9bbd0468..e8f4036d 100644 --- a/src/world/inv/ServerInventoryList.cpp +++ b/src/world/inv/ServerInventoryList.cpp @@ -10,44 +10,44 @@ #include "world/player/ServerPlayer.h" ServerInventoryList::ServerInventoryList(SubgamePtr game, ServerClients& list, - const std::string& name, const std::string& invName, unsigned short size, unsigned short width) : - InventoryList(game, name, invName, size, width), - clients(list) {} + const std::string& name, const std::string& invName, unsigned short size, unsigned short width) : + InventoryList(game, name, invName, size, width), + clients(list) {} void ServerInventoryList::manipulated() { - dirty = true; + dirty = true; } bool ServerInventoryList::addWatcher(unsigned int id) { - auto& client = clients.getPlayer(id); - if (!client || watchers.count(id)) return false; - watchers.insert(id); - sendTo(client); - return true; + auto& client = clients.getPlayer(id); + if (!client || watchers.count(id)) return false; + watchers.insert(id); + sendTo(client); + return true; } bool ServerInventoryList::removeWatcher(unsigned int id) { - if (!watchers.count(id)) return false; - watchers.erase(id); - return true; + if (!watchers.count(id)) return false; + watchers.erase(id); + return true; } void ServerInventoryList::sendTo(std::shared_ptr player) { - if (!player) return; - createPacket().sendTo(player->getPeer(), Packet::Channel::INTERACT); + if (!player) return; + createPacket().sendTo(player->getPeer(), Packet::Channel::INTERACT); } void ServerInventoryList::sendToAll() { - auto p = createPacket(); - - for (auto it = watchers.cbegin(); it != watchers.cend();) { - auto& player = clients.getPlayer(*it); - if (!player) it = watchers.erase(it); - else { - p.sendTo(player->getPeer(), Packet::Channel::INTERACT); - it++; - } - } - - dirty = false; + auto p = createPacket(); + + for (auto it = watchers.cbegin(); it != watchers.cend();) { + auto& player = clients.getPlayer(*it); + if (!player) it = watchers.erase(it); + else { + p.sendTo(player->getPeer(), Packet::Channel::INTERACT); + it++; + } + } + + dirty = false; } diff --git a/src/world/inv/ServerInventoryList.h b/src/world/inv/ServerInventoryList.h index dcee5977..af363027 100644 --- a/src/world/inv/ServerInventoryList.h +++ b/src/world/inv/ServerInventoryList.h @@ -9,25 +9,29 @@ #include "InventoryList.h" class ServerClients; + class ServerPlayer; + class Packet; class ServerInventoryList : public InventoryList { -public: - ServerInventoryList(SubgamePtr defs, ServerClients& list, const std::string& name, - const std::string& invName, unsigned short size, unsigned short width); - - bool addWatcher(unsigned int id); - bool removeWatcher(unsigned int id); - - void sendToAll(); - void sendTo(std::shared_ptr player); - - bool dirty = false; - -private: - void manipulated() override; - - ServerClients& clients; - std::set watchers {}; + public: + ServerInventoryList(SubgamePtr defs, ServerClients& list, const std::string& name, + const std::string& invName, unsigned short size, unsigned short width); + + bool addWatcher(unsigned int id); + + bool removeWatcher(unsigned int id); + + void sendToAll(); + + void sendTo(std::shared_ptr player); + + bool dirty = false; + + private: + void manipulated() override; + + ServerClients& clients; + std::set watchers{}; }; diff --git a/src/world/inv/ServerInventoryRefs.cpp b/src/world/inv/ServerInventoryRefs.cpp index 0cc10c1c..7f310838 100644 --- a/src/world/inv/ServerInventoryRefs.cpp +++ b/src/world/inv/ServerInventoryRefs.cpp @@ -8,49 +8,50 @@ #include "ServerInventoryList.h" ServerInventoryRefs::ServerInventoryRefs(SubgamePtr game, ServerClients& clients) : - InventoryRefs(game), clients(clients) {} + InventoryRefs(game), clients(clients) {} void ServerInventoryRefs::update() { - for (auto& inv : inventories) - std::static_pointer_cast(inv.second)->sendDirtyLists(); + for (auto& inv : inventories) + std::static_pointer_cast(inv.second)->sendDirtyLists(); } -InventoryPtr ServerInventoryRefs::createInventory(const std::string &inv) { - if (!inventories.count(inv)) inventories.emplace(inv, std::make_shared(game, inv, clients)); - return inventories[inv]; +InventoryPtr ServerInventoryRefs::createInventory(const std::string& inv) { + if (!inventories.count(inv)) inventories.emplace(inv, std::make_shared(game, inv, clients)); + return inventories[inv]; } -bool ServerInventoryRefs::addWatcher(const std::string &inv, const std::string &list, unsigned int id) { - std::string invReal = inv == "current_player" ? "player:" + std::to_string(id) : inv; - - if (!hasInventory(invReal)) return false; - auto inventory = getInventory(invReal); - if (!inventory->hasList(list)) return false; - inventory->getList(list).s()->addWatcher(id); - - return true; +bool ServerInventoryRefs::addWatcher(const std::string& inv, const std::string& list, unsigned int id) { + std::string invReal = inv == "current_player" ? "player:" + std::to_string(id) : inv; + + if (!hasInventory(invReal)) return false; + auto inventory = getInventory(invReal); + if (!inventory->hasList(list)) return false; + inventory->getList(list).s()->addWatcher(id); + + return true; } -bool ServerInventoryRefs::removeWatcher(const std::string &inv, const std::string &list, unsigned int id) { - std::string invReal = inv == "current_player" ? "player:" + std::to_string(id) : inv; - - if (!hasInventory(invReal)) return false; - auto inventory = getInventory(invReal); - if (!inventory->hasList(list)) return false; - inventory->getList(list).s()->removeWatcher(id); - - return true; +bool ServerInventoryRefs::removeWatcher(const std::string& inv, const std::string& list, unsigned int id) { + std::string invReal = inv == "current_player" ? "player:" + std::to_string(id) : inv; + + if (!hasInventory(invReal)) return false; + auto inventory = getInventory(invReal); + if (!inventory->hasList(list)) return false; + inventory->getList(list).s()->removeWatcher(id); + + return true; } -bool ServerInventoryRefs::interact(bool primary, const std::string &inv, const std::string &list, unsigned short ind, unsigned int id) { - std::string playerInv = "player:" + std::to_string(id); - if (!hasInventory(playerInv)) return false; - auto playerInventory = getInventory(playerInv); - - if (!hasInventory(inv)) return false; - auto inventory = getInventory(inv); - if (!inventory->hasList(list)) return false; - - inventory->getList(list).s()->interact(playerInventory->getList("cursor"), primary, ind); - return true; +bool ServerInventoryRefs::interact(bool primary, const std::string& inv, const std::string& list, unsigned short ind, + unsigned int id) { + std::string playerInv = "player:" + std::to_string(id); + if (!hasInventory(playerInv)) return false; + auto playerInventory = getInventory(playerInv); + + if (!hasInventory(inv)) return false; + auto inventory = getInventory(inv); + if (!inventory->hasList(list)) return false; + + inventory->getList(list).s()->interact(playerInventory->getList("cursor"), primary, ind); + return true; } \ No newline at end of file diff --git a/src/world/inv/ServerInventoryRefs.h b/src/world/inv/ServerInventoryRefs.h index 80e557f8..9bf765c8 100644 --- a/src/world/inv/ServerInventoryRefs.h +++ b/src/world/inv/ServerInventoryRefs.h @@ -9,20 +9,23 @@ #include "ServerInventory.h" class ServerClients; + class ServerInventoryList; class ServerInventoryRefs : public InventoryRefs { -public: - ServerInventoryRefs(SubgamePtr game, ServerClients& clients); - - void update(); - - virtual InventoryPtr createInventory(const std::string &inv) override; - - bool addWatcher(const std::string& inv, const std::string& list, unsigned int id); - bool removeWatcher(const std::string& inv, const std::string& list, unsigned int id); - - bool interact(bool primary, const std::string& inv, const std::string& list, unsigned short ind, unsigned int id); -private: - ServerClients& clients; + public: + ServerInventoryRefs(SubgamePtr game, ServerClients& clients); + + void update(); + + virtual InventoryPtr createInventory(const std::string& inv) override; + + bool addWatcher(const std::string& inv, const std::string& list, unsigned int id); + + bool removeWatcher(const std::string& inv, const std::string& list, unsigned int id); + + bool interact(bool primary, const std::string& inv, const std::string& list, unsigned short ind, unsigned int id); + + private: + ServerClients& clients; }; diff --git a/src/world/player/LocalPlayer.cpp b/src/world/player/LocalPlayer.cpp index b6de4a8f..49bf50a3 100644 --- a/src/world/player/LocalPlayer.cpp +++ b/src/world/player/LocalPlayer.cpp @@ -14,57 +14,68 @@ #include "world/dim/ent/Collision.h" #include "client/conn/ClientNetworkInterpreter.h" -LocalPlayer::LocalPlayer(SubgamePtr game, LocalWorld& world, DimensionPtr dim, Renderer &renderer) : - Player(game, world, dim), DrawableEntity(game, dim), Entity(game, dim), - renderer(renderer), - wireframe(game, dim, {1, 1, 1}), - gameGui(world.getRefs().l(), renderer.window.getSize(), game.l(), renderer) { - - handItemModel.parent = &handModel; - - renderer.window.addResizeCallback("player", [&](glm::ivec2 win) { gameGui.winResized(win); }); +LocalPlayer::LocalPlayer(SubgamePtr game, LocalWorld& world, DimensionPtr dim, Renderer& renderer) : + Player(game, world, dim), DrawableEntity(game, dim), Entity(game, dim), + renderer(renderer), + wireframe(game, dim, { 1, 1, 1 }), + gameGui(world.getRefs().l(), renderer.window.getSize(), game.l(), renderer) { + + handItemModel.parent = &handModel; + + renderer.window.addResizeCallback("player", [&](glm::ivec2 win) { gameGui.winResized(win); }); } -void LocalPlayer::update(Input &input, double delta, glm::vec2 mouseDelta) { - gameGui.update(delta); - handItemModel.setVisible(gameGui.isVisible()); - - updatePhysics(input, delta, mouseDelta); - - Collision::moveCollide(game, dim, collision, pos, vel, - Collision::isOnGround(game, dim, collision, pos, vel) ? 0.6 : vel.y <= 0 ? 0.1 : 0); - - updateCamera(); - - findPointedThing(input); - updateWireframe(); - - if (!gameGui.isInMenu()) interact(input, delta); +void LocalPlayer::update(Input& input, double delta, glm::vec2 mouseDelta) { + gameGui.update(delta); + handItemModel.setVisible(gameGui.isVisible()); + + updatePhysics(input, delta, mouseDelta); + + Collision::moveCollide(game, dim, collision, pos, vel, + Collision::isOnGround(game, dim, collision, pos, vel) ? 0.6 : vel.y <= 0 ? 0.1 : 0); + + updateCamera(); + + findPointedThing(input); + updateWireframe(); + + if (!gameGui.isInMenu()) interact(input, delta); } void LocalPlayer::assertField(Packet packet) { - packet.type = Packet::Type::THIS_PLAYER_INFO; - static_cast(world).getNet().sendPacket(packet, Packet::Channel::INTERACT); + packet.type = Packet::Type::THIS_PLAYER_INFO; + static_cast(world).getNet().sendPacket(packet, Packet::Channel::INTERACT); } -void LocalPlayer::handleAssertion(Deserializer &d) { - while (!d.atEnd()) { - switch (d.readE()) { - default: std::cout << "Invalid assertion." << std::endl; break; - - case NetField::ID: setId(d.read()); break; - case NetField::DIM: setDim(world.getDimension(d.read())); break; - case NetField::POS: setPos(d.read()); break; - case NetField::VEL: setVel(d.read()); break; - case NetField::LOOK_YAW: setYaw(d.read()); break; - case NetField::LOOK_PITCH: setPitch(d.read()); break; - case NetField::FLYING: setFlying(d.read()); break; - - case NetField::HAND_INV: setHandList(d.read()); break; - case NetField::WIELD_INV: setWieldList(d.read()); break; - case NetField::WIELD_INDEX: setWieldIndex(d.read()); break; - } - } +void LocalPlayer::handleAssertion(Deserializer& d) { + while (!d.atEnd()) { + switch (d.readE()) { + default: std::cout << "Invalid assertion." << std::endl; + break; + + case NetField::ID: setId(d.read()); + break; + case NetField::DIM: setDim(world.getDimension(d.read())); + break; + case NetField::POS: setPos(d.read()); + break; + case NetField::VEL: setVel(d.read()); + break; + case NetField::LOOK_YAW: setYaw(d.read()); + break; + case NetField::LOOK_PITCH: setPitch(d.read()); + break; + case NetField::FLYING: setFlying(d.read()); + break; + + case NetField::HAND_INV: setHandList(d.read()); + break; + case NetField::WIELD_INV: setWieldList(d.read()); + break; + case NetField::WIELD_INDEX: setWieldIndex(d.read()); + break; + } + } } // @@ -72,39 +83,39 @@ void LocalPlayer::handleAssertion(Deserializer &d) { // void LocalPlayer::setPos(glm::vec3 pos, bool assert) { - Player::setPos(pos, assert); - this->renderer.camera.setPos(pos + getLookOffset()); + Player::setPos(pos, assert); + this->renderer.camera.setPos(pos + getLookOffset()); } void LocalPlayer::setLookOffset(glm::vec3 eyeOffset, bool assert) { - Player::setLookOffset(eyeOffset, assert); - this->renderer.camera.setPos(pos + getLookOffset()); + Player::setLookOffset(eyeOffset, assert); + this->renderer.camera.setPos(pos + getLookOffset()); } -void LocalPlayer::setHandList(const std::string &list, bool assert) { - Player::setHandList(list, assert); - world.getRefs().l()->setHandList(list); - updateWieldAndHandItems(); +void LocalPlayer::setHandList(const std::string& list, bool assert) { + Player::setHandList(list, assert); + world.getRefs().l()->setHandList(list); + updateWieldAndHandItems(); } void LocalPlayer::setWieldList(const std::string& list, bool assert) { - Player::setWieldList(list, assert); - world.getRefs().l()->setWieldList(list); - setWieldIndex(wieldIndex); - updateWieldAndHandItems(); + Player::setWieldList(list, assert); + world.getRefs().l()->setWieldList(list); + setWieldIndex(wieldIndex); + updateWieldAndHandItems(); } void LocalPlayer::setWieldIndex(unsigned short index, bool assert) { - auto wieldList = world.getRefs().l()->getWieldList(); - wieldIndex = index % std::max((wieldList ? wieldList->getLength() : 1), 1); - Player::setWieldIndex(wieldIndex, assert); - updateWieldAndHandItems(); + auto wieldList = world.getRefs().l()->getWieldList(); + wieldIndex = index % std::max((wieldList ? wieldList->getLength() : 1), 1); + Player::setWieldIndex(wieldIndex, assert); + updateWieldAndHandItems(); } void LocalPlayer::setDim(DimensionPtr dim) { - Player::setDim(dim); - static_cast(world).setActiveDimension(dim); + Player::setDim(dim); + static_cast(world).setActiveDimension(dim); } // @@ -112,29 +123,29 @@ void LocalPlayer::setDim(DimensionPtr dim) { // bool LocalPlayer::isInMenu() { - return gameGui.isInMenu(); + return gameGui.isInMenu(); } void LocalPlayer::showMenu(std::shared_ptr root) { - gameGui.showMenu(root); - renderer.window.input.lockMouse(false); + gameGui.showMenu(root); + renderer.window.input.lockMouse(false); } void LocalPlayer::closeMenu() { - gameGui.closeMenu(); - renderer.window.input.lockMouse(true); + gameGui.closeMenu(); + renderer.window.input.lockMouse(true); } void LocalPlayer::setHud(std::shared_ptr hud) { - gameGui.setHud(hud); + gameGui.setHud(hud); } std::shared_ptr LocalPlayer::getHud() { - return gameGui.getHud(); + return gameGui.getHud(); } void LocalPlayer::setHudVisible(bool hudVisible) { - gameGui.setVisible(hudVisible); + gameGui.setVisible(hudVisible); } // @@ -142,28 +153,28 @@ void LocalPlayer::setHudVisible(bool hudVisible) { // InventoryPtr LocalPlayer::getInventory() { - return dim->getWorld().getRefs()->getInventory("current_player"); + return dim->getWorld().getRefs()->getInventory("current_player"); } Target& LocalPlayer::getTarget() { - return target; + return target; } // // Draw Functions // -void LocalPlayer::draw(Renderer &renderer) { - wireframe.draw(renderer); - handItemModel.draw(renderer); +void LocalPlayer::draw(Renderer& renderer) { + wireframe.draw(renderer); + handItemModel.draw(renderer); } -void LocalPlayer::drawHud(Renderer &renderer) { - gameGui.drawHud(renderer); +void LocalPlayer::drawHud(Renderer& renderer) { + gameGui.drawHud(renderer); } -void LocalPlayer::drawMenu(Renderer &renderer) { - gameGui.drawMenu(renderer); +void LocalPlayer::drawMenu(Renderer& renderer) { + gameGui.drawMenu(renderer); } // @@ -171,199 +182,201 @@ void LocalPlayer::drawMenu(Renderer &renderer) { // bool LocalPlayer::getKey(Input& input, LocalPlayer::PlayerControl control) { - if (gameGui.isInMenu()) return false; - return input.keyDown( - control == PlayerControl::FORWARD ? GLFW_KEY_W : - control == PlayerControl::BACKWARD ? GLFW_KEY_S : - control == PlayerControl::LEFT ? GLFW_KEY_A : - control == PlayerControl::RIGHT ? GLFW_KEY_D : - control == PlayerControl::JUMP ? GLFW_KEY_SPACE : - control == PlayerControl::MOD1 ? GLFW_KEY_LEFT_SHIFT : - GLFW_KEY_LEFT_CONTROL); + if (gameGui.isInMenu()) return false; + return input.keyDown( + control == PlayerControl::FORWARD ? GLFW_KEY_W : + control == PlayerControl::BACKWARD ? GLFW_KEY_S : + control == PlayerControl::LEFT ? GLFW_KEY_A : + control == PlayerControl::RIGHT ? GLFW_KEY_D : + control == PlayerControl::JUMP ? GLFW_KEY_SPACE : + control == PlayerControl::MOD1 ? GLFW_KEY_LEFT_SHIFT : + GLFW_KEY_LEFT_CONTROL); } -void LocalPlayer::updatePhysics(Input &input, double delta, glm::vec2 mouseDelta) { - static constexpr float JUMP_VEL = 0.14f; - static constexpr float BASE_MOVE_SPEED = 4.3f; - static constexpr float MOUSE_SENSITIVITY = 0.1f; - - //Position movement - bool sprinting = getKey(input, PlayerControl::MOD2); - - double moveSpeed = BASE_MOVE_SPEED * delta * (sprinting ? 1.6 : 1); - float friction = 0.3f; - - if (flying) { - moveSpeed *= 4; - friction = 0.15f; - } - else if (getKey(input, PlayerControl::JUMP) && - Collision::isOnGround(game, dim, collision, pos, vel)) vel.y = JUMP_VEL; - - //Calculate movement vector from camera angle. - auto& camera = renderer.camera; - glm::vec3 frontFlat = glm::normalize(glm::vec3(camera.getFront().x, 0, camera.getFront().z)); - glm::vec3 rightFlat = glm::normalize(glm::vec3(camera.getRight().x, 0, camera.getRight().z)); - - glm::vec3 mod {0, 0, 0}; - - if (getKey(input, PlayerControl::FORWARD)) mod += frontFlat; - if (getKey(input, PlayerControl::BACKWARD)) mod -= frontFlat; - if (getKey(input, PlayerControl::RIGHT)) mod += rightFlat; - if (getKey(input, PlayerControl::LEFT)) mod -= rightFlat; - - if (flying) { - if (getKey(input, PlayerControl::JUMP)) mod.y += 1; - if (getKey(input, PlayerControl::MOD1)) mod.y -= 1; - } - else { - if (!Collision::isOnGround(game, dim, collision, pos, vel)) vel.y = std::fmax(vel.y - 0.0085, -3); - else if (vel.y < 0) vel.y = 0; - } - - if (glm::length(mod) != 0) mod = glm::normalize(mod); - mod = mod * static_cast(moveSpeed); - - if (!flying) { - glm::vec3 velFlat = {vel.x, 0, vel.z}; - //Add movement vector with friction. - velFlat = velFlat * (1.0f-friction) + mod * friction; - - vel.x = velFlat.x; - vel.z = velFlat.z; - } - else { - //If flying factor in vertical mod values. - vel = vel * (1.0f-friction) + mod * friction; - } - - //View movement - mouseDelta.x *= MOUSE_SENSITIVITY; - mouseDelta.y *= MOUSE_SENSITIVITY; - - yaw += mouseDelta.x; - pitch += mouseDelta.y; - - while (yaw > 360.f) yaw -= 360.f; - while (yaw < 0.f) yaw += 360.f; - - pitch = std::fmin(std::fmax(pitch, -90), 90); +void LocalPlayer::updatePhysics(Input& input, double delta, glm::vec2 mouseDelta) { + static constexpr float JUMP_VEL = 0.14f; + static constexpr float BASE_MOVE_SPEED = 4.3f; + static constexpr float MOUSE_SENSITIVITY = 0.1f; + + //Position movement + bool sprinting = getKey(input, PlayerControl::MOD2); + + double moveSpeed = BASE_MOVE_SPEED * delta * (sprinting ? 1.6 : 1); + float friction = 0.3f; + + if (flying) { + moveSpeed *= 4; + friction = 0.15f; + } + else if (getKey(input, PlayerControl::JUMP) && + Collision::isOnGround(game, dim, collision, pos, vel)) + vel.y = JUMP_VEL; + + //Calculate movement vector from camera angle. + auto& camera = renderer.camera; + glm::vec3 frontFlat = glm::normalize(glm::vec3(camera.getFront().x, 0, camera.getFront().z)); + glm::vec3 rightFlat = glm::normalize(glm::vec3(camera.getRight().x, 0, camera.getRight().z)); + + glm::vec3 mod{ 0, 0, 0 }; + + if (getKey(input, PlayerControl::FORWARD)) mod += frontFlat; + if (getKey(input, PlayerControl::BACKWARD)) mod -= frontFlat; + if (getKey(input, PlayerControl::RIGHT)) mod += rightFlat; + if (getKey(input, PlayerControl::LEFT)) mod -= rightFlat; + + if (flying) { + if (getKey(input, PlayerControl::JUMP)) mod.y += 1; + if (getKey(input, PlayerControl::MOD1)) mod.y -= 1; + } + else { + if (!Collision::isOnGround(game, dim, collision, pos, vel)) vel.y = std::fmax(vel.y - 0.0085, -3); + else if (vel.y < 0) vel.y = 0; + } + + if (glm::length(mod) != 0) mod = glm::normalize(mod); + mod = mod * static_cast(moveSpeed); + + if (!flying) { + glm::vec3 velFlat = { vel.x, 0, vel.z }; + //Add movement vector with friction. + velFlat = velFlat * (1.0f - friction) + mod * friction; + + vel.x = velFlat.x; + vel.z = velFlat.z; + } + else { + //If flying factor in vertical mod values. + vel = vel * (1.0f - friction) + mod * friction; + } + + //View movement + mouseDelta.x *= MOUSE_SENSITIVITY; + mouseDelta.y *= MOUSE_SENSITIVITY; + + yaw += mouseDelta.x; + pitch += mouseDelta.y; + + while (yaw > 360.f) yaw -= 360.f; + while (yaw < 0.f) yaw += 360.f; + + pitch = std::fmin(std::fmax(pitch, -90), 90); } void LocalPlayer::updateCamera() { - renderer.camera.setYaw(yaw); - renderer.camera.setPitch(pitch); - - auto type = game->getDefs().fromId(wieldItem).type; - - glm::vec3 eyesPos = pos + getLookOffset(); - renderer.camera.setPos(eyesPos); - - float pitch = std::min(std::max(this->pitch, -89.9f), 89.9f); - - glm::vec3 front = glm::normalize(glm::vec3 { - cos(glm::radians(yaw)) * cos(glm::radians(pitch)), - sin(glm::radians(pitch)), - sin(glm::radians(yaw)) * cos(glm::radians(pitch))}); - - glm::vec3 right = glm::normalize(glm::cross(front, {0, 1, 0})); - glm::vec3 up = glm::normalize(glm::cross(right, front)); - glm::vec3 handPos = eyesPos + front * 0.25f + right * 0.25f + up * (type == ItemDef::Type::CRAFTITEM ? -0.15f : -0.2f); - - handModel.setRotateY(-yaw); - handModel.setRotateZ(pitch); - - if (type == ItemDef::Type::CRAFTITEM) { - handItemModel.setRotateX(45); - handItemModel.setRotateY(110); - handItemModel.setRotateZ(-25); - } - else { - handItemModel.setRotateX(0); - handItemModel.setRotateY(0); - handItemModel.setRotateZ(0); - } - - handItemModel.setPos(handPos + vel * 0.1f); - handItemModel.setScale((type == ItemDef::Type::CRAFTITEM ? 0.2f : 0.12f)); + renderer.camera.setYaw(yaw); + renderer.camera.setPitch(pitch); + + auto type = game->getDefs().fromId(wieldItem).type; + + glm::vec3 eyesPos = pos + getLookOffset(); + renderer.camera.setPos(eyesPos); + + float pitch = std::min(std::max(this->pitch, -89.9f), 89.9f); + + glm::vec3 front = glm::normalize(glm::vec3{ + cos(glm::radians(yaw)) * cos(glm::radians(pitch)), + sin(glm::radians(pitch)), + sin(glm::radians(yaw)) * cos(glm::radians(pitch)) }); + + glm::vec3 right = glm::normalize(glm::cross(front, { 0, 1, 0 })); + glm::vec3 up = glm::normalize(glm::cross(right, front)); + glm::vec3 handPos = + eyesPos + front * 0.25f + right * 0.25f + up * (type == ItemDef::Type::CRAFTITEM ? -0.15f : -0.2f); + + handModel.setRotateY(-yaw); + handModel.setRotateZ(pitch); + + if (type == ItemDef::Type::CRAFTITEM) { + handItemModel.setRotateX(45); + handItemModel.setRotateY(110); + handItemModel.setRotateZ(-25); + } + else { + handItemModel.setRotateX(0); + handItemModel.setRotateY(0); + handItemModel.setRotateZ(0); + } + + handItemModel.setPos(handPos + vel * 0.1f); + handItemModel.setScale((type == ItemDef::Type::CRAFTITEM ? 0.2f : 0.12f)); } -void LocalPlayer::findPointedThing(Input &input) { - static constexpr float LOOK_DISTANCE = 6.5f; - static constexpr float LOOK_PRECISION = 0.01f; - - glm::ivec3 chunkPos = {}; - std::shared_ptr chunk = nullptr; - - for (Ray ray(*this); ray.getLength() < LOOK_DISTANCE; ray.step(LOOK_PRECISION)) { - glm::vec3 rayEnd = ray.getEnd(); - glm::ivec3 roundedPos = glm::floor(rayEnd); - - glm::ivec3 currChunkPos = Space::Chunk::world::fromBlock(roundedPos); - if (currChunkPos != chunkPos || chunk == nullptr) { - chunkPos = currChunkPos; - chunk = dim->getChunk(chunkPos); - if (chunk == nullptr) continue; - } - - unsigned int blockID = chunk->getBlock(Space::Block::relative::toChunk(roundedPos)); - auto& boxes = game->getDefs().blockFromId(blockID).sBoxes; - - for (auto& sBox : boxes) { - auto face = sBox.intersects(rayEnd, roundedPos); - - if (face != EVec::NONE) { - target = Target(dim, roundedPos, face); - return; - } - } - } - - target = Target {}; +void LocalPlayer::findPointedThing(Input& input) { + static constexpr float LOOK_DISTANCE = 6.5f; + static constexpr float LOOK_PRECISION = 0.01f; + + glm::ivec3 chunkPos = {}; + std::shared_ptr chunk = nullptr; + + for (Ray ray(*this); ray.getLength() < LOOK_DISTANCE; ray.step(LOOK_PRECISION)) { + glm::vec3 rayEnd = ray.getEnd(); + glm::ivec3 roundedPos = glm::floor(rayEnd); + + glm::ivec3 currChunkPos = Space::Chunk::world::fromBlock(roundedPos); + if (currChunkPos != chunkPos || chunk == nullptr) { + chunkPos = currChunkPos; + chunk = dim->getChunk(chunkPos); + if (chunk == nullptr) continue; + } + + unsigned int blockID = chunk->getBlock(Space::Block::relative::toChunk(roundedPos)); + auto& boxes = game->getDefs().blockFromId(blockID).sBoxes; + + for (auto& sBox : boxes) { + auto face = sBox.intersects(rayEnd, roundedPos); + + if (face != EVec::NONE) { + target = Target(dim, roundedPos, face); + return; + } + } + } + + target = Target{}; } void LocalPlayer::updateWireframe() { - if (!gameGui.isVisible()) { - wireframe.setVisible(false); - } - else if (target.type == Target::Type::BLOCK) { - auto& boxes = game->getDefs().blockFromId(dim->getBlock(target.pos)).sBoxes; - float distance = glm::distance(pos, target.pos + glm::vec3(0.5)); - - wireframe.updateMesh(boxes, 0.002f + distance * 0.0014f); - wireframe.setPos(target.pos); - wireframe.setVisible(true); - } - else { - wireframe.setVisible(false); - } + if (!gameGui.isVisible()) { + wireframe.setVisible(false); + } + else if (target.type == Target::Type::BLOCK) { + auto& boxes = game->getDefs().blockFromId(dim->getBlock(target.pos)).sBoxes; + float distance = glm::distance(pos, target.pos + glm::vec3(0.5)); + + wireframe.updateMesh(boxes, 0.002f + distance * 0.0014f); + wireframe.setPos(target.pos); + wireframe.setVisible(true); + } + else { + wireframe.setVisible(false); + } } void LocalPlayer::interact(Input& input, double delta) { - if (target.type == Target::Type::BLOCK) { - if (input.mouseDown(GLFW_MOUSE_BUTTON_LEFT) && breakTime == 0) { - breakInterval = dim->blockHit(target, static_cast(dim->getWorld()).getPlayer()); - breakTime += delta; - } - else if (input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) - dim->blockPlaceOrInteract(target, static_cast(dim->getWorld()).getPlayer()); - } - - if (breakTime > 0) breakTime += delta; - if (breakTime > breakInterval) breakTime = 0; + if (target.type == Target::Type::BLOCK) { + if (input.mouseDown(GLFW_MOUSE_BUTTON_LEFT) && breakTime == 0) { + breakInterval = dim->blockHit(target, static_cast(dim->getWorld()).getPlayer()); + breakTime += delta; + } + else if (input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) + dim->blockPlaceOrInteract(target, static_cast(dim->getWorld()).getPlayer()); + } + + if (breakTime > 0) breakTime += delta; + if (breakTime > breakInterval) breakTime = 0; } void LocalPlayer::updateWieldAndHandItems() { - auto handList = world.getRefs().l()->getHandList(); - auto wieldList = world.getRefs().l()->getWieldList(); - - handItem = handList && handList->getLength() > 0 ? handList->getStack(0).id : 0; - wieldItem = wieldList && wieldList->getLength() > wieldIndex ? wieldList->getStack(wieldIndex).id : 0; - - auto& model = game->getDefs().fromId(wieldItem <= DefinitionAtlas::AIR ? handItem : wieldItem).entityModel; - handItemModel.setModel(model); + auto handList = world.getRefs().l()->getHandList(); + auto wieldList = world.getRefs().l()->getWieldList(); + + handItem = handList && handList->getLength() > 0 ? handList->getStack(0).id : 0; + wieldItem = wieldList && wieldList->getLength() > wieldIndex ? wieldList->getStack(wieldIndex).id : 0; + + auto& model = game->getDefs().fromId(wieldItem <= DefinitionAtlas::AIR ? handItem : wieldItem).entityModel; + handItemModel.setModel(model); } LocalPlayer::~LocalPlayer() { - renderer.window.removeResizeCallback("player"); + renderer.window.removeResizeCallback("player"); } \ No newline at end of file diff --git a/src/world/player/LocalPlayer.h b/src/world/player/LocalPlayer.h index 5b09b0b4..cca67ddd 100644 --- a/src/world/player/LocalPlayer.h +++ b/src/world/player/LocalPlayer.h @@ -13,69 +13,91 @@ #include "client/entity/WireframeEntity.h" class Input; + class Deserializer; + class LuaGuiElement; + class LocalInventory; + class LocalInventoryRefs; + enum class NetPlayerField; class LocalPlayer : public virtual DrawableEntity, public Player { -public: - enum class PlayerControl { FORWARD, LEFT, BACKWARD, RIGHT, JUMP, MOD1, MOD2 }; - - LocalPlayer(SubgamePtr game, LocalWorld& world, DimensionPtr dim, Renderer &renderer); - - void update(Input &input, double delta, glm::vec2 mouseDelta); - virtual void assertField(Packet packet) override; - virtual void handleAssertion(Deserializer& d) override; - - virtual InventoryPtr getInventory() override; - - virtual void setPos(glm::vec3 pos, bool assert = false) override; - virtual void setLookOffset(glm::vec3 eyeOffset, bool assert = false) override; - virtual void setHandList(const std::string& list, bool assert = false) override; - virtual void setWieldList(const std::string& list, bool assert = false) override; - virtual void setWieldIndex(unsigned short index, bool assert = false) override; - virtual void setDim(DimensionPtr dim) override; - - bool isInMenu(); - void showMenu(std::shared_ptr root); - void closeMenu(); - - void setHud(std::shared_ptr hud); - std::shared_ptr getHud(); - void setHudVisible(bool hudVisible); - - Target& getTarget(); - - void draw(Renderer& renderer) override; - void drawHud(Renderer& renderer); - void drawMenu(Renderer& renderer); - - ~LocalPlayer(); - -private: - bool getKey(Input& input, PlayerControl control); - - void updatePhysics(Input &input, double delta, glm::vec2 mouseDelta); - void updateCamera(); - - void findPointedThing(Input &input); - void updateWireframe(); - - void interact(Input& input, double delta); - - void updateWieldAndHandItems(); - - GameGui gameGui; - DrawableEntity handModel; - DrawableEntity handItemModel; - WireframeEntity wireframe; - - Renderer& renderer; - - double breakTime = 0; - double breakInterval = 0; - Target target; + public: + enum class PlayerControl { + FORWARD, LEFT, BACKWARD, RIGHT, JUMP, MOD1, MOD2 + }; + + LocalPlayer(SubgamePtr game, LocalWorld& world, DimensionPtr dim, Renderer& renderer); + + void update(Input& input, double delta, glm::vec2 mouseDelta); + + virtual void assertField(Packet packet) override; + + virtual void handleAssertion(Deserializer& d) override; + + virtual InventoryPtr getInventory() override; + + virtual void setPos(glm::vec3 pos, bool assert = false) override; + + virtual void setLookOffset(glm::vec3 eyeOffset, bool assert = false) override; + + virtual void setHandList(const std::string& list, bool assert = false) override; + + virtual void setWieldList(const std::string& list, bool assert = false) override; + + virtual void setWieldIndex(unsigned short index, bool assert = false) override; + + virtual void setDim(DimensionPtr dim) override; + + bool isInMenu(); + + void showMenu(std::shared_ptr root); + + void closeMenu(); + + void setHud(std::shared_ptr hud); + + std::shared_ptr getHud(); + + void setHudVisible(bool hudVisible); + + Target& getTarget(); + + void draw(Renderer& renderer) override; + + void drawHud(Renderer& renderer); + + void drawMenu(Renderer& renderer); + + ~LocalPlayer(); + + private: + bool getKey(Input& input, PlayerControl control); + + void updatePhysics(Input& input, double delta, glm::vec2 mouseDelta); + + void updateCamera(); + + void findPointedThing(Input& input); + + void updateWireframe(); + + void interact(Input& input, double delta); + + void updateWieldAndHandItems(); + + GameGui gameGui; + DrawableEntity handModel; + DrawableEntity handItemModel; + WireframeEntity wireframe; + + Renderer& renderer; + + double breakTime = 0; + double breakInterval = 0; + Target target; }; diff --git a/src/world/player/Player.cpp b/src/world/player/Player.cpp index dd263078..5899a2fe 100644 --- a/src/world/player/Player.cpp +++ b/src/world/player/Player.cpp @@ -11,80 +11,80 @@ #include "world/dim/Dimension.h" void Player::setDim(DimensionPtr dim, bool assert) { - Entity::setDim(dim); - if (assert) assertField(Serializer().appendE(NetField::DIM).append(dim->getInd()).packet()); + Entity::setDim(dim); + if (assert) assertField(Serializer().appendE(NetField::DIM).append(dim->getInd()).packet()); } void Player::setPos(glm::vec3 pos, bool assert) { - Entity::setPos(pos); - if (assert) assertField(Serializer().appendE(NetField::POS).append(pos).packet()); + Entity::setPos(pos); + if (assert) assertField(Serializer().appendE(NetField::POS).append(pos).packet()); } void Player::setVel(glm::vec3 vel, bool assert) { - Entity::setVel(vel); - if (assert) assertField(Serializer().appendE(NetField::VEL).append(vel).packet()); + Entity::setVel(vel); + if (assert) assertField(Serializer().appendE(NetField::VEL).append(vel).packet()); } float Player::getYaw() { - return yaw; + return yaw; } void Player::setYaw(float yaw, bool assert) { - this->yaw = yaw; - if (assert) assertField(Serializer().appendE(NetField::LOOK_YAW).append(yaw).packet()); + this->yaw = yaw; + if (assert) assertField(Serializer().appendE(NetField::LOOK_YAW).append(yaw).packet()); } float Player::getPitch() { - return pitch; + return pitch; } void Player::setPitch(float pitch, bool assert) { - this->pitch = pitch; - if (assert) assertField(Serializer().appendE(NetField::LOOK_PITCH).append(pitch).packet()); + this->pitch = pitch; + if (assert) assertField(Serializer().appendE(NetField::LOOK_PITCH).append(pitch).packet()); } glm::vec3 Player::getLookOffset() { - return this->lookOffset; + return this->lookOffset; } void Player::setLookOffset(glm::vec3 lookOffset, bool assert) { - this->lookOffset = lookOffset; - if (assert) assertField(Serializer().appendE(NetField::LOOK_OFF).append(lookOffset).packet()); + this->lookOffset = lookOffset; + if (assert) assertField(Serializer().appendE(NetField::LOOK_OFF).append(lookOffset).packet()); } bool Player::isFlying() { - return flying; + return flying; } void Player::setFlying(bool flying, bool assert) { - this->flying = flying; - if (assert) assertField(Serializer().appendE(NetField::FLYING).append(flying).packet()); + this->flying = flying; + if (assert) assertField(Serializer().appendE(NetField::FLYING).append(flying).packet()); } std::string Player::getHandList() { - return handList; + return handList; } -void Player::setHandList(const std::string &list, bool assert) { - handList = list; - if (assert) assertField(Serializer().appendE(NetField::HAND_INV).append(handList).packet()); +void Player::setHandList(const std::string& list, bool assert) { + handList = list; + if (assert) assertField(Serializer().appendE(NetField::HAND_INV).append(handList).packet()); } std::string Player::getWieldList() { - return wieldList; + return wieldList; } -void Player::setWieldList(const std::string &list, bool assert) { - wieldList = list; - if (assert) assertField(Serializer().appendE(NetField::WIELD_INV).append(wieldList).packet()); +void Player::setWieldList(const std::string& list, bool assert) { + wieldList = list; + if (assert) assertField(Serializer().appendE(NetField::WIELD_INV).append(wieldList).packet()); } unsigned short Player::getWieldIndex() { - return wieldIndex; + return wieldIndex; } void Player::setWieldIndex(unsigned short index, bool assert) { - wieldIndex = index; - if (assert) assertField(Serializer().appendE(NetField::WIELD_INDEX).append(index).packet()); + wieldIndex = index; + if (assert) assertField(Serializer().appendE(NetField::WIELD_INDEX).append(index).packet()); } \ No newline at end of file diff --git a/src/world/player/Player.h b/src/world/player/Player.h index 49be3c2e..3762c5ec 100644 --- a/src/world/player/Player.h +++ b/src/world/player/Player.h @@ -12,67 +12,83 @@ #include "game/atlas/DefinitionAtlas.h" class World; + class Packet; + class Subgame; + class Inventory; + class Dimension; + class Deserializer; + class InventoryList; class Player : public virtual Entity { -public: - Player(SubgamePtr game, World& world, DimensionPtr dim, unsigned int id = 0) : - Entity(game, dim), - world(world), lookOffset(0, 1.65, 0) { - collision = {{-0.3, 0, -0.3}, {0.3, 1.8, 0.3}}; - this->id = id; - } - - virtual void setDim(DimensionPtr dim, bool assert = false); - virtual void setPos(glm::vec3 pos, bool assert = false); - virtual void setVel(glm::vec3 vel, bool assert = false); - - virtual float getYaw(); - virtual void setYaw(float yaw, bool assert = false); - - virtual float getPitch(); - virtual void setPitch(float pitch, bool assert = false); - - virtual glm::vec3 getLookOffset(); - virtual void setLookOffset(glm::vec3 lookOffset, bool assert = false); - - virtual bool isFlying(); - virtual void setFlying(bool flying, bool assert = false); - - virtual std::string getHandList(); - virtual void setHandList(const std::string& list, bool assert = false); - - virtual std::string getWieldList(); - virtual void setWieldList(const std::string& list, bool assert = false); - - virtual unsigned short getWieldIndex(); - virtual void setWieldIndex(unsigned short index, bool assert = false); - - virtual InventoryPtr getInventory() = 0; - - virtual void handleAssertion(Deserializer& d) = 0; -protected: - virtual void assertField(Packet packet) = 0; - - World& world; - - float yaw = 0; - float pitch = 0; - - glm::vec3 lookOffset {}; - - bool flying = false; - - std::string handList = ""; - std::string wieldList = ""; - - unsigned int handItem = DefinitionAtlas::AIR; - unsigned int wieldItem = DefinitionAtlas::AIR; - - unsigned int wieldIndex = 0; + public: + Player(SubgamePtr game, World& world, DimensionPtr dim, unsigned int id = 0) : + Entity(game, dim), + world(world), lookOffset(0, 1.65, 0) { + collision = {{ -0.3, 0, -0.3 }, { 0.3, 1.8, 0.3 }}; + this->id = id; + } + + virtual void setDim(DimensionPtr dim, bool assert = false); + + virtual void setPos(glm::vec3 pos, bool assert = false); + + virtual void setVel(glm::vec3 vel, bool assert = false); + + virtual float getYaw(); + + virtual void setYaw(float yaw, bool assert = false); + + virtual float getPitch(); + + virtual void setPitch(float pitch, bool assert = false); + + virtual glm::vec3 getLookOffset(); + + virtual void setLookOffset(glm::vec3 lookOffset, bool assert = false); + + virtual bool isFlying(); + + virtual void setFlying(bool flying, bool assert = false); + + virtual std::string getHandList(); + + virtual void setHandList(const std::string& list, bool assert = false); + + virtual std::string getWieldList(); + + virtual void setWieldList(const std::string& list, bool assert = false); + + virtual unsigned short getWieldIndex(); + + virtual void setWieldIndex(unsigned short index, bool assert = false); + + virtual InventoryPtr getInventory() = 0; + + virtual void handleAssertion(Deserializer& d) = 0; + + protected: + virtual void assertField(Packet packet) = 0; + + World& world; + + float yaw = 0; + float pitch = 0; + + glm::vec3 lookOffset{}; + + bool flying = false; + + std::string handList = ""; + std::string wieldList = ""; + + unsigned int handItem = DefinitionAtlas::AIR; + unsigned int wieldItem = DefinitionAtlas::AIR; + + unsigned int wieldIndex = 0; }; diff --git a/src/world/player/ServerPlayer.cpp b/src/world/player/ServerPlayer.cpp index c9d10dc0..2e1a8466 100644 --- a/src/world/player/ServerPlayer.cpp +++ b/src/world/player/ServerPlayer.cpp @@ -12,53 +12,62 @@ #include "world/inv/ServerInventoryRefs.h" ServerPlayer::ServerPlayer(ServerClient& client, World& world, SubgamePtr game, DimensionPtr dim) : - Player(game, world, dim, client.id), Entity(game, dim), client(client), - inventory(world.getRefs()->createInventory("player:" + std::to_string(id))) {} + Player(game, world, dim, client.id), Entity(game, dim), client(client), + inventory(world.getRefs()->createInventory("player:" + std::to_string(id))) {} void ServerPlayer::assertField(Packet packet) { - packet.type = Packet::Type::THIS_PLAYER_INFO; - packet.sendTo(getPeer(), Packet::Channel::INTERACT); + packet.type = Packet::Type::THIS_PLAYER_INFO; + packet.sendTo(getPeer(), Packet::Channel::INTERACT); } -void ServerPlayer::handleAssertion(Deserializer &d) { - while (!d.atEnd()) { - switch (d.readE()) { - default: std::cout << "Invalid assertion." << std::endl; break; - - case NetField::POS: setPos(d.read()); break; - case NetField::VEL: setVel(d.read()); break; - case NetField::LOOK_YAW: setPitch(d.read()); break; - case NetField::LOOK_PITCH: setYaw(d.read()); break; - case NetField::FLYING: setFlying(d.read()); break; - - case NetField::HAND_INV: setHandList(d.read()); break; - case NetField::WIELD_INV: setWieldList(d.read()); break; - case NetField::WIELD_INDEX: setWieldIndex(d.read()); break; - } - } +void ServerPlayer::handleAssertion(Deserializer& d) { + while (!d.atEnd()) { + switch (d.readE()) { + default: std::cout << "Invalid assertion." << std::endl; + break; + + case NetField::POS: setPos(d.read()); + break; + case NetField::VEL: setVel(d.read()); + break; + case NetField::LOOK_YAW: setPitch(d.read()); + break; + case NetField::LOOK_PITCH: setYaw(d.read()); + break; + case NetField::FLYING: setFlying(d.read()); + break; + + case NetField::HAND_INV: setHandList(d.read()); + break; + case NetField::WIELD_INV: setWieldList(d.read()); + break; + case NetField::WIELD_INDEX: setWieldIndex(d.read()); + break; + } + } } void ServerPlayer::setDim(DimensionPtr dim, bool assert) { - Player::setDim(dim, assert); - - // Force a generation flush. - lastPos = glm::vec3(INFINITY); - changedMapBlocks = true; + Player::setDim(dim, assert); + + // Force a generation flush. + lastPos = glm::vec3(INFINITY); + changedMapBlocks = true; } void ServerPlayer::setPos(glm::vec3 pos, bool assert) { - glm::vec3 lastMapBlock = Space::MapBlock::world::fromBlock(this->pos); - glm::vec3 newMapBlock = Space::MapBlock::world::fromBlock(pos); - - Player::setPos(pos, assert); - - if (newMapBlock != lastMapBlock && !changedMapBlocks) changedMapBlocks = true; + glm::vec3 lastMapBlock = Space::MapBlock::world::fromBlock(this->pos); + glm::vec3 newMapBlock = Space::MapBlock::world::fromBlock(pos); + + Player::setPos(pos, assert); + + if (newMapBlock != lastMapBlock && !changedMapBlocks) changedMapBlocks = true; } InventoryPtr ServerPlayer::getInventory() { - return inventory; + return inventory; } ENetPeer* ServerPlayer::getPeer() { - return client.peer; + return client.peer; } \ No newline at end of file diff --git a/src/world/player/ServerPlayer.h b/src/world/player/ServerPlayer.h index 7bdf3704..71405a6b 100644 --- a/src/world/player/ServerPlayer.h +++ b/src/world/player/ServerPlayer.h @@ -14,29 +14,35 @@ #include "world/inv/ServerInventory.h" class ServerClient; + class Deserializer; -class ServerSubgame; + +class ServerSubgame; + class ServerInventoryRefs; + enum class NetPlayerField; class ServerPlayer : public Player { -public: - ServerPlayer(ServerClient& client, World& world, SubgamePtr game, DimensionPtr dim); - - virtual void assertField(Packet packet) override; - virtual void handleAssertion(Deserializer& d) override; - - virtual void setDim(DimensionPtr dim, bool assert = false) override; - virtual void setPos(glm::vec3 pos, bool assert = false) override; - - virtual InventoryPtr getInventory() override; - - ENetPeer* getPeer(); - - bool changedMapBlocks = true; - glm::vec3 lastPos = glm::vec3(INFINITY); - -private: - ServerClient& client; - InventoryPtr inventory; + public: + ServerPlayer(ServerClient& client, World& world, SubgamePtr game, DimensionPtr dim); + + virtual void assertField(Packet packet) override; + + virtual void handleAssertion(Deserializer& d) override; + + virtual void setDim(DimensionPtr dim, bool assert = false) override; + + virtual void setPos(glm::vec3 pos, bool assert = false) override; + + virtual InventoryPtr getInventory() override; + + ENetPeer* getPeer(); + + bool changedMapBlocks = true; + glm::vec3 lastPos = glm::vec3(INFINITY); + + private: + ServerClient& client; + InventoryPtr inventory; };