diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/AssetManager.cpp | 2 | ||||
-rw-r--r-- | src/core/AssetManager.hpp | 75 | ||||
-rw-r--r-- | src/core/Core.cpp | 4 | ||||
-rw-r--r-- | src/core/Core.hpp | 95 | ||||
-rw-r--r-- | src/core/Event.cpp | 76 | ||||
-rw-r--r-- | src/core/Event.hpp | 96 |
6 files changed, 345 insertions, 3 deletions
diff --git a/src/core/AssetManager.cpp b/src/core/AssetManager.cpp index d263c4a..14ea677 100644 --- a/src/core/AssetManager.cpp +++ b/src/core/AssetManager.cpp @@ -1,4 +1,4 @@ -#include <AssetManager.hpp> +#include <core/AssetManager.hpp> namespace fs = std::experimental::filesystem; diff --git a/src/core/AssetManager.hpp b/src/core/AssetManager.hpp new file mode 100644 index 0000000..26c7eca --- /dev/null +++ b/src/core/AssetManager.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include <experimental/filesystem> +#include <map> + +#include <GL/glew.h> +#include <glm/vec4.hpp> +#include <nlohmann/json.hpp> + +#include <world/Block.hpp> +#include <graphics/Texture.hpp> + +struct TextureCoordinates { + TextureCoordinates(float x = -1, float y = -1, float w = -1, float h = -1) : x(x), y(y), w(w), h(h) {} + + bool operator==(const TextureCoordinates &rhs) const { + return x == rhs.x && + y == rhs.y && + w == rhs.w && + h == rhs.h; + } + + explicit operator bool() const { + return !(*this == TextureCoordinates(-1, -1, -1, -1)); + } + + float x, y, w, h; +}; + +struct BlockTextureId { + //Block sides: 0 - bottom, 1 - top, 2 - north, 3 - south, 4 - west, 5 - east 6 - every side + BlockTextureId(int id = 0, int state = 0, int side = 6) : id(id), state(state), side(side) {} + + int id:9; + int state:4; + int side:3; + + + bool operator<(const BlockTextureId &rhs) const { + if (id < rhs.id) + return true; + if (rhs.id < id) + return false; + if (state < rhs.state) + return true; + if (rhs.state < state) + return false; + return side < rhs.side; + } +}; + +class AssetManager { + Texture *textureAtlas; + std::map<std::string, Block> assetIds; + std::map<std::string, TextureCoordinates> assetTextures; + std::map<BlockTextureId,glm::vec4> textureAtlasIndexes; +public: + AssetManager(); + + ~AssetManager(); + + void LoadTextureResources(); + + TextureCoordinates GetTextureByAssetName(std::string AssetName); + + std::string GetTextureAssetNameByBlockId(BlockTextureId block); + + GLuint GetTextureAtlas(); + + const std::map<BlockTextureId,glm::vec4> &GetTextureAtlasIndexes(); + + void LoadIds(); + + TextureCoordinates GetTextureByBlock(BlockTextureId block); +}; diff --git a/src/core/Core.cpp b/src/core/Core.cpp index 44e2648..e98d204 100644 --- a/src/core/Core.cpp +++ b/src/core/Core.cpp @@ -44,7 +44,7 @@ void Core::Exec() { UpdateChunksToRender(); } - /*std::ostringstream toWindow; + std::ostringstream toWindow; auto camPos = gameState->Position(); auto velPos = glm::vec3(gameState->g_PlayerVelocityX, gameState->g_PlayerVelocityY, gameState->g_PlayerVelocityZ); @@ -57,7 +57,7 @@ void Core::Exec() { toWindow << " (" << deltaTime * 1000 << "ms); "; toWindow << "Tickrate: " << tickRate << " (" << (1.0 / tickRate * 1000) << "ms); "; toWindow << "Sections: " << sectionRate << " (" << (1.0 / sectionRate * 1000) << "ms); "; - window->setTitle(toWindow.str());*/ + window->setTitle(toWindow.str()); HandleEvents(); if (isMouseCaptured) HandleMouseCapture(); diff --git a/src/core/Core.hpp b/src/core/Core.hpp new file mode 100644 index 0000000..fdbb377 --- /dev/null +++ b/src/core/Core.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include <iomanip> +#include <tuple> + +#include <easylogging++.h> +#include <SFML/Window.hpp> +#include <GL/glew.h> +#include <glm/gtc/type_ptr.hpp> + +#include <world/GameState.hpp> +#include <core/AssetManager.hpp> +#include <graphics/Shader.hpp> +#include <graphics/Gui.hpp> +#include <graphics/RenderSection.hpp> +#include <network/NetworkClient.hpp> + +struct MyMutex { + std::mutex mtx; + std::string str; + MyMutex(std::string name); + void lock(); + void unlock(); +}; + +class Core { + GameState *gameState; + NetworkClient *client; + sf::Window *window; + AssetManager *assetManager; + bool isMouseCaptured = false; + bool isRunning = true; + enum { + MainMenu, + Loading, + Playing, + PauseMenu, + } currentState = Playing; + float mouseXDelta, mouseYDelta; + float deltaTime; + float absTime; + + void RenderWorld(); + + void HandleMouseCapture(); + + void HandleEvents(); + + void InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle); + + void InitGlew(); + + void SetMouseCapture(bool IsCaptured); + + void PrepareToRendering(); + + void RenderFrame(); + + unsigned int width(); + + unsigned int height(); + + void UpdateChunksToRender(); + + void UpdateGameState(); + + void UpdateSections(); + + std::thread gameStateLoopThread; + std::thread sectionUpdateLoopThread; + + Shader *shader; + //Cube verticies, Cube VAO, Cube UVs, TextureIndexes UboTextureIndexes, TextureData UboTextureIndexes, TextureData2 UboTextureIndexes, Blocks VBO, Models VBO, Line VAO, Lines VBO + bool isRendersShouldBeCreated=false; + std::condition_variable waitRendersCreated; + std::vector<Vector> renders; + std::mutex toRenderMutex; + std::vector<Vector> toRender; + std::map<Vector, RenderSection> availableChunks; + std::mutex availableChunksMutex; + + int ChunkDistance = 3; + + RenderState renderState; + + double tickRate = 0; + double sectionRate = 0; + +public: + Core(); + + ~Core(); + + void Exec(); +}; diff --git a/src/core/Event.cpp b/src/core/Event.cpp new file mode 100644 index 0000000..10b2eaa --- /dev/null +++ b/src/core/Event.cpp @@ -0,0 +1,76 @@ +#include <core/Event.hpp> +#include <easylogging++.h> + +std::queue <Event> EventAgregator::eventsToHandle; +std::mutex EventAgregator::queueMutex; +bool EventAgregator::isStarted = false; +std::vector<EventListener*> EventAgregator::listeners; +std::mutex EventAgregator::listenersMutex; + +void EventAgregator::EventHandlingLoop() { + while (true) { + queueMutex.lock(); + if (!eventsToHandle.empty()) { + auto queue = eventsToHandle; + while (!eventsToHandle.empty()) + eventsToHandle.pop(); + queueMutex.unlock(); + + while (!queue.empty()) { + auto event = queue.front(); + listenersMutex.lock(); + for (auto& listener : listeners) { + LOG(INFO)<<"Listener notified about event"; + listener->PushEvent(event); + } + listenersMutex.unlock(); + queue.pop(); + } + + queueMutex.lock(); + } + queueMutex.unlock(); + } +} + +void EventAgregator::RegisterListener(EventListener &listener) { + listenersMutex.lock(); + LOG(INFO)<<"Registered handler "<<&listener; + listeners.push_back(&listener); + listenersMutex.unlock(); +} + +void EventAgregator::UnregisterListener(EventListener &listener) { + listenersMutex.lock(); + LOG(INFO)<<"Unregistered handler "<<&listener; + listeners.erase(std::find(listeners.begin(), listeners.end(), &listener)); + listenersMutex.unlock(); +} + + + +EventListener::EventListener() { + EventAgregator::RegisterListener(*this); +} + +EventListener::~EventListener() { + EventAgregator::UnregisterListener(*this); +} + +void EventListener::PushEvent(Event event) { + eventsMutex.lock(); + LOG(INFO)<<"Pushed event to queue"; + events.push(event); + eventsMutex.unlock(); +} + +/*void EventListener::RegisterHandler(EventType type, std::function<void(void*)> handler) { + handlers[type] = handler; +}*/ + +bool EventListener::IsEventsQueueIsNotEmpty() { + eventsMutex.lock(); + bool value = !events.empty(); + eventsMutex.unlock(); + return value; +}
\ No newline at end of file diff --git a/src/core/Event.hpp b/src/core/Event.hpp new file mode 100644 index 0000000..cfa990a --- /dev/null +++ b/src/core/Event.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include <queue> +#include <map> +#include <thread> +#include <mutex> +#include <condition_variable> +#include <chrono> +#include <variant> +#include <functional> + +#include <Vector.hpp> + +enum class EventType { + Echo, + ChunkChanged, +}; + +struct EchoData { + std::chrono::time_point<std::chrono::high_resolution_clock> time; +}; + +struct ChunkChangedData { + Vector chunkPosition; +}; + +using EventData = std::variant<EchoData, ChunkChangedData>; + +struct Event { + EventType type; + EventData data; +}; + +class EventListener { + friend class EventAgregator; + + using HandlerFunc = std::function<void(EventData)>; + + std::map<EventType, HandlerFunc> handlers; //TODO: There must be more elegant solution than std::variant of all data + + std::mutex eventsMutex; + + std::queue<Event> events; + + void PushEvent(Event event); + +public: + EventListener(); + ~EventListener(); + bool IsEventsQueueIsNotEmpty(); + + void RegisterHandler(EventType type, HandlerFunc handler) { + handlers[type] = handler; + } + + void HandleEvent() { + eventsMutex.lock(); + if (events.empty()) { + eventsMutex.unlock(); + return; + } + Event event = events.front(); + events.pop(); + eventsMutex.unlock(); + auto function = handlers[event.type]; + function(event.data); + } +}; + +class EventAgregator { + friend EventListener; + + EventAgregator() = default; + static std::queue<Event> eventsToHandle; + static std::mutex queueMutex; + static bool isStarted; + static std::vector<EventListener *> listeners; + static std::mutex listenersMutex; + + static void EventHandlingLoop(); + + static void RegisterListener(EventListener &listener); + static void UnregisterListener(EventListener &listener); + +public: + static void PushEvent(EventType type, EventData data) { + if (!isStarted) { + isStarted = true; + std::thread(&EventAgregator::EventHandlingLoop).detach(); + } + Event event; + event.type = type; + event.data = data; + eventsToHandle.push(event); + } +};
\ No newline at end of file |