summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AssetManager.cpp185
-rw-r--r--src/AssetManager.hpp (renamed from src/core/AssetManager.hpp)6
-rw-r--r--src/Block.cpp17
-rw-r--r--src/Block.hpp (renamed from src/world/Block.hpp)0
-rw-r--r--src/Collision.cpp28
-rw-r--r--src/Collision.hpp (renamed from src/world/Collision.hpp)0
-rw-r--r--src/Core.cpp59
-rw-r--r--src/Core.hpp23
-rw-r--r--src/Event.cpp (renamed from src/core/Event.cpp)112
-rw-r--r--src/Event.hpp (renamed from src/core/Event.hpp)76
-rw-r--r--src/GameState.cpp383
-rw-r--r--src/GameState.hpp (renamed from src/world/GameState.hpp)6
-rw-r--r--src/Nbt.hpp516
-rw-r--r--src/Network.cpp224
-rw-r--r--src/Network.hpp (renamed from src/network/Network.hpp)0
-rw-r--r--src/NetworkClient.cpp93
-rw-r--r--src/NetworkClient.hpp (renamed from src/network/NetworkClient.hpp)2
-rw-r--r--src/Packet.hpp (renamed from src/network/Packet.hpp)2
-rw-r--r--src/Render.cpp137
-rw-r--r--src/Render.hpp32
-rw-r--r--src/Renderer.cpp15
-rw-r--r--src/Renderer.hpp18
-rw-r--r--src/RendererSection.cpp348
-rw-r--r--src/RendererSection.hpp49
-rw-r--r--src/RendererWorld.cpp1
-rw-r--r--src/RendererWorld.hpp7
-rw-r--r--src/Section.cpp147
-rw-r--r--src/Section.hpp (renamed from src/world/Section.hpp)6
-rw-r--r--src/Shader.cpp115
-rw-r--r--src/Shader.hpp (renamed from src/graphics/Shader.hpp)0
-rw-r--r--src/Socket.cpp29
-rw-r--r--src/Socket.hpp (renamed from src/network/Socket.hpp)0
-rw-r--r--src/Stream.cpp348
-rw-r--r--src/Stream.hpp (renamed from src/network/Stream.hpp)6
-rw-r--r--src/Texture.cpp37
-rw-r--r--src/Texture.hpp (renamed from src/graphics/Texture.hpp)0
-rw-r--r--src/Utility.cpp73
-rw-r--r--src/Utility.hpp65
-rw-r--r--src/World.cpp129
-rw-r--r--src/World.hpp (renamed from src/world/World.hpp)9
-rw-r--r--src/core/AssetManager.cpp2
-rw-r--r--src/core/Core.cpp166
-rw-r--r--src/core/Core.hpp95
-rw-r--r--src/graphics/Gui.hpp8
-rw-r--r--src/graphics/RenderSection.cpp54
-rw-r--r--src/graphics/RenderSection.hpp52
-rw-r--r--src/graphics/Widget.hpp8
-rw-r--r--src/main.cpp7
-rw-r--r--src/network/Network.cpp8
-rw-r--r--src/network/Stream.cpp9
-rw-r--r--src/world/GameState.cpp2
-rw-r--r--src/world/Section.cpp50
52 files changed, 2722 insertions, 1042 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp
new file mode 100644
index 0000000..351a118
--- /dev/null
+++ b/src/AssetManager.cpp
@@ -0,0 +1,185 @@
+#include <fstream>
+#include "AssetManager.hpp"
+
+//const fs::path pathToAssets = "./assets/";
+//const fs::path pathToAssetsList = "./items.json";
+//const fs::path pathToTextureIndex = "./textures.json";
+const std::string pathToAssetsList = "./items.json";
+const std::string pathToTextureIndex = "./textures.json";
+
+AssetManager::AssetManager() {
+ LoadIds();
+ LoadTextureResources();
+}
+
+void AssetManager::LoadIds() {
+ std::ifstream in(pathToAssetsList);
+ nlohmann::json index;
+ in >> index;
+ for (auto &it:index) {
+ int id = it["type"].get<int>();
+ int state = it["meta"].get<int>();
+ std::string blockName = it["text_type"].get<std::string>();
+ assetIds[blockName] = Block(id, state);
+ }
+ LOG(INFO) << "Loaded " << assetIds.size() << " ids";
+}
+
+AssetManager::~AssetManager() {
+ delete textureAtlas;
+}
+
+//TODO: This function must be replaced with runtime texture atlas generating
+void AssetManager::LoadTextureResources() {
+ std::ifstream in(pathToTextureIndex);
+ nlohmann::json index;
+ in >> index;
+ std::string filename = index["meta"]["image"].get<std::string>();
+ float textureWidth = index["meta"]["size"]["w"].get<int>();
+ float textureHeight = index["meta"]["size"]["h"].get<int>();
+ for (auto &it:index["frames"]) {
+ auto frame = it["frame"];
+ TextureCoordinates coord;
+ coord.x = frame["x"].get<int>() / textureWidth;
+ coord.y = frame["y"].get<int>() / textureHeight;
+ coord.w = frame["w"].get<int>() / textureWidth;
+ coord.h = frame["h"].get<int>() / textureHeight;
+ std::string assetName = it["filename"].get<std::string>();
+ assetName.insert(0, "minecraft/textures/");
+ assetName.erase(assetName.length() - 4);
+ assetTextures[assetName] = coord;
+ }
+
+ textureAtlas = new Texture(filename);
+ LOG(INFO) << "Texture atlas id is " << textureAtlas->texture;
+}
+
+TextureCoordinates AssetManager::GetTextureByAssetName(std::string AssetName) {
+ if (assetTextures.find(AssetName) != assetTextures.end())
+ return assetTextures[AssetName];
+ else
+ return TextureCoordinates{-1, -1, -1, -1};
+}
+
+std::string AssetManager::GetTextureAssetNameByBlockId(BlockTextureId block) {
+ //Block sides: 0 - bottom, 1 - top, 2 - north, 3 - south, 4 - west, 5 - east 6 - every side
+ const std::map<BlockTextureId, std::string> lookupTable = {
+ {BlockTextureId(0, 0), "minecraft/textures/blocks/air"},
+ {BlockTextureId(1, 0), "minecraft/textures/blocks/stone"},
+ {BlockTextureId(1, 1), "minecraft/textures/blocks/stone_granite"},
+
+ {BlockTextureId(2, 0, 0), "minecraft/textures/blocks/dirt"},
+ {BlockTextureId(2, 0, 1), "minecraft/textures/blocks/grass_top"},
+ {BlockTextureId(2, 0, 2), "minecraft/textures/blocks/grass_side"},
+ {BlockTextureId(2, 0, 3), "minecraft/textures/blocks/grass_side"},
+ {BlockTextureId(2, 0, 4), "minecraft/textures/blocks/grass_side"},
+ {BlockTextureId(2, 0, 5), "minecraft/textures/blocks/grass_side"},
+
+ {BlockTextureId(3, 0), "minecraft/textures/blocks/dirt"},
+ {BlockTextureId(4, 0), "minecraft/textures/blocks/cobblestone"},
+ {BlockTextureId(5, 0), "minecraft/textures/blocks/planks"},
+
+ {BlockTextureId(7, 0), "minecraft/textures/blocks/bedrock"},
+
+ {BlockTextureId(17, 0, 0), "minecraft/textures/blocks/log_oak_top"},
+ {BlockTextureId(17, 0, 1), "minecraft/textures/blocks/log_oak_top"},
+ {BlockTextureId(17, 0, 2), "minecraft/textures/blocks/log_oak"},
+ {BlockTextureId(17, 0, 3), "minecraft/textures/blocks/log_oak"},
+ {BlockTextureId(17, 0, 4), "minecraft/textures/blocks/log_oak"},
+ {BlockTextureId(17, 0, 5), "minecraft/textures/blocks/log_oak"},
+
+ {BlockTextureId(17, 1, 0), "minecraft/textures/blocks/log_spruce_top"},
+ {BlockTextureId(17, 1, 1), "minecraft/textures/blocks/log_spruce_top"},
+ {BlockTextureId(17, 1, 2), "minecraft/textures/blocks/log_spruce"},
+ {BlockTextureId(17, 1, 3), "minecraft/textures/blocks/log_spruce"},
+ {BlockTextureId(17, 1, 4), "minecraft/textures/blocks/log_spruce"},
+ {BlockTextureId(17, 1, 5), "minecraft/textures/blocks/log_spruce"},
+
+ {BlockTextureId(17, 2, 0), "minecraft/textures/blocks/log_birch_top"},
+ {BlockTextureId(17, 2, 1), "minecraft/textures/blocks/log_birch_top"},
+ {BlockTextureId(17, 2, 2), "minecraft/textures/blocks/log_birch"},
+ {BlockTextureId(17, 2, 3), "minecraft/textures/blocks/log_birch"},
+ {BlockTextureId(17, 2, 4), "minecraft/textures/blocks/log_birch"},
+ {BlockTextureId(17, 2, 5), "minecraft/textures/blocks/log_birch"},
+
+ {BlockTextureId(17, 3, 0), "minecraft/textures/blocks/log_jungle_top"},
+ {BlockTextureId(17, 3, 1), "minecraft/textures/blocks/log_jungle_top"},
+ {BlockTextureId(17, 3, 2), "minecraft/textures/blocks/log_jungle"},
+ {BlockTextureId(17, 3, 3), "minecraft/textures/blocks/log_jungle"},
+ {BlockTextureId(17, 3, 4), "minecraft/textures/blocks/log_jungle"},
+ {BlockTextureId(17, 3, 5), "minecraft/textures/blocks/log_jungle"},
+
+ {BlockTextureId(18, 0), "minecraft/textures/blocks/leaves_oak"},
+ {BlockTextureId(18, 1), "minecraft/textures/blocks/leaves_spruce"},
+ {BlockTextureId(18, 2), "minecraft/textures/blocks/leaves_birch"},
+ {BlockTextureId(18, 3), "minecraft/textures/blocks/leaves_jungle"},
+
+ {BlockTextureId(61, 0, 0), "minecraft/textures/blocks/furnace_side"},
+ {BlockTextureId(61, 0, 1), "minecraft/textures/blocks/furnace_top"},
+ {BlockTextureId(61, 0, 2), "minecraft/textures/blocks/furnace_front_off"},
+ {BlockTextureId(61, 0, 3), "minecraft/textures/blocks/furnace_side"},
+ {BlockTextureId(61, 0, 4), "minecraft/textures/blocks/furnace_side"},
+ {BlockTextureId(61, 0, 5), "minecraft/textures/blocks/furnace_side"},
+
+ {BlockTextureId(62, 0, 0), "minecraft/textures/blocks/furnace_side"},
+ {BlockTextureId(62, 0, 1), "minecraft/textures/blocks/furnace_top"},
+ {BlockTextureId(62, 0, 2), "minecraft/textures/blocks/furnace_front_on"},
+ {BlockTextureId(62, 0, 3), "minecraft/textures/blocks/furnace_side"},
+ {BlockTextureId(62, 0, 4), "minecraft/textures/blocks/furnace_side"},
+ {BlockTextureId(62, 0, 5), "minecraft/textures/blocks/furnace_side"},
+
+
+ {BlockTextureId(31, 0), "minecraft/textures/blocks/deadbush"},
+ {BlockTextureId(31, 1), "minecraft/textures/blocks/tallgrass"},
+ {BlockTextureId(31, 2), "minecraft/textures/blocks/fern"},
+ };
+ auto ret = lookupTable.find(block);
+ if (ret == lookupTable.end())
+ return "";
+ else
+ return ret->second;
+}
+
+GLuint AssetManager::GetTextureAtlas() {
+ return textureAtlas->texture;
+}
+
+TextureCoordinates AssetManager::GetTextureByBlock(BlockTextureId block) {
+ std::string assetName = this->GetTextureAssetNameByBlockId(block);
+ return this->GetTextureByAssetName(assetName);
+}
+
+const std::map<BlockTextureId, glm::vec4> &AssetManager::GetTextureAtlasIndexes() {
+ if (!textureAtlasIndexes.empty())
+ return textureAtlasIndexes;
+
+ LOG(INFO) << "Initializing texture atlas...";
+ for (int id = 1; id < 128; id++) {
+ for (int state = 0; state < 16; state++) {
+ BlockTextureId blockTextureId(id, state, 6);
+ if (!this->GetTextureByBlock(blockTextureId) &&
+ !this->GetTextureByBlock(BlockTextureId(id, state, 0))) {
+ continue;
+ }
+ if (this->GetTextureByBlock(blockTextureId)) {
+ for (int i = 0; i < 6; i++) {
+ TextureCoordinates tc = this->GetTextureByBlock(BlockTextureId(id, state, 6));
+ textureAtlasIndexes[BlockTextureId(id, state, i)] = glm::vec4(tc.x, tc.y, tc.w, tc.h);
+ }
+ } else {
+ for (int i = 0; i < 6; i++) {
+ TextureCoordinates tc = this->GetTextureByBlock(BlockTextureId(id, state, i));
+ textureAtlasIndexes[BlockTextureId(id, state, i)] = glm::vec4(tc.x, tc.y, tc.w, tc.h);
+ }
+ }
+ }
+ }
+ LOG(INFO) << "Created " << textureAtlasIndexes.size() << " texture indexes";
+
+ return textureAtlasIndexes;
+}
+
+AssetManager &AssetManager::Instance() {
+ static AssetManager assetManager;
+ return assetManager;
+}
diff --git a/src/core/AssetManager.hpp b/src/AssetManager.hpp
index 26c7eca..ba5546b 100644
--- a/src/core/AssetManager.hpp
+++ b/src/AssetManager.hpp
@@ -7,8 +7,8 @@
#include <glm/vec4.hpp>
#include <nlohmann/json.hpp>
-#include <world/Block.hpp>
-#include <graphics/Texture.hpp>
+#include "Block.hpp"
+#include "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) {}
@@ -72,4 +72,6 @@ public:
void LoadIds();
TextureCoordinates GetTextureByBlock(BlockTextureId block);
+
+ static AssetManager& Instance();
};
diff --git a/src/Block.cpp b/src/Block.cpp
new file mode 100644
index 0000000..e88068a
--- /dev/null
+++ b/src/Block.cpp
@@ -0,0 +1,17 @@
+#include "Block.hpp"
+
+Block::~Block() {}
+
+Block::Block(unsigned short id, unsigned char state) : id(id), state(state) {}
+
+Block::Block() : id(0), state(0) {}
+
+bool operator<(const Block &lhs, const Block &rhs) {
+ if (lhs.id < rhs.id)
+ return true;
+ if (lhs.id == rhs.id) {
+ if (lhs.state != rhs.state)
+ return lhs.state < rhs.state;
+ }
+ return false;
+}
diff --git a/src/world/Block.hpp b/src/Block.hpp
index 2f823fe..2f823fe 100644
--- a/src/world/Block.hpp
+++ b/src/Block.hpp
diff --git a/src/Collision.cpp b/src/Collision.cpp
new file mode 100644
index 0000000..4f2c837
--- /dev/null
+++ b/src/Collision.cpp
@@ -0,0 +1,28 @@
+#include "Collision.hpp"
+
+bool TestCollision(AABB first, AABB second) {
+ double firstXl = first.x;
+ double firstXr = first.x + first.w;
+
+ double firstYl = first.y;
+ double firstYr = first.y + first.h;
+
+ double firstZl = first.z;
+ double firstZr = first.z + first.l;
+
+
+ double secondXl = second.x;
+ double secondXr = second.x + second.w;
+
+ double secondYl = second.y;
+ double secondYr = second.y + second.h;
+
+ double secondZl = second.z;
+ double secondZr = second.z + second.l;
+
+ bool collidesOnX = firstXr >= secondXl && firstXl <= secondXr;
+ bool collidesOnY = firstYr >= secondYl && firstYl <= secondYr;
+ bool collidesOnZ = firstZr >= secondZl && firstZl <= secondZr;
+
+ return collidesOnX && collidesOnY && collidesOnZ;
+}
diff --git a/src/world/Collision.hpp b/src/Collision.hpp
index b88fbf7..b88fbf7 100644
--- a/src/world/Collision.hpp
+++ b/src/Collision.hpp
diff --git a/src/Core.cpp b/src/Core.cpp
new file mode 100644
index 0000000..3a89c07
--- /dev/null
+++ b/src/Core.cpp
@@ -0,0 +1,59 @@
+#include "Core.hpp"
+#include "NetworkClient.hpp"
+
+Core::Core() {
+ coreLoop = std::thread(&Core::ExecuteCoreLoop, this);
+ render = new Render(900, 480, "AltCraft");
+}
+
+Core::~Core() {
+ delete render;
+ coreLoop.join();
+}
+
+void Core::ExecuteRenderLoop() {
+ render->ExecuteRenderLoop();
+}
+
+void Core::ExecuteCoreLoop() {
+
+ EventListener events;
+ events.RegisterHandler(EventType::ConnectionSuccessfull, [](EventData eventData) {
+ GlobalAppStateData data = {GlobalState::Loading};
+ EventAgregator::PushEvent(EventType::GlobalAppState, EventData{data});
+ });
+ events.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) {
+ auto data = std::get<GlobalAppStateData>(eventData);
+ globalState = data.state;
+ });
+
+ while (globalState != GlobalState::Exiting) {
+ if (events.IsEventsQueueIsNotEmpty()) {
+ events.HandleEvent();
+ }
+ }
+}
+
+void Core::ExecuteNetworkLoop() {
+ NetworkClient *nc;
+ EventListener events;
+ bool isRunning = true;
+ events.RegisterHandler(EventType::ConnectToServer, [](EventData eventData) {
+ auto data = std::get<ConnectToServerData>(eventData);
+ try {
+ nc = new NetworkClient(data.address, data.port, "HelloOne", isRunning);
+ } catch (std::exception &e) {
+ GlobalAppStateData data{GlobalState::Exiting};
+ EventAgregator::PushEvent(EventType::GlobalAppState, data);
+ }
+ });
+ events.RegisterHandler(EventType::Disconnect, [nc](EventData eventData) {
+ delete nc;
+ nc = nullptr;
+ });
+
+ while (globalState != GlobalState::Exiting) {
+
+ }
+ delete nc;
+}
diff --git a/src/Core.hpp b/src/Core.hpp
new file mode 100644
index 0000000..3c2d8da
--- /dev/null
+++ b/src/Core.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <thread>
+#include <memory>
+
+#include "Render.hpp"
+#include "Event.hpp"
+
+class Core {
+ std::thread coreLoop;
+ std::thread networkLoop;
+ Render* render;
+
+ GlobalState globalState = GlobalState::InitialLoading;
+
+ void ExecuteCoreLoop();
+ void ExecuteNetworkLoop();
+public:
+ Core();
+ ~Core();
+
+ void ExecuteRenderLoop();
+}; \ No newline at end of file
diff --git a/src/core/Event.cpp b/src/Event.cpp
index 10b2eaa..ff16178 100644
--- a/src/core/Event.cpp
+++ b/src/Event.cpp
@@ -1,4 +1,4 @@
-#include <core/Event.hpp>
+#include "Event.hpp"
#include <easylogging++.h>
std::queue <Event> EventAgregator::eventsToHandle;
@@ -7,6 +7,72 @@ bool EventAgregator::isStarted = false;
std::vector<EventListener*> EventAgregator::listeners;
std::mutex EventAgregator::listenersMutex;
+EventListener::EventListener() {
+ EventAgregator::RegisterListener(*this);
+}
+
+EventListener::~EventListener() {
+ EventAgregator::UnregisterListener(*this);
+}
+
+void EventListener::PushEvent(Event event) {
+ eventsMutex.lock();
+ events.push(event);
+ eventsMutex.unlock();
+}
+
+bool EventListener::IsEventsQueueIsNotEmpty() {
+ eventsMutex.lock();
+ bool value = !events.empty();
+ eventsMutex.unlock();
+ return value;
+}
+
+
+void EventListener::RegisterHandler(EventType type, EventListener::HandlerFunc handler) {
+ handlers[type] = handler;
+}
+
+void EventListener::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);
+}
+
+
+
+void EventAgregator::RegisterListener(EventListener &listener) {
+ listenersMutex.lock();
+ LOG(WARNING)<<"Registered handler "<<&listener;
+ listeners.push_back(&listener);
+ listenersMutex.unlock();
+}
+
+void EventAgregator::UnregisterListener(EventListener &listener) {
+ listenersMutex.lock();
+ LOG(WARNING)<<"Unregistered handler "<<&listener;
+ listeners.erase(std::find(listeners.begin(), listeners.end(), &listener));
+ listenersMutex.unlock();
+}
+
+void EventAgregator::PushEvent(EventType type, EventData data) {
+ Event event;
+ event.type = type;
+ event.data = data;
+ eventsToHandle.push(event);
+ if (!isStarted) {
+ isStarted = true;
+ std::thread(&EventAgregator::EventHandlingLoop).detach();
+ }
+}
+
void EventAgregator::EventHandlingLoop() {
while (true) {
queueMutex.lock();
@@ -20,7 +86,7 @@ void EventAgregator::EventHandlingLoop() {
auto event = queue.front();
listenersMutex.lock();
for (auto& listener : listeners) {
- LOG(INFO)<<"Listener notified about event";
+ LOG(ERROR)<<"Listener notified about event";
listener->PushEvent(event);
}
listenersMutex.unlock();
@@ -32,45 +98,3 @@ void EventAgregator::EventHandlingLoop() {
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/Event.hpp
index cfa990a..2d830a4 100644
--- a/src/core/Event.hpp
+++ b/src/Event.hpp
@@ -9,11 +9,18 @@
#include <variant>
#include <functional>
-#include <Vector.hpp>
+#include "Vector.hpp"
+#include "Packet.hpp"
enum class EventType {
Echo,
ChunkChanged,
+ ConnectToServer,
+ ConnectionSuccessfull,
+ GlobalAppState,
+ Disconnect,
+ SendPacket,
+ ReceivePacket,
};
struct EchoData {
@@ -24,7 +31,42 @@ struct ChunkChangedData {
Vector chunkPosition;
};
-using EventData = std::variant<EchoData, ChunkChangedData>;
+struct ConnectToServerData {
+ std::string address;
+ unsigned short port;
+};
+
+struct ConnectionSuccessfullData {
+
+};
+
+enum class GlobalState {
+ InitialLoading,
+ MainMenu,
+ Loading,
+ InGame,
+ PauseMenu,
+ Exiting,
+};
+
+struct GlobalAppStateData {
+ GlobalState state;
+};
+
+struct DisconnectData {
+
+};
+
+struct SendPacketData {
+ std::shared_ptr<Packet> packet;
+};
+
+struct ReceivePacketData {
+ std::shared_ptr<Packet> packet;
+};
+
+using EventData = std::variant<EchoData, ChunkChangedData, ConnectToServerData, ConnectionSuccessfullData,
+ GlobalAppStateData, DisconnectData, SendPacketData, ReceivePacketData>;
struct Event {
EventType type;
@@ -49,22 +91,9 @@ public:
~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);
- }
+ void RegisterHandler(EventType type, HandlerFunc handler);
+
+ void HandleEvent();
};
class EventAgregator {
@@ -83,14 +112,5 @@ class EventAgregator {
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);
- }
+ static void PushEvent(EventType type, EventData data);
}; \ No newline at end of file
diff --git a/src/GameState.cpp b/src/GameState.cpp
new file mode 100644
index 0000000..3ccff37
--- /dev/null
+++ b/src/GameState.cpp
@@ -0,0 +1,383 @@
+#include "GameState.hpp"
+
+GameState::GameState(NetworkClient *Net, bool &quit) : nc(Net), isRunning(quit) {
+ Front = glm::vec3(0.0f, 0.0f, -1.0f);
+ this->SetPosition(glm::vec3(0.0f, 0.0f, 3.0f));
+ this->WorldUp = glm::vec3(0.0f, 1.0f, 0.0f);
+ this->updateCameraVectors();
+}
+
+void GameState::Update(float deltaTime) {
+ if (g_IsGameStarted) {
+ std::chrono::steady_clock clock;
+ static auto timeOfPreviousSendedPacket(clock.now());
+ auto delta = clock.now() - timeOfPreviousSendedPacket;
+ using namespace std::chrono_literals;
+ if (delta >= 50ms) {
+ nc->SendPacket(std::make_shared<PacketPlayerPositionAndLookSB>(g_PlayerX, g_PlayerY, g_PlayerZ, g_PlayerYaw,
+ g_PlayerPitch, g_OnGround));
+ timeOfPreviousSendedPacket = clock.now();
+ }
+
+ const float gravity = -9.8f;
+ g_PlayerVelocityY += gravity * deltaTime;
+
+ bool isCollides = world.isPlayerCollides(g_PlayerX, g_PlayerY + g_PlayerVelocityY * deltaTime,
+ g_PlayerZ);
+ if (!isCollides) {
+ g_PlayerY += g_PlayerVelocityY * deltaTime;
+ g_OnGround = false;
+ } else {
+ g_PlayerVelocityY = 0;
+ if (g_OnGround == false) {
+ auto updatePacket = std::make_shared<PacketPlayerPosition>(g_PlayerX, g_PlayerY, g_PlayerZ, true);
+ nc->SendPacket(updatePacket);
+ }
+ g_OnGround = true;
+ }
+
+ isCollides = world.isPlayerCollides(g_PlayerX + g_PlayerVelocityX * deltaTime, g_PlayerY,
+ g_PlayerZ + g_PlayerVelocityZ * deltaTime);
+ if (!isCollides) {
+ g_PlayerX += g_PlayerVelocityX * deltaTime;
+ g_PlayerZ += g_PlayerVelocityZ * deltaTime;
+ }
+
+ const float AirResistance = 10.0f;
+ glm::vec3 vel(g_PlayerVelocityX, 0, g_PlayerVelocityZ);
+ glm::vec3 resistForce = -vel * AirResistance * deltaTime;
+ vel += resistForce;
+ g_PlayerVelocityX = vel.x;
+ g_PlayerVelocityZ = vel.z;
+ }
+
+
+ //Packet handling
+ auto ptr = nc->ReceivePacket();
+ while (ptr != nullptr) {
+ switch ((PacketNamePlayCB) ptr->GetPacketId()) {
+ case SpawnObject:
+ break;
+ case SpawnExperienceOrb:
+ break;
+ case SpawnGlobalEntity:
+ break;
+ case SpawnMob:
+ break;
+ case SpawnPainting:
+ break;
+ case SpawnPlayer:
+ break;
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+ case BlockChange:
+ break;
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+ case ChatMessageCB:
+ break;
+ case MultiBlockChange:
+ break;
+ case ConfirmTransactionCB:
+ break;
+ case CloseWindowCB:
+ break;
+ case OpenWindow:
+ break;
+ case WindowItems:
+ break;
+ case WindowProperty:
+ break;
+ case SetSlot:
+ break;
+ case SetCooldown:
+ break;
+ case PluginMessageCB:
+ break;
+ case NamedSoundEffect:
+ break;
+ case DisconnectPlay: {
+ auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr);
+ LOG(INFO) << "Disconnect reason: " << packet->Reason;
+ isRunning = false;
+ break;
+ }
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+ case UnloadChunk:
+ break;
+ case ChangeGameState:
+ break;
+ case KeepAliveCB:
+ LOG(WARNING) << "Receive KeepAlive packet in GameState handler";
+ break;
+ case ChunkData: {
+ auto packet = std::static_pointer_cast<PacketChunkData>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+ case Effect:
+ break;
+ case Particle:
+ break;
+ case JoinGame: {
+ auto packet = std::static_pointer_cast<PacketJoinGame>(ptr);
+ g_PlayerEid = packet->EntityId;
+ g_Gamemode = (packet->Gamemode & 0b11111011);
+ g_Dimension = packet->Dimension;
+ g_Difficulty = packet->Difficulty;
+ g_MaxPlayers = packet->MaxPlayers;
+ g_LevelType = packet->LevelType;
+ g_ReducedDebugInfo = packet->ReducedDebugInfo;
+ LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty
+ << ", Level Type is " << g_LevelType;
+ break;
+ }
+ case Map:
+ break;
+ case EntityRelativeMove:
+ break;
+ case EntityLookAndRelativeMove:
+ break;
+ case EntityLook:
+ break;
+ case Entity:
+ break;
+ case VehicleMove:
+ break;
+ case OpenSignEditor:
+ break;
+ case PlayerAbilitiesCB:
+ break;
+ case CombatEvent:
+ break;
+ case PlayerListItem:
+ break;
+ case PlayerPositionAndLookCB: {
+ auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr);
+ if ((packet->Flags & 0x10) != 0) {
+ g_PlayerPitch += packet->Pitch;
+ } else {
+ g_PlayerPitch = packet->Pitch;
+ };
+
+ if ((packet->Flags & 0x08) != 0) {
+ g_PlayerYaw += packet->Yaw;
+ } else {
+ g_PlayerYaw = packet->Yaw;
+ }
+
+ if ((packet->Flags & 0x01) != 0) {
+ g_PlayerX += packet->X;
+ } else {
+ g_PlayerX = packet->X;
+ }
+
+ if ((packet->Flags & 0x02) != 0) {
+ g_PlayerY += packet->Y;
+ } else {
+ g_PlayerY = packet->Y;
+ }
+
+ if ((packet->Flags & 0x04) != 0) {
+ g_PlayerZ += packet->Z;
+ } else {
+ g_PlayerZ = packet->Z;
+ }
+
+ //if (!g_IsGameStarted)
+ LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: "
+ << g_PlayerYaw << "," << g_PlayerPitch;
+
+ g_IsGameStarted = true;
+
+ auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+
+ nc->SendPacket(packetResponse);
+ nc->SendPacket(packetPerformRespawn);
+ break;
+ }
+ case UseBed:
+ break;
+ case UnlockRecipes:
+ break;
+ case DestroyEntities:
+ break;
+ case RemoveEntityEffect:
+ break;
+ case ResourcePackSend:
+ break;
+ case Respawn:
+ break;
+ case EntityHeadLook:
+ break;
+ case SelectAdvancementTab:
+ break;
+ case WorldBorder:
+ break;
+ case Camera:
+ break;
+ case HeldItemChangeCB:
+ break;
+ case DisplayScoreboard:
+ break;
+ case EntityMetadata:
+ break;
+ case AttachEntity:
+ break;
+ case EntityVelocity:
+ break;
+ case EntityEquipment:
+ break;
+ case SetExperience:
+ break;
+ case UpdateHealth: {
+ auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr);
+ g_PlayerHealth = packet->Health;
+ if (g_PlayerHealth <= 0) {
+ LOG(INFO) << "Player is dead. Respawning...";
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+ nc->SendPacket(packetPerformRespawn);
+ }
+ break;
+ }
+ case ScoreboardObjective:
+ break;
+ case SetPassengers:
+ break;
+ case Teams:
+ break;
+ case UpdateScore:
+ break;
+ case SpawnPosition: {
+ auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr);
+ g_SpawnPosition = packet->Location;
+ LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << ","
+ << g_SpawnPosition.GetZ();
+ break;
+ }
+ case TimeUpdate:
+ break;
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+ case EntityTeleport:
+ break;
+ case Advancements:
+ break;
+ case EntityProperties:
+ break;
+ case EntityEffect:
+ break;
+ }
+ ptr = nc->ReceivePacket();
+ }
+}
+
+void GameState::HandleMovement(GameState::Direction direction, float deltaTime) {
+ const float PlayerSpeed = 40.0;
+ float velocity = PlayerSpeed * deltaTime;
+ glm::vec3 vel(g_PlayerVelocityX, g_PlayerVelocityY, g_PlayerVelocityZ);
+ glm::vec3 front(cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())), 0,
+ sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch())));
+ front = glm::normalize(front);
+ glm::vec3 right = glm::normalize(glm::cross(front, this->WorldUp));
+ switch (direction) {
+ case FORWARD:
+ vel += front * velocity;
+ break;
+ case BACKWARD:
+ vel -= front * velocity;
+ break;
+ case RIGHT:
+ vel += right * velocity;
+ break;
+ case LEFT:
+ vel -= right * velocity;
+ break;
+ case JUMP:
+ if (g_OnGround) {
+ vel.y += 5;
+ g_OnGround = false;
+ }
+ break;
+ }
+ g_PlayerVelocityX = vel.x;
+ g_PlayerVelocityY = vel.y;
+ g_PlayerVelocityZ = vel.z;
+}
+
+void GameState::HandleRotation(double yaw, double pitch) {
+ this->SetYaw(Yaw() + yaw);
+ this->SetPitch(Pitch() + pitch);
+ if (this->Pitch() > 89.0f)
+ this->SetPitch(89.0f);
+ if (this->Pitch() < -89.0f)
+ this->SetPitch(-89.0f);
+ this->updateCameraVectors();
+
+ auto updatePacket = std::make_shared<PacketPlayerLook>(g_PlayerYaw, g_PlayerPitch, g_OnGround);
+ nc->SendPacket(updatePacket);
+}
+
+glm::mat4 GameState::GetViewMatrix() {
+ auto pos = this->Position();
+ pos.y+=1.62;
+ return glm::lookAt(pos, pos + this->Front, this->Up);
+}
+
+void GameState::updateCameraVectors() {
+ glm::vec3 front;
+ front.x = cos(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()));
+ front.y = sin(glm::radians(this->Pitch()));
+ front.z = sin(glm::radians(this->Yaw())) * cos(glm::radians(this->Pitch()));
+ this->Front = glm::normalize(front);
+ this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));
+ this->Up = glm::normalize(glm::cross(this->Right, this->Front));
+}
+
+float GameState::Yaw() {
+ return g_PlayerYaw + 90;
+}
+
+float GameState::Pitch() {
+ return -g_PlayerPitch;
+}
+
+void GameState::SetYaw(float yaw) {
+ g_PlayerYaw = yaw - 90;
+}
+
+void GameState::SetPitch(float pitch) {
+ g_PlayerPitch = -pitch;
+}
+
+glm::vec3 GameState::Position() {
+ return glm::vec3(g_PlayerX, g_PlayerY, g_PlayerZ);
+}
+
+void GameState::SetPosition(glm::vec3 Position) {
+ g_PlayerX = Position.x;
+ g_PlayerY = Position.y;
+ g_PlayerZ = Position.z;
+}
diff --git a/src/world/GameState.hpp b/src/GameState.hpp
index 6741882..2ac7bc1 100644
--- a/src/world/GameState.hpp
+++ b/src/GameState.hpp
@@ -4,9 +4,9 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
-#include <world/World.hpp>
-#include <network/NetworkClient.hpp>
-#include <Vector.hpp>
+#include "World.hpp"
+#include "NetworkClient.hpp"
+#include "Vector.hpp"
class GameState {
NetworkClient *nc;
diff --git a/src/Nbt.hpp b/src/Nbt.hpp
deleted file mode 100644
index 03f5af0..0000000
--- a/src/Nbt.hpp
+++ /dev/null
@@ -1,516 +0,0 @@
-#pragma once
-
-#include <cstddef>
-#include <vector>
-#include <fstream>
-#include <zlib.h>
-
-#include <Utility.hpp>
-
-namespace nbt {
- enum TagType {
- End, //nullptr
- Byte, //int8_t
- Short, //int16_t
- Int, //int32_t
- Long, //int64_t
- Float, //float
- Double, //double
- ByteArray, //std::vector<signed char>
- String, //std::string
- List, //std::vector<NbtTag>
- Compound, //std::vector<NbtTag>
- IntArray, //std::vector<int32_t>
- Unknown, //dummy value
- };
-
- class NbtTag;
-
- typedef std::vector<NbtTag> compound_t;
-
- typedef std::string string_t;
-
- typedef std::vector<signed char> byteArray_t;
-
- typedef std::vector<int> intArray_t;
-
- class NbtTag {
- TagType type = Unknown;
- string_t name = "";
- unsigned char *data = nullptr;
- public:
- NbtTag(TagType type, string_t name) : type(type), name(name) {
- switch (type) {
- case End:
- data = nullptr;
- break;
- case Compound:
- data = (unsigned char *) new compound_t;
- break;
- case String:
- data = (unsigned char *) new string_t;
- break;
- case Int:
- data = (unsigned char *) new int32_t;
- break;
- case Long:
- data = (unsigned char *) new int64_t;
- break;
- case Byte:
- data = (unsigned char *) new int8_t;
- break;
- case Short:
- data = (unsigned char *) new int16_t;
- break;
- case Float:
- data = (unsigned char *) new float;
- break;
- case Double:
- data = (unsigned char *) new double;
- break;
- case ByteArray:
- data = (unsigned char *) new byteArray_t;
- break;
- case List:
- data = (unsigned char *) new compound_t;
- break;
- case IntArray:
- data = (unsigned char *) new intArray_t;
- }
- }
-
- NbtTag(const NbtTag &other) : type(other.type), name(other.name) {
- switch (type) {
- case Byte:
- data = (unsigned char *) new int8_t;
- *((int8_t *) data) = *((int8_t *) other.data);
- break;
- case Short:
- data = (unsigned char *) new int16_t;
- *((int16_t *) data) = *((int16_t *) other.data);
- break;
- case Int:
- data = (unsigned char *) new int32_t;
- *((int32_t *) data) = *((int32_t *) other.data);
- break;
- case Long:
- data = (unsigned char *) new int64_t;
- *((int64_t *) data) = *((int64_t *) other.data);
- break;
- case Float:
- data = (unsigned char *) new float;
- *((float *) data) = *((float *) other.data);
- break;
- case Double:
- data = (unsigned char *) new double;
- *((double *) data) = *((double *) other.data);
- break;
- case ByteArray:
- data = (unsigned char *) new byteArray_t;
- *((std::vector<signed char> *) data) = *((std::vector<signed char> *) other.data);
- break;
- case String:
- data = (unsigned char *) new string_t;
- *((std::string *) data) = *((std::string *) other.data);
- break;
- case List:
- data = (unsigned char *) new compound_t;
- *((std::vector<NbtTag> *) data) = *((std::vector<NbtTag> *) other.data);
- break;
- case Compound:
- data = (unsigned char *) new compound_t;
- *((std::vector<NbtTag> *) data) = *((std::vector<NbtTag> *) other.data);
- break;
- case IntArray:
- data = (unsigned char *) new intArray_t;
- *((std::vector<int> *) data) = *((std::vector<int> *) other.data);
- break;
- }
- }
-
- ~NbtTag() {
- switch (type) {
- case Byte:
- delete ((int8_t *) data);
- break;
- case Short:
- delete ((int16_t *) data);
- break;
- case Int:
- delete ((int32_t *) data);
- break;
- case Long:
- delete ((int64_t *) data);
- break;
- case Float:
- delete ((float *) data);
- break;
- case Double:
- delete ((double *) data);
- break;
- case ByteArray:
- delete ((std::vector<signed char> *) data);
- break;
- case String:
- delete ((std::string *) data);
- break;
- case List:
- delete ((std::vector<NbtTag> *) data);
- break;
- case Compound:
- delete ((std::vector<NbtTag> *) data);
- break;
- case IntArray:
- delete ((std::vector<int> *) data);
- break;
- }
- };
-
- void swap(NbtTag &other) {
- std::swap(other.data, data);
- std::swap(other.name, name);
- std::swap(other.type, type);
- }
-
- NbtTag &operator=(NbtTag other) {
- other.swap(*this);
- return *this;
- }
-
- TagType GetType() const {
- return type;
- }
-
- string_t GetName() const {
- return name;
- }
-
-
- string_t &GetString() {
- string_t &val = *reinterpret_cast<std::string *>(data);
- return val;
- }
-
- compound_t &GetCompound() {
- std::vector<NbtTag> &val = *reinterpret_cast<std::vector<NbtTag> *>(data);
- return val;
- }
-
- compound_t &GetList() {
- std::vector<NbtTag> &val = *reinterpret_cast<std::vector<NbtTag> *>(data);
- return val;
- }
-
- int64_t &GetLong() {
- int64_t &val = *reinterpret_cast<int64_t *>(data);
- return val;
- }
-
- float &GetFloat() {
- float &val = *reinterpret_cast<float *>(data);
- return val;
- }
-
- double &GetDouble() {
- double &val = *reinterpret_cast<double *>(data);
- return val;
- }
-
- byteArray_t &GetByteArray() {
- auto &val = *reinterpret_cast<byteArray_t *>(data);
- return val;
- }
-
- intArray_t &GetIntArray() {
- auto &val = *reinterpret_cast<intArray_t *>(data);
- return val;
- }
-
- int16_t &GetShort() {
- auto &val = *reinterpret_cast<int16_t *>(data);
- return val;
- }
-
- int32_t &GetInt() {
- auto &val = *reinterpret_cast<int32_t *>(data);
- return val;
- }
-
- int8_t &GetByte() {
- auto &val = *reinterpret_cast<int8_t *>(data);
- return val;
- }
- };
-
- NbtTag ParseTag(unsigned char *data, size_t &size, TagType listItemType = Unknown) {
- size = 0;
- TagType type;
- if (listItemType == Unknown) {
- type = (TagType) *data;
- data += 1;
- size += 1;
- } else
- type = listItemType;
- string_t name;
- if (listItemType == Unknown && type != End) {
- short nameLen = *((short *) data);
- data += 2;
- size += 2;
- endswap(&nameLen);
- name = std::string((char *) data, nameLen);
- data += nameLen;
- size += nameLen;
- }
- NbtTag tag(type, name);
- switch (type) {
- case Compound: {
- do {
- size_t s;
- tag.GetCompound().push_back(ParseTag(data, s));
- data += s;
- size += s;
- } while (tag.GetCompound().back().GetType() != End);
- tag.GetCompound().pop_back();
- return tag;
- }
- case String: {
- short len = *((short *) data);
- data += 2;
- size += 2;
- endswap(&len);
- string_t str((char *) data, len);
- data += len;
- size += len;
- tag.GetString() = str;
- return tag;
- }
- case End:
- return tag;
- case Long:
- tag.GetLong() = *((int64_t *) data);
- endswap(&tag.GetLong());
- data += 8;
- size += 8;
- return tag;
- case Short:
- tag.GetShort() = *((int16_t *) data);
- endswap(&tag.GetShort());
- data += 2;
- size += 2;
- return tag;
- case Float:
- tag.GetFloat() = *((float *) data);
- endswap(&tag.GetFloat());
- data += 4;
- size += 4;
- return tag;
- case Double:
- tag.GetDouble() = *((double *) data);
- endswap(&tag.GetDouble());
- data += 8;
- size += 8;
- return tag;
- case Byte:
- tag.GetByte() = *((int8_t *) data);
- endswap(&tag.GetByte());
- data += 1;
- size += 1;
- return tag;
- case Int:
- tag.GetInt() = *((int32_t *) data);
- endswap(&tag.GetInt());
- data += 4;
- size += 4;
- return tag;
- case List: {
- TagType listType = *((TagType *) data);
- data += 1;
- size += 1;
- int32_t listLength = *((int32_t *) data);
- endswap(&listLength);
- data += 4;
- size += 4;
- for (int i = 0; i < listLength; i++) {
- size_t s = 0;
- std::vector<NbtTag> &vec = tag.GetCompound();
- vec.push_back(ParseTag(data, s, listType));
- data += s;
- size += s;
- }
- return tag;
- }
- case ByteArray: {
- int32_t arrLength = *((int32_t *) data);
- endswap(&arrLength);
- data += 4;
- size += 4;
- for (int i = 0; i < arrLength; i++) {
- signed char val = (signed char) data[i];
- std::vector<signed char> &vec = tag.GetByteArray();
- vec.push_back(val);
- }
- data += arrLength;
- size += arrLength;
- return tag;
- }
- default:
- throw 13;
- }
- }
-
- NbtTag ParseTag(unsigned char *data, size_t *optionalSize = nullptr) {
- size_t s = 0;
- size_t &size = (optionalSize ? *optionalSize : s);
- return ParseTag(data, size);
- }
-
- std::vector<unsigned char> Decompress(unsigned char *data, size_t dataLen) {
- const size_t decompBuffSize = 1024 * 16;
- unsigned char *decompBuff = new unsigned char[decompBuffSize];
- std::vector<unsigned char> uncompressed;
- for (int i = 0; i < decompBuffSize; i++)
- decompBuff[i] = 0;
-
-
- z_stream stream;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.next_in = data;
- stream.avail_in = dataLen;
- stream.next_out = decompBuff;
- stream.avail_out = decompBuffSize;
-
- if (inflateInit2(&stream, 15 + 32) != Z_OK) {
- delete[] decompBuff;
- throw 171;
- }
-
- int res;
- do {
- stream.avail_out = decompBuffSize;
-
- switch ((res = inflate(&stream, Z_NO_FLUSH))) {
- case Z_MEM_ERROR:
- throw 172;
- case Z_DATA_ERROR:
- throw 173;
- case Z_NEED_DICT:
- throw 174;
- }
-
- uncompressed.resize(uncompressed.size() + decompBuffSize);
- std::copy(decompBuff, decompBuff + decompBuffSize, uncompressed.end() - decompBuffSize);
- } while (stream.avail_out == 0);
- if (res != Z_STREAM_END)
- throw 175;
- if (inflateEnd(&stream) != Z_OK)
- throw 176;
- delete[] decompBuff;
- return uncompressed;
- }
-
- NbtTag ParseCompressed(unsigned char *data, size_t dataLen) {
- auto uncompressed = Decompress(data, dataLen);
- NbtTag root = ParseTag(uncompressed.data());
- return root;
- }
-
- NbtTag Parse(unsigned char *data, size_t dataLen) {
- bool isCompressed = *data != 10;
- if (isCompressed)
- return ParseCompressed(data, dataLen);
- else
- return ParseTag(data);
- }
-
- void PrintTree(NbtTag &tree, int deepness = 0, std::ostream &ostream = std::cout) {
- ostream << std::string(deepness, '\t') << "Tag ";
- switch (tree.GetType()) {
- case Byte:
- ostream << "byte";
- break;
- case Short:
- ostream << "short";
- break;
- case Int:
- ostream << "int";
- break;
- case Long:
- ostream << "long";
- break;
- case Float:
- ostream << "float";
- break;
- case Double:
- ostream << "double";
- break;
- case ByteArray:
- ostream << "byte array";
- break;
- case String:
- ostream << "string";
- break;
- case List:
- ostream << "list";
- break;
- case Compound:
- ostream << "compound";
- break;
- case IntArray:
- ostream << "int array";
- break;
- case End:
- ostream << "end";
- break;
- }
- if (tree.GetName().length() > 0)
- ostream << " (" << tree.GetName() << ")";
- ostream << ": ";
-
- if (tree.GetType() == Compound || tree.GetType() == List) {
- std::vector<NbtTag> &vec = (tree.GetType() == Compound ? tree.GetCompound() : tree.GetList());
- ostream << vec.size() << " entries {" << std::endl;
- for (auto it = vec.begin(); it != vec.end(); ++it) {
- PrintTree(*it, deepness + 1, std::cout);
- }
- ostream << std::string(deepness, '\t') << "}" << std::endl;
- return;
- } else {
- switch (tree.GetType()) {
- case Int:
- ostream << tree.GetInt();
- break;
- case String:
- ostream << "\"" << tree.GetString() << "\"";
- break;
- case Double:
- ostream << tree.GetDouble();
- break;
- case Float:
- ostream << tree.GetFloat();
- break;
- case Short:
- ostream << tree.GetShort();
- break;
- case Byte:
- ostream << (int) tree.GetByte();
- break;
- case Long:
- ostream << tree.GetLong();
- break;
- case ByteArray:
- ostream << "[" << tree.GetByteArray().size() << " bytes]: ";
- for (int i = 0; i < (tree.GetByteArray().size() > 10 ? 10 : tree.GetByteArray().size()); i++) {
- ostream << std::hex << "0x" << (tree.GetByteArray()[i] > 15 ? "" : "0")
- << (int) tree.GetByteArray()[i]
- << std::dec << " ";
- }
- break;
- case IntArray:
- break;
- }
- ostream << std::endl;
- }
- }
-} \ No newline at end of file
diff --git a/src/Network.cpp b/src/Network.cpp
new file mode 100644
index 0000000..dcdda10
--- /dev/null
+++ b/src/Network.cpp
@@ -0,0 +1,224 @@
+#include "Network.hpp"
+
+Network::Network(std::string address, unsigned short port) {
+ try {
+ socket = new Socket(address, port);
+ stream = new StreamSocket(socket);
+ } catch (std::exception &e) {
+ LOG(FATAL)<<e.what();
+ }
+}
+
+Network::~Network() {
+ delete stream;
+ delete socket;
+}
+
+std::shared_ptr<Packet> Network::ReceivePacket(ConnectionState state) {
+ int packetSize = stream->ReadVarInt();
+ auto packetData = stream->ReadByteArray(packetSize);
+ StreamBuffer streamBuffer(packetData.data(), packetData.size());
+ int packetId = streamBuffer.ReadVarInt();
+ auto packet = ReceivePacketByPacketId(packetId, state, streamBuffer);
+ return packet;
+}
+
+void Network::SendPacket(Packet &packet) {
+ StreamCounter packetSize;
+ packetSize.WriteVarInt(packet.GetPacketId());
+ packet.ToStream(&packetSize);
+ stream->WriteVarInt(packetSize.GetCountedSize());
+ stream->WriteVarInt(packet.GetPacketId());
+ packet.ToStream(stream);
+}
+
+std::shared_ptr<Packet> Network::ReceivePacketByPacketId(int packetId, ConnectionState state, StreamInput &stream) {
+ std::shared_ptr<Packet> packet(nullptr);
+ switch (state) {
+ case Handshaking:
+ switch (packetId) {
+ case PacketNameHandshakingCB::Handshake:
+ packet = std::make_shared<PacketHandshake>();
+ break;
+ }
+ case Login:
+ switch (packetId) {
+ case PacketNameLoginCB::LoginSuccess:
+ packet = std::make_shared<PacketLoginSuccess>();
+ break;
+ }
+ break;
+ case Play:
+ packet = ParsePacketPlay((PacketNamePlayCB) packetId);
+ break;
+ case Status:
+ break;
+ }
+ if (packet.get() != nullptr)
+ packet->FromStream(&stream);
+ return packet;
+}
+
+std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) {
+ switch (id) {
+ case SpawnObject:
+ break;
+ case SpawnExperienceOrb:
+ break;
+ case SpawnGlobalEntity:
+ break;
+ case SpawnMob:
+ break;
+ case SpawnPainting:
+ break;
+ case SpawnPlayer:
+ break;
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+ case BlockChange:
+ break;
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+ case ChatMessageCB:
+ break;
+ case MultiBlockChange:
+ break;
+ case ConfirmTransactionCB:
+ break;
+ case CloseWindowCB:
+ break;
+ case OpenWindow:
+ break;
+ case WindowItems:
+ break;
+ case WindowProperty:
+ break;
+ case SetSlot:
+ break;
+ case SetCooldown:
+ break;
+ case PluginMessageCB:
+ break;
+ case NamedSoundEffect:
+ break;
+ case DisconnectPlay:
+ return std::make_shared<PacketDisconnectPlay>();
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+ case UnloadChunk:
+ break;
+ case ChangeGameState:
+ break;
+ case KeepAliveCB:
+ return std::make_shared<PacketKeepAliveCB>();
+ case ChunkData:
+ return std::make_shared<PacketChunkData>();
+ case Effect:
+ break;
+ case Particle:
+ break;
+ case JoinGame:
+ return std::make_shared<PacketJoinGame>();
+ case Map:
+ break;
+ case EntityRelativeMove:
+ break;
+ case EntityLookAndRelativeMove:
+ break;
+ case EntityLook:
+ break;
+ case Entity:
+ break;
+ case VehicleMove:
+ break;
+ case OpenSignEditor:
+ break;
+ case PlayerAbilitiesCB:
+ break;
+ case CombatEvent:
+ break;
+ case PlayerListItem:
+ break;
+ case PlayerPositionAndLookCB:
+ return std::make_shared<PacketPlayerPositionAndLookCB>();
+ case UseBed:
+ break;
+ case DestroyEntities:
+ break;
+ case RemoveEntityEffect:
+ break;
+ case ResourcePackSend:
+ break;
+ case Respawn:
+ break;
+ case EntityHeadLook:
+ break;
+ case WorldBorder:
+ break;
+ case Camera:
+ break;
+ case HeldItemChangeCB:
+ break;
+ case DisplayScoreboard:
+ break;
+ case EntityMetadata:
+ break;
+ case AttachEntity:
+ break;
+ case EntityVelocity:
+ break;
+ case EntityEquipment:
+ break;
+ case SetExperience:
+ break;
+ case UpdateHealth:
+ return std::make_shared<PacketUpdateHealth>();
+ case ScoreboardObjective:
+ break;
+ case SetPassengers:
+ break;
+ case Teams:
+ break;
+ case UpdateScore:
+ break;
+ case SpawnPosition:
+ return std::make_shared<PacketSpawnPosition>();
+ case TimeUpdate:
+ break;
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+ case EntityTeleport:
+ break;
+ case EntityProperties:
+ break;
+ case EntityEffect:
+ break;
+ case UnlockRecipes:
+ break;
+ case SelectAdvancementTab:
+ break;
+ case Advancements:
+ break;
+ }
+ return nullptr;
+}
diff --git a/src/network/Network.hpp b/src/Network.hpp
index 1281289..1281289 100644
--- a/src/network/Network.hpp
+++ b/src/Network.hpp
diff --git a/src/NetworkClient.cpp b/src/NetworkClient.cpp
new file mode 100644
index 0000000..0b759e6
--- /dev/null
+++ b/src/NetworkClient.cpp
@@ -0,0 +1,93 @@
+#include "NetworkClient.hpp"
+
+NetworkClient::NetworkClient(std::string address, unsigned short port, std::string username, bool &quit)
+ : network(address, port), isRunning(quit) {
+ state = Handshaking;
+
+ PacketHandshake handshake;
+ handshake.protocolVersion = 335;
+ handshake.serverAddress = "127.0.0.1";
+ handshake.serverPort = 25565;
+ handshake.nextState = 2;
+ network.SendPacket(handshake);
+ state = Login;
+
+ PacketLoginStart loginStart;
+ loginStart.Username = "HelloOne";
+ network.SendPacket(loginStart);
+
+ auto response = std::static_pointer_cast<PacketLoginSuccess>(network.ReceivePacket(Login));
+ if (response->Username != username) {
+ throw std::logic_error("Received username is not sended username");
+ }
+
+ state = Play;
+
+ isActive = true;
+ std::thread thread(&NetworkClient::NetworkLoop, this);
+ std::swap(networkThread, thread);
+}
+
+NetworkClient::~NetworkClient() {
+ isActive = false;
+ networkThread.join();
+}
+
+std::shared_ptr<Packet> NetworkClient::ReceivePacket() {
+ if (toReceive.empty())
+ return std::shared_ptr<Packet>(nullptr);
+ toReceiveMutex.lock();
+ auto ret = toReceive.front();
+ toReceive.pop();
+ toReceiveMutex.unlock();
+ return ret;
+}
+
+void NetworkClient::SendPacket(std::shared_ptr<Packet> packet) {
+ toSendMutex.lock();
+ toSend.push(packet);
+ toSendMutex.unlock();
+}
+
+void NetworkClient::NetworkLoop() {
+ auto timeOfLastKeepAlivePacket = std::chrono::steady_clock::now();
+ el::Helpers::setThreadName("Network");
+ LOG(INFO) << "Network thread is started";
+ try {
+ while (isActive) {
+ toSendMutex.lock();
+ while (!toSend.empty()) {
+ if (toSend.front()!=nullptr)
+ network.SendPacket(*toSend.front());
+ toSend.pop();
+ }
+ toSendMutex.unlock();
+ auto packet = network.ReceivePacket(state);
+ if (packet.get() != nullptr) {
+ if (packet->GetPacketId() != PacketNamePlayCB::KeepAliveCB) {
+ toReceiveMutex.lock();
+ toReceive.push(packet);
+ toReceiveMutex.unlock();
+ } else {
+ timeOfLastKeepAlivePacket = std::chrono::steady_clock::now();
+ auto packetKeepAlive = std::static_pointer_cast<PacketKeepAliveCB>(packet);
+ auto packetKeepAliveSB = std::make_shared<PacketKeepAliveSB>(packetKeepAlive->KeepAliveId);
+ network.SendPacket(*packetKeepAliveSB);
+ }
+ }
+ using namespace std::chrono_literals;
+ if (std::chrono::steady_clock::now() - timeOfLastKeepAlivePacket > 20s) {
+ auto disconnectPacket = std::make_shared<PacketDisconnectPlay>();
+ disconnectPacket->Reason = "Timeout";
+ toReceiveMutex.lock();
+ toReceive.push(disconnectPacket);
+ toReceiveMutex.unlock();
+ break;
+ }
+ }
+ } catch (std::exception &e) {
+ LOG(ERROR) << "Exception catched in NetworkLoop: " << e.what();
+ isRunning = false;
+ }
+ LOG(INFO) << "Network thread is stopped";
+}
diff --git a/src/network/NetworkClient.hpp b/src/NetworkClient.hpp
index 22b1b22..cf41f91 100644
--- a/src/network/NetworkClient.hpp
+++ b/src/NetworkClient.hpp
@@ -4,7 +4,7 @@
#include <queue>
#include <mutex>
-#include <network/Network.hpp>
+#include "Network.hpp"
class NetworkClient {
Network network;
diff --git a/src/network/Packet.hpp b/src/Packet.hpp
index 685e3da..d615332 100644
--- a/src/network/Packet.hpp
+++ b/src/Packet.hpp
@@ -2,7 +2,7 @@
#include <easylogging++.h>
-#include <network/Stream.hpp>
+#include "Stream.hpp"
enum PacketNameLoginSB {
LoginStart = 0x00,
diff --git a/src/Render.cpp b/src/Render.cpp
new file mode 100644
index 0000000..ebfbc20
--- /dev/null
+++ b/src/Render.cpp
@@ -0,0 +1,137 @@
+#include "Render.hpp"
+
+#include "Utility.hpp"
+#include "Shader.hpp"
+#include "AssetManager.hpp"
+#include "Event.hpp"
+
+Render::Render(unsigned int windowWidth, unsigned int windowHeight, std::string windowTitle) {
+ InitSfml(windowWidth, windowHeight, windowTitle);
+ glCheckError();
+ InitGlew();
+ glCheckError();
+ PrepareToRendering();
+ glCheckError();
+}
+
+Render::~Render() {
+ delete window;
+}
+
+void Render::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle) {
+ LOG(INFO) << "Creating window: " << WinWidth << "x" << WinHeight << " \"" << WinTitle << "\"";
+ sf::ContextSettings contextSetting;
+ contextSetting.majorVersion = 3;
+ contextSetting.minorVersion = 3;
+ contextSetting.attributeFlags = contextSetting.Core;
+ contextSetting.depthBits = 24;
+ window = new sf::Window(sf::VideoMode(WinWidth, WinHeight), WinTitle, sf::Style::Default, contextSetting);
+ glCheckError();
+ window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2,
+ sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2));
+ SetMouseCapture(false);
+}
+
+void Render::InitGlew() {
+ LOG(INFO) << "Initializing GLEW";
+ glewExperimental = GL_TRUE;
+ GLenum glewStatus = glewInit();
+ glCheckError();
+ if (glewStatus != GLEW_OK) {
+ LOG(FATAL) << "Failed to initialize GLEW: " << glewGetErrorString(glewStatus);
+ }
+ glViewport(0, 0, window->getSize().x, window->getSize().y);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glFrontFace(GL_CCW);
+ //glEnable(GL_BLEND);
+ //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glCheckError();
+}
+
+void Render::PrepareToRendering() {
+ shader = new Shader("./shaders/face.vs", "./shaders/face.fs");
+ shader->Use();
+
+ //TextureAtlas texture
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, AssetManager::Instance().GetTextureAtlas());
+ glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0);
+}
+
+void Render::RenderFrame() {
+ glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+ window->display();
+}
+
+void Render::HandleEvents() {
+ sf::Event event;
+ while (window->pollEvent(event)) {
+ switch (event.type) {
+ case sf::Event::Closed:
+ LOG(INFO) << "Received close event by window closing";
+ isRunning = false;
+ break;
+ case sf::Event::Resized:
+ glViewport(0, 0, window->getSize().x, window->getSize().y);
+ break;
+ case sf::Event::KeyPressed:
+ if (!window->hasFocus()) break;
+ switch (event.key.code) {
+ case sf::Keyboard::Escape:
+ LOG(INFO) << "Received close event by esc";
+ isRunning = false;
+ break;
+ case sf::Keyboard::T:
+ SetMouseCapture(!isMouseCaptured);
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (window->hasFocus()) {
+ /*if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) gameState->HandleMovement(GameState::FORWARD, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) gameState->HandleMovement(GameState::BACKWARD, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) gameState->HandleMovement(GameState::LEFT, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) gameState->HandleMovement(GameState::RIGHT, deltaTime);
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) gameState->HandleMovement(GameState::JUMP, deltaTime);*/
+ }
+}
+
+void Render::HandleMouseCapture() {
+ sf::Vector2i mousePos = sf::Mouse::getPosition(*window);
+ sf::Vector2i center = sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2);
+ sf::Mouse::setPosition(center, *window);
+ mouseXDelta = (mousePos - center).x, mouseYDelta = (center - mousePos).y;
+ const float Sensetivity = 0.7f;
+ //gameState->HandleRotation(mouseXDelta * Sensetivity, mouseYDelta * Sensetivity);
+}
+
+void Render::SetMouseCapture(bool IsCaptured) {
+ window->setMouseCursorVisible(!isMouseCaptured);
+ sf::Mouse::setPosition(sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2), *window);
+ isMouseCaptured = IsCaptured;
+ window->setMouseCursorVisible(!IsCaptured);
+}
+
+void Render::ExecuteRenderLoop() {
+ using namespace std::chrono_literals;
+ LoopExecutionTimeController timer(16ms);
+ while (isRunning) {
+ HandleEvents();
+ if (isMouseCaptured) HandleMouseCapture();
+ glCheckError();
+
+ RenderFrame();
+ timer.Update();
+ }
+ EventData data = GlobalAppStateData{GlobalState::Exiting};
+ EventAgregator::PushEvent(EventType::GlobalAppState,data);
+}
diff --git a/src/Render.hpp b/src/Render.hpp
new file mode 100644
index 0000000..636c4c7
--- /dev/null
+++ b/src/Render.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <SFML/Window.hpp>
+
+#include "Shader.hpp"
+
+class Render {
+ sf::Window *window;
+ bool isRunning=true;
+ bool isMouseCaptured = false;
+ float mouseXDelta, mouseYDelta;
+ Shader *shader;
+
+ void SetMouseCapture(bool IsCaptured);
+
+ void HandleMouseCapture();
+
+ void HandleEvents();
+
+ void InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle);
+
+ void InitGlew();
+
+ void RenderFrame();
+
+ void PrepareToRendering();
+public:
+ Render(unsigned int windowWidth, unsigned int windowHeight, std::string windowTitle);
+ ~Render();
+
+ void ExecuteRenderLoop();
+}; \ No newline at end of file
diff --git a/src/Renderer.cpp b/src/Renderer.cpp
new file mode 100644
index 0000000..5fc8c2e
--- /dev/null
+++ b/src/Renderer.cpp
@@ -0,0 +1,15 @@
+#include "Renderer.hpp"
+
+void RenderState::SetActiveVao(GLuint Vao) {
+ if (Vao != ActiveVao) {
+ glBindVertexArray(Vao);
+ ActiveVao = Vao;
+ }
+}
+
+void RenderState::SetActiveShader(GLuint Shader) {
+ if (Shader != ActiveShader) {
+ glUseProgram(Shader);
+ ActiveShader = Shader;
+ }
+} \ No newline at end of file
diff --git a/src/Renderer.hpp b/src/Renderer.hpp
new file mode 100644
index 0000000..81c5c50
--- /dev/null
+++ b/src/Renderer.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <GL/glew.h>
+
+class RenderState {
+ GLuint ActiveVao;
+ GLuint ActiveShader;
+public:
+ void SetActiveVao(GLuint Vao);
+ void SetActiveShader(GLuint Shader);
+};
+
+struct Renderer {
+ virtual ~Renderer() = default;
+ virtual void Render(RenderState& renderState) = 0;
+ virtual void PrepareResources() = 0;
+ virtual void PrepareRender() = 0;
+}; \ No newline at end of file
diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp
new file mode 100644
index 0000000..62a0dc7
--- /dev/null
+++ b/src/RendererSection.cpp
@@ -0,0 +1,348 @@
+#include "RendererSection.hpp"
+
+#include <thread>
+
+const GLfloat vertices[] = {
+ 0, 0, 0,
+ 1, 0, 1,
+ 1, 0, 0,
+
+ 0, 0, 0,
+ 0, 0, 1,
+ 1, 0, 1,
+};
+
+const GLfloat uv_coords[] = {
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+};
+
+const GLuint magicUniqueConstant = 88375;
+GLuint RendererSection::VboVertices = magicUniqueConstant;
+GLuint RendererSection::VboUvs = magicUniqueConstant;
+std::map<GLuint, int> RendererSection::refCounterVbo;
+std::map<GLuint, int> RendererSection::refCounterVao;
+
+
+RendererSection::RendererSection(World *world, Vector position) : sectionPosition(position), world(world) {
+ if (VboVertices == magicUniqueConstant) {
+ glGenBuffers(1, &VboVertices);
+ glGenBuffers(1, &VboUvs);
+
+ //Cube vertices
+ glBindBuffer(GL_ARRAY_BUFFER, VboVertices);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ //Cube UVs
+ glBindBuffer(GL_ARRAY_BUFFER, VboUvs);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW);
+
+ LOG(INFO) << "Created VBOs with vertices (" << VboVertices << ") and UVs (" << VboUvs
+ << ") for ordinary blocks";
+ }
+
+ glGenBuffers(1, &VboTextures);
+ if (refCounterVbo.find(VboTextures) == refCounterVbo.end())
+ refCounterVbo[VboTextures] = 0;
+ refCounterVbo[VboTextures]++;
+
+ glGenBuffers(1, &VboModels);
+ if (refCounterVbo.find(VboModels) == refCounterVbo.end())
+ refCounterVbo[VboModels] = 0;
+ refCounterVbo[VboModels]++;
+
+ glGenBuffers(1, &VboColors);
+ if (refCounterVbo.find(VboColors) == refCounterVbo.end())
+ refCounterVbo[VboColors] = 0;
+ refCounterVbo[VboColors]++;
+
+ glGenVertexArrays(1, &Vao);
+ if (refCounterVao.find(Vao) == refCounterVao.end())
+ refCounterVao[Vao] = 0;
+ refCounterVao[Vao]++;
+
+ glBindVertexArray(Vao);
+ {
+ //Cube vertices
+ GLuint VertAttribPos = 0;
+ glBindBuffer(GL_ARRAY_BUFFER, VboVertices);
+ glVertexAttribPointer(VertAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
+ glEnableVertexAttribArray(VertAttribPos);
+
+ //Cube UVs
+ GLuint UvAttribPos = 2;
+ glBindBuffer(GL_ARRAY_BUFFER, VboUvs);
+ glVertexAttribPointer(UvAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr);
+ glEnableVertexAttribArray(UvAttribPos);
+
+ //Textures
+ GLuint textureAttribPos = 7;
+ glBindBuffer(GL_ARRAY_BUFFER, VboTextures);
+ glVertexAttribPointer(textureAttribPos, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
+ glEnableVertexAttribArray(textureAttribPos);
+ glVertexAttribDivisor(textureAttribPos, 1);
+ glCheckError();
+
+ //Blocks models
+ GLuint matAttribPos = 8;
+ size_t sizeOfMat4 = 4 * 4 * sizeof(GLfloat);
+ glBindBuffer(GL_ARRAY_BUFFER, VboModels);
+ glVertexAttribPointer(matAttribPos + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr);
+ glVertexAttribPointer(matAttribPos + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (1 * 4 * sizeof(GLfloat)));
+ glVertexAttribPointer(matAttribPos + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (2 * 4 * sizeof(GLfloat)));
+ glVertexAttribPointer(matAttribPos + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (3 * 4 * sizeof(GLfloat)));
+ glEnableVertexAttribArray(matAttribPos + 0);
+ glEnableVertexAttribArray(matAttribPos + 1);
+ glEnableVertexAttribArray(matAttribPos + 2);
+ glEnableVertexAttribArray(matAttribPos + 3);
+ glVertexAttribDivisor(matAttribPos + 0, 1);
+ glVertexAttribDivisor(matAttribPos + 1, 1);
+ glVertexAttribDivisor(matAttribPos + 2, 1);
+ glVertexAttribDivisor(matAttribPos + 3, 1);
+
+ //Color
+ GLuint colorAttribPos = 12;
+ glBindBuffer(GL_ARRAY_BUFFER, VboColors);
+ glVertexAttribPointer(colorAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
+ glEnableVertexAttribArray(colorAttribPos);
+ glVertexAttribDivisor(colorAttribPos, 1);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ glBindVertexArray(0);
+ glCheckError();
+}
+
+RendererSection::~RendererSection() {
+ refCounterVbo[VboTextures]--;
+ refCounterVbo[VboModels]--;
+ refCounterVbo[VboColors]--;
+ refCounterVao[Vao]--;
+ if (refCounterVbo[VboTextures] <= 0)
+ glDeleteBuffers(1, &VboTextures);
+
+ if (refCounterVbo[VboModels] <= 0)
+ glDeleteBuffers(1, &VboTextures);
+ if (refCounterVbo[VboColors] <= 0)
+ glDeleteBuffers(1, &VboColors);
+
+ if (refCounterVao[Vao] <= 0)
+ glDeleteVertexArrays(1, &Vao);
+}
+
+void RendererSection::Render(RenderState &renderState) {
+ if (!isEnabled) return;
+ if (!models.empty()) {
+ PrepareRender();
+ }
+ renderState.SetActiveVao(Vao);
+ glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numOfFaces);
+ glCheckError();
+}
+
+Section *RendererSection::GetSection() {
+ return &world->GetSection(sectionPosition);
+}
+
+RendererSection::RendererSection(const RendererSection &other) {
+ this->world = other.world;
+ this->VboModels = other.VboModels;
+ this->VboTextures = other.VboTextures;
+ this->VboColors = other.VboColors;
+ this->sectionPosition = other.sectionPosition;
+ this->Vao = other.Vao;
+ this->numOfFaces = other.numOfFaces;
+ this->models = other.models;
+ this->textures = other.textures;
+ this->colors = other.colors;
+ this->hash = other.hash;
+
+ refCounterVbo[VboTextures]++;
+ refCounterVbo[VboModels]++;
+ refCounterVbo[VboColors]++;
+ refCounterVao[Vao]++;
+}
+
+void RendererSection::SetEnabled(bool isEnabled) {
+ this->isEnabled = isEnabled;
+}
+
+bool RendererSection::IsNeedUpdate() {
+ size_t currentHash = world->GetSection(sectionPosition).GetHash();
+ bool isNeedUpdate = currentHash != hash;
+ return isNeedUpdate;
+}
+
+void RendererSection::PrepareResources() {
+ const std::map<BlockTextureId,glm::vec4> &textureAtlas = AssetManager::Instance().GetTextureAtlasIndexes();
+ Section &section = world->GetSection(sectionPosition);
+ models.clear();
+ textures.clear();
+ colors.clear();
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ for (int x = 0; x < 16; x++) {
+ Vector blockPos = Vector(x, y, z) + (sectionPosition * 16);
+ Block &block = world->GetBlock(blockPos);
+ if (block.id == 0)
+ continue;
+
+ auto checkBlockVisibility = [&](Vector block) -> bool {
+ return section.GetBlock(block).id == 0 ||
+ section.GetBlock(block).id == 31 ||
+ section.GetBlock(block).id == 18;
+ };
+
+ unsigned char isVisible = 0;
+ if (x == 0 || x == 15 || y == 0 || y == 15 || z == 0 || z == 15) {
+ isVisible = 0b1111'1111; //All faces is visible
+ } else {
+ isVisible |= checkBlockVisibility(Vector(x - 1, y, z)) << 0;
+ isVisible |= checkBlockVisibility(Vector(x + 1, y, z)) << 1;
+ isVisible |= checkBlockVisibility(Vector(x, y + 1, z)) << 2;
+ isVisible |= checkBlockVisibility(Vector(x, y - 1, z)) << 3;
+ isVisible |= checkBlockVisibility(Vector(x, y, z - 1)) << 4;
+ isVisible |= checkBlockVisibility(Vector(x, y, z + 1)) << 5;
+ }
+
+ if (isVisible == 0x00)
+ continue;
+
+ glm::mat4 transform;
+ transform = glm::translate(transform, glm::vec3(sectionPosition.GetX() * 16,
+ sectionPosition.GetY() * 16,
+ sectionPosition.GetZ() * 16));
+ transform = glm::translate(transform, glm::vec3(x, y, z));
+ glm::vec3 biomeColor(0.275, 0.63, 0.1);
+ glm::vec3 color(0.0f, 0.0f, 0.0f);
+ if (block.id == 31 || block.id == 18)
+ color = biomeColor;
+
+ if (block.id == 31) { //X-cross like blocks rendering
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 2));
+ for (int i = 0; i < 4; i++) {
+ textures.push_back(texture->second);
+ colors.push_back(color);
+ }
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0.15f, 0, 0.15f));
+ faceTransform = glm::scale(faceTransform, glm::vec3(1.0f, 0.9f, 1.0f));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f));
+ faceTransform = glm::rotate(faceTransform, glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0));
+ for (int i = 0; i < 4; i++) {
+ models.push_back(faceTransform);
+ faceTransform = glm::translate(faceTransform, glm::vec3(0.0f, 0.0f, 0.5f));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
+ faceTransform = glm::translate(faceTransform, glm::vec3(0.0f, 0.0f, -0.5f));
+ }
+ continue;
+ }
+
+ if (isVisible >> 0 & 0x1) { //east side of block (X+)
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 0));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f));
+ models.push_back(faceTransform);
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 2));
+ if (texture != textureAtlas.end())
+ textures.push_back(texture->second);
+ else
+ textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
+ 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
+ colors.push_back(color);
+ }
+ if (isVisible >> 1 & 0x1) { //west side X-
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(1, 0, 0));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f));
+ faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f));
+ faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1));
+ models.push_back(faceTransform);
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 3));
+ if (texture != textureAtlas.end())
+ textures.push_back(texture->second);
+ else
+ textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
+ 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
+ colors.push_back(color);
+ }
+ if (isVisible >> 2 & 0x1) { //Top side Y+
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 1, 0));
+ models.push_back(faceTransform);
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 1));
+ if (texture != textureAtlas.end())
+ textures.push_back(texture->second);
+ else
+ textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
+ 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
+ if (block.id != 2)
+ colors.push_back(color);
+ else
+ colors.push_back(biomeColor);
+ }
+ if (isVisible >> 3 & 0x1) { //Bottom side Y-
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 0));
+ faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0, 0));
+ faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1));
+ models.push_back(faceTransform);
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 0));
+ if (texture != textureAtlas.end())
+ textures.push_back(texture->second);
+ else
+ textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
+ 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
+ colors.push_back(color);
+ }
+ if (isVisible >> 4 & 0x1) { //south side Z+
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(1, 0, 0));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f));
+ models.push_back(faceTransform);
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 3));
+ if (texture != textureAtlas.end())
+ textures.push_back(texture->second);
+ else
+ textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
+ 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
+ colors.push_back(color);
+ }
+ if (isVisible >> 5 & 0x1) { //north side Z-
+ glm::mat4 faceTransform = glm::translate(transform, glm::vec3(0, 0, 1));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f));
+ faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f));
+ faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1));
+ faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1, 0, 0.0f));
+ faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1.0f));
+ models.push_back(faceTransform);
+ auto texture = textureAtlas.find(BlockTextureId(block.id, block.state, 4));
+ if (texture != textureAtlas.end())
+ textures.push_back(texture->second);
+ else
+ textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690,
+ 0.0078125, 0.00442477876106194690)); //Fallback TNT texture
+ colors.push_back(color);
+ }
+ }
+ }
+ }
+ numOfFaces = textures.size();
+ hash = section.GetHash();
+}
+
+void RendererSection::PrepareRender() {
+ glBindBuffer(GL_ARRAY_BUFFER, VboTextures);
+ glBufferData(GL_ARRAY_BUFFER, textures.size() * sizeof(glm::vec4), textures.data(), GL_DYNAMIC_DRAW);
+ textures.clear();
+
+ glBindBuffer(GL_ARRAY_BUFFER, VboModels);
+ glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW);
+ models.clear();
+
+ glBindBuffer(GL_ARRAY_BUFFER, VboColors);
+ glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_DYNAMIC_DRAW);
+ colors.clear();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp
new file mode 100644
index 0000000..093a977
--- /dev/null
+++ b/src/RendererSection.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <GL/glew.h>
+#include <glm/detail/type_mat.hpp>
+#include <glm/vec2.hpp>
+#include <glm/detail/type_mat4x4.hpp>
+#include <glm/gtx/transform.hpp>
+#include <easylogging++.h>
+
+#include "AssetManager.hpp"
+#include "Section.hpp"
+#include "World.hpp"
+#include "Vector.hpp"
+#include "Renderer.hpp"
+
+class RendererSection : Renderer {
+ Vector sectionPosition;
+ World *world;
+ GLuint Vao, VboTextures, VboModels, VboColors;
+ std::vector<glm::mat4> models;
+ std::vector<glm::vec4> textures;
+ std::vector<glm::vec3> colors;
+
+ static GLuint VboVertices, VboUvs;
+ static std::map<GLuint, int> refCounterVbo;
+ static std::map<GLuint, int> refCounterVao;
+
+ size_t numOfFaces = 0;
+
+ bool isEnabled = true;
+
+ size_t hash = 0;
+public:
+ RendererSection(World *world, Vector position);
+ RendererSection(const RendererSection &other);
+ ~RendererSection() override;
+
+ void Render(RenderState &renderState) override;
+
+ void PrepareResources() override;
+
+ void PrepareRender() override;
+
+ void SetEnabled(bool isEnabled);
+
+ Section *GetSection();
+
+ bool IsNeedUpdate();
+}; \ No newline at end of file
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
new file mode 100644
index 0000000..c80250c
--- /dev/null
+++ b/src/RendererWorld.cpp
@@ -0,0 +1 @@
+#include "RendererWorld.hpp"
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
new file mode 100644
index 0000000..761bbde
--- /dev/null
+++ b/src/RendererWorld.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "RendererSection.hpp"
+
+class RendererWorld {
+
+}; \ No newline at end of file
diff --git a/src/Section.cpp b/src/Section.cpp
new file mode 100644
index 0000000..8b86afd
--- /dev/null
+++ b/src/Section.cpp
@@ -0,0 +1,147 @@
+#include "Section.hpp"
+
+
+Section::Section(Vector position, byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky,
+ byte bitsPerBlock,
+ std::vector<unsigned short> palette) {
+ worldPosition = position;
+
+ m_dataBlocksLen = dataBlocksLength;
+ m_dataBlocks = new byte[m_dataBlocksLen];
+ std::copy(dataBlocks, dataBlocks + m_dataBlocksLen, m_dataBlocks);
+
+ m_dataLight = new byte[2048];
+ std::copy(dataLight, dataLight + 2048, m_dataLight);
+
+ if (dataSky) {
+ m_dataSkyLight = new byte[2048];
+ std::copy(dataSky, dataSky + 2048, m_dataSkyLight);
+ }
+
+ m_palette = palette;
+ m_bitsPerBlock = bitsPerBlock;
+}
+
+Section::~Section() {
+ delete[] m_dataBlocks;
+ m_dataBlocksLen = 0;
+ m_dataBlocks = nullptr;
+ delete[] m_dataLight;
+ m_dataLight = nullptr;
+ delete[] m_dataSkyLight;
+ m_dataSkyLight = nullptr;
+}
+
+Block &Section::GetBlock(Vector pos) {
+ return m_blocks[pos.GetY() * 256 + pos.GetZ() * 16 + pos.GetX()];
+}
+
+double totalParsingTime = 0;
+
+void Section::Parse() {
+ if (!m_blocks.empty())
+ return;
+
+ long long *longArray = reinterpret_cast<long long *>(m_dataBlocks);
+ for (size_t i = 0; i < m_dataBlocksLen / 8; i++)
+ endswap(&longArray[i]);
+ std::vector<unsigned short> blocks;
+ blocks.reserve(4096);
+ {
+ auto begin = std::chrono::steady_clock::now();
+ int bitPos = 0;
+ unsigned short t = 0;
+ for (size_t i = 0; i < m_dataBlocksLen; i++) {
+ for (int j = 0; j < 8; j++) {
+ t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00;
+ t >>= 1;
+ m_dataBlocks[i] >>= 1;
+ bitPos++;
+ if (bitPos >= m_bitsPerBlock) {
+ bitPos = 0;
+ t >>= m_bitsPerBlock - 1;
+ blocks.push_back(t);
+ t = 0;
+ }
+ }
+ }
+ auto end = std::chrono::steady_clock::now();
+ std::chrono::duration<double, std::milli> time = end - begin;
+ totalParsingTime += time.count();
+ }
+ std::vector<byte> light;
+ light.reserve(4096);
+ for (int i = 0; i < 2048; i++) {
+ byte t = m_dataLight[i];
+ byte first = t & 0b11110000;
+ byte second = t >> 4;
+ light.push_back(first);
+ light.push_back(second);
+ }
+ for (int i = 0; i < 4096; i++) {
+ unsigned short blockId = m_palette.size() > 0 ? m_palette[blocks[i]] : blocks[i];
+ Block block(blockId >> 4, blockId & 0xF);
+ m_blocks.push_back(block);
+ }
+ delete[] m_dataBlocks;
+ m_dataBlocksLen = 0;
+ m_dataBlocks = nullptr;
+ delete[] m_dataLight;
+ m_dataLight = nullptr;
+ delete[] m_dataSkyLight;
+ m_dataSkyLight = nullptr;
+
+ parseWaiter.notify_all();
+}
+
+Section &Section::operator=(Section other) {
+ std::swap(*this, other);
+ return *this;
+}
+
+void swap(Section &a, Section &b) {
+ using std::swap;
+ swap(a.m_dataBlocksLen, b.m_dataBlocksLen);
+ swap(a.m_dataBlocks, b.m_dataBlocks);
+ swap(a.m_dataLight, b.m_dataLight);
+ swap(a.m_dataSkyLight, b.m_dataSkyLight);
+ swap(a.m_blocks, b.m_blocks);
+ swap(a.m_palette, b.m_palette);
+ swap(a.m_bitsPerBlock, b.m_bitsPerBlock);
+}
+
+Section::Section(const Section &other) {
+ worldPosition = other.worldPosition;
+ m_dataBlocksLen = other.m_dataBlocksLen;
+ if (other.m_blocks.empty()) {
+ m_dataBlocks = new byte[m_dataBlocksLen];
+ std::copy(other.m_dataBlocks, other.m_dataBlocks + m_dataBlocksLen, m_dataBlocks);
+
+ m_dataLight = new byte[2048];
+ std::copy(other.m_dataLight, other.m_dataLight + 2048, m_dataLight);
+
+ if (other.m_dataSkyLight) {
+ m_dataSkyLight = new byte[2048];
+ std::copy(other.m_dataSkyLight, other.m_dataSkyLight + 2048, m_dataSkyLight);
+ }
+ } else {
+ std::copy(other.m_blocks.begin(), other.m_blocks.end(), std::back_inserter(m_blocks));
+ }
+
+ m_palette = other.m_palette;
+ m_bitsPerBlock = other.m_bitsPerBlock;
+}
+
+Vector Section::GetPosition() {
+ return worldPosition;
+}
+
+size_t Section::GetHash() {
+ if (m_blocks.empty()) return 0;
+
+ unsigned char *from = reinterpret_cast<unsigned char *>(m_blocks.data());
+ size_t length = m_blocks.size() * sizeof(Block);
+
+ std::string str(from, from + length);
+ return std::hash<std::string>{}(str);
+} \ No newline at end of file
diff --git a/src/world/Section.hpp b/src/Section.hpp
index 2df0cfe..f40fdf9 100644
--- a/src/world/Section.hpp
+++ b/src/Section.hpp
@@ -7,9 +7,9 @@
#include <easylogging++.h>
-#include <world/Block.hpp>
-#include <Vector.hpp>
-#include <Utility.hpp>
+#include "Block.hpp"
+#include "Vector.hpp"
+#include "Utility.hpp"
const int SECTION_WIDTH = 16;
const int SECTION_LENGTH = 16;
diff --git a/src/Shader.cpp b/src/Shader.cpp
new file mode 100644
index 0000000..cf43115
--- /dev/null
+++ b/src/Shader.cpp
@@ -0,0 +1,115 @@
+#include "Shader.hpp"
+
+Shader::Shader(const GLchar *vertexPath, const GLchar *fragmentPath, const GLchar *geometryPath) {
+ vertex = vertexPath;
+ fragment = fragmentPath;
+ // 1. Получаем исходный код шейдера из filePath
+ std::string vertexCode;
+ std::string fragmentCode;
+ std::string geometryCode;
+ std::ifstream vShaderFile;
+ std::ifstream fShaderFile;
+ std::ifstream gShaderFile;
+ // Удостоверимся, что ifstream объекты могут выкидывать исключения
+ vShaderFile.exceptions(std::ifstream::failbit);
+ fShaderFile.exceptions(std::ifstream::failbit);
+ gShaderFile.exceptions(std::ifstream::failbit);
+ try {
+ // Открываем файлы
+ vShaderFile.open(vertexPath);
+ fShaderFile.open(fragmentPath);
+ if (geometryPath != nullptr)
+ gShaderFile.open(geometryPath);
+ std::stringstream vShaderStream, fShaderStream, gShaderStream;
+ // Считываем данные в потоки
+ vShaderStream << vShaderFile.rdbuf();
+ fShaderStream << fShaderFile.rdbuf();
+ if (geometryPath != nullptr)
+ gShaderStream << gShaderFile.rdbuf();
+ // Закрываем файлы
+ vShaderFile.close();
+ fShaderFile.close();
+ if (geometryPath != nullptr)
+ gShaderFile.close();
+ // Преобразовываем потоки в массив GLchar
+ vertexCode = vShaderStream.str();
+ fragmentCode = fShaderStream.str();
+ if (geometryPath != nullptr)
+ geometryCode = gShaderStream.str();
+ }
+ catch (std::ifstream::failure e) {
+ LOG(ERROR) << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ";
+ }
+ const GLchar *vShaderCode = vertexCode.c_str();
+ const GLchar *fShaderCode = fragmentCode.c_str();
+ const GLchar *gShaderCode = geometryCode.c_str();
+
+ // 2. Сборка шейдеров
+ GLuint vertex, fragment, geometry;
+ GLint success;
+ GLchar infoLog[512];
+
+ // Вершинный шейдер
+ vertex = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex, 1, &vShaderCode, NULL);
+ glCompileShader(vertex);
+ // Если есть ошибки - вывести их
+ glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(vertex, 512, NULL, infoLog);
+ LOG(ERROR) << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
+ };
+
+ // Вершинный шейдер
+ fragment = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment, 1, &fShaderCode, NULL);
+ glCompileShader(fragment);
+ // Если есть ошибки - вывести их
+ glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(fragment, 512, NULL, infoLog);
+ LOG(ERROR) << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog;
+ };
+
+ if (geometryPath != nullptr) {
+ geometry = glCreateShader(GL_GEOMETRY_SHADER);
+ glShaderSource(geometry, 1, &gShaderCode, NULL);
+ glCompileShader(geometry);
+ // Если есть ошибки - вывести их
+ glGetShaderiv(geometry, GL_COMPILE_STATUS, &success);
+ if (!success) {
+ glGetShaderInfoLog(geometry, 512, NULL, infoLog);
+ LOG(ERROR) << "ERROR::SHADER::GEOMETRY::COMPILATION_FAILED\n" << infoLog;
+ };
+ }
+
+ // Шейдерная программа
+ this->Program = glCreateProgram();
+ glAttachShader(this->Program, vertex);
+ glAttachShader(this->Program, fragment);
+ if (geometryPath != nullptr)
+ glAttachShader(this->Program, geometry);
+ glLinkProgram(this->Program);
+ //Если есть ошибки - вывести их
+ glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
+ if (!success) {
+ glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
+ LOG(FATAL) << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
+ }
+
+ // Удаляем шейдеры, поскольку они уже в программу и нам больше не нужны.
+ glDeleteShader(vertex);
+ glDeleteShader(fragment);
+}
+
+void Shader::Use() {
+ glUseProgram(this->Program);
+}
+
+void Shader::Reload() {
+ const GLchar *vertexPath = vertex;
+ const GLchar *fragmentPath = fragment;
+ this->~Shader();
+ new(this) Shader(vertexPath, fragmentPath);
+ LOG(INFO) << "Shader is realoded!";
+}
diff --git a/src/graphics/Shader.hpp b/src/Shader.hpp
index 17a434e..17a434e 100644
--- a/src/graphics/Shader.hpp
+++ b/src/Shader.hpp
diff --git a/src/Socket.cpp b/src/Socket.cpp
new file mode 100644
index 0000000..2bbf49a
--- /dev/null
+++ b/src/Socket.cpp
@@ -0,0 +1,29 @@
+#include "Socket.hpp"
+
+Socket::Socket(std::string address, unsigned short port) {
+ sf::Socket::Status connectionStatus = socket.connect(sf::IpAddress(address), port);
+ if (connectionStatus == sf::Socket::Status::Error)
+ throw std::runtime_error("Can't connect to remote server");
+ else if (connectionStatus != sf::Socket::Status::Done)
+ throw std::runtime_error("Connection failed with unknown reason");
+}
+
+Socket::~Socket() {
+ socket.disconnect();
+}
+
+void Socket::Read(unsigned char *buffPtr, size_t buffLen) {
+ size_t received = 0;
+ socket.receive(buffPtr, buffLen, received);
+ size_t totalReceived = received;
+ while (totalReceived < buffLen) {
+ if (socket.receive(buffPtr + totalReceived, buffLen - totalReceived, received) != sf::Socket::Done)
+ throw std::runtime_error("Raw socket data receiving is failed");
+ totalReceived += received;
+ }
+}
+
+void Socket::Write(unsigned char *buffPtr, size_t buffLen) {
+ if (socket.send(buffPtr, buffLen) != sf::Socket::Done)
+ throw std::runtime_error("Raw socket data sending is failed");
+}
diff --git a/src/network/Socket.hpp b/src/Socket.hpp
index 48bcad9..48bcad9 100644
--- a/src/network/Socket.hpp
+++ b/src/Socket.hpp
diff --git a/src/Stream.cpp b/src/Stream.cpp
new file mode 100644
index 0000000..54b1e1b
--- /dev/null
+++ b/src/Stream.cpp
@@ -0,0 +1,348 @@
+#include "Stream.hpp"
+
+const int MAX_VARINT_LENGTH = 5;
+
+bool StreamInput::ReadBool() {
+ unsigned char value;
+ ReadData(&value, 1);
+ return value != 0;
+}
+
+signed char StreamInput::ReadByte() {
+ signed char value;
+ ReadData((unsigned char *) &value, 1);
+ endswap(value);
+ return value;
+}
+
+unsigned char StreamInput::ReadUByte() {
+ unsigned char value;
+ ReadData(&value, 1);
+ endswap(value);
+ return value;
+}
+
+short StreamInput::ReadShort() {
+ unsigned short value;
+ ReadData((unsigned char *) &value, 2);
+ endswap(value);
+ return value;
+}
+
+unsigned short StreamInput::ReadUShort() {
+ unsigned short value;
+ ReadData((unsigned char *) &value, 2);
+ endswap(value);
+ return value;
+}
+
+int StreamInput::ReadInt() {
+ int value;
+ ReadData((unsigned char *) &value, 4);
+ endswap(value);
+ return value;
+}
+
+long long StreamInput::ReadLong() {
+ long long value;
+ ReadData((unsigned char *) &value, 8);
+ endswap(value);
+ return value;
+}
+
+float StreamInput::ReadFloat() {
+ float value;
+ ReadData((unsigned char *) &value, 4);
+ endswap(value);
+ return value;
+}
+
+double StreamInput::ReadDouble() {
+ double value;
+ ReadData((unsigned char *) &value, 8);
+ endswap(value);
+ return value;
+}
+
+std::string StreamInput::ReadString() {
+ int strLength = ReadVarInt();
+ unsigned char *buff = new unsigned char[strLength + 1];
+ ReadData(buff, strLength);
+ buff[strLength] = 0;
+ std::string str((char *) buff);
+ delete buff;
+ return str;
+}
+
+std::string StreamInput::ReadChat() {
+ std::string str, jsonStr = ReadString();
+ nlohmann::json json;
+ try {
+ json = nlohmann::json::parse(jsonStr);
+ } catch (std::exception &e) {
+ LOG(WARNING) << "Chat json parsing failed: " << e.what();
+ LOG(WARNING) << "Corrupted json: " << jsonStr;
+ return "";
+ }
+ if (json.find("translate") != json.end())
+ if (json["translate"].get<std::string>() == "multiplayer.disconnect.kicked")
+ return "kicked by operator";
+ for (auto &it:json["extra"]) {
+ str += it["text"].get<std::string>();
+ }
+ return str;
+}
+
+int StreamInput::ReadVarInt() {
+ unsigned char data[MAX_VARINT_LENGTH] = {0};
+ size_t dataLen = 0;
+ do {
+ ReadData(&data[dataLen], 1);
+ } while ((data[dataLen++] & 0x80) != 0);
+
+ int readed = 0;
+ int result = 0;
+ char read;
+ do {
+ read = data[readed];
+ int value = (read & 0b01111111);
+ result |= (value << (7 * readed));
+ readed++;
+ } while ((read & 0b10000000) != 0);
+
+ return result;
+}
+
+long long StreamInput::ReadVarLong() {
+ return 0;
+}
+
+std::vector<unsigned char> StreamInput::ReadEntityMetadata() {
+ return std::vector<unsigned char>();
+}
+
+std::vector<unsigned char> StreamInput::ReadSlot() {
+ return std::vector<unsigned char>();
+}
+
+std::vector<unsigned char> StreamInput::ReadNbtTag() {
+ return std::vector<unsigned char>();
+}
+
+Vector StreamInput::ReadPosition() {
+ unsigned long long t = ReadLong();
+ int x = t >> 38;
+ int y = (t >> 26) & 0xFFF;
+ int z = t << 38 >> 38;
+ if (x >= pow(2, 25)) {
+ x -= pow(2, 26);
+ }
+ if (y >= pow(2, 11)) {
+ y -= pow(2, 12);
+ }
+ if (z >= pow(2, 25)) {
+ z -= pow(2, 26);
+ }
+ return Vector(x, y, z);
+}
+
+unsigned char StreamInput::ReadAngle() {
+ return ReadUByte();
+}
+
+std::vector<unsigned char> StreamInput::ReadUuid() {
+ unsigned char buff[16];
+ ReadData(buff, 16);
+ endswap(buff, 16);
+ return std::vector<unsigned char>(buff, buff + 16);
+}
+
+std::vector<unsigned char> StreamInput::ReadByteArray(size_t arrLength) {
+ unsigned char *buffer = new unsigned char[arrLength];
+ ReadData(buffer, arrLength);
+ std::vector<unsigned char> ret(buffer, buffer + arrLength);
+ delete buffer;
+ return ret;
+
+}
+
+void StreamOutput::WriteBool(bool value) {
+ unsigned char val = value ? 1 : 0;
+ endswap(val);
+ WriteData(&val, 1);
+}
+
+void StreamOutput::WriteByte(signed char value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 1);
+}
+
+void StreamOutput::WriteUByte(unsigned char value) {
+ endswap(value);
+ WriteData(&value, 1);
+}
+
+void StreamOutput::WriteShort(short value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 2);
+}
+
+void StreamOutput::WriteUShort(unsigned short value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 2);
+}
+
+void StreamOutput::WriteInt(int value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 4);
+}
+
+void StreamOutput::WriteLong(long long value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 8);
+}
+
+void StreamOutput::WriteFloat(float value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 4);
+}
+
+void StreamOutput::WriteDouble(double value) {
+ endswap(value);
+ WriteData((unsigned char *) &value, 8);
+}
+
+void StreamOutput::WriteString(std::string value) {
+ WriteVarInt(value.size());
+ WriteData((unsigned char *) value.data(), value.size());
+}
+
+void StreamOutput::WriteChat(std::string value) {
+ WriteString(value);
+}
+
+void StreamOutput::WriteVarInt(int value) {
+ unsigned char buff[5];
+ size_t len = 0;
+ do {
+ unsigned char temp = (unsigned char) (value & 0b01111111);
+ value >>= 7;
+ if (value != 0) {
+ temp |= 0b10000000;
+ }
+ buff[len] = temp;
+ len++;
+ } while (value != 0);
+ WriteData(buff, len);
+}
+
+void StreamOutput::WriteVarLong(long long value) {
+ unsigned char buff[10];
+ size_t len = 0;
+ do {
+ unsigned char temp = (unsigned char) (value & 0b01111111);
+ value >>= 7;
+ if (value != 0) {
+ temp |= 0b10000000;
+ }
+ buff[len] = temp;
+ len++;
+ } while (value != 0);
+ WriteData(buff, len);
+}
+
+void StreamOutput::WriteEntityMetadata(std::vector<unsigned char> value) {
+ LOG(FATAL) << "Used unimplemented WriteEntityMetadata: " << value.size();
+}
+
+void StreamOutput::WriteSlot(std::vector<unsigned char> value) {
+ LOG(FATAL) << "Used unimplemented WriteSlot " << value.size();
+}
+
+void StreamOutput::WriteNbtTag(std::vector<unsigned char> value) {
+ LOG(FATAL) << "Used unimplemented WriteNbtTag " << value.size();
+}
+
+void StreamOutput::WritePosition(Vector value) {
+ LOG(FATAL) << "Used unimplemented Position: " << value.GetX() << ", " << value.GetY() << " " << value.GetZ();
+}
+
+void StreamOutput::WriteAngle(unsigned char value) {
+ WriteUByte(value);
+}
+
+void StreamOutput::WriteUuid(std::vector<unsigned char> value) {
+ WriteByteArray(value);
+}
+
+void StreamOutput::WriteByteArray(std::vector<unsigned char> value) {
+ WriteData(value.data(), value.size());
+}
+
+void StreamBuffer::ReadData(unsigned char *buffPtr, size_t buffLen) {
+ size_t bufferLengthLeft = buffer + bufferLength - bufferPtr;
+ if (bufferLengthLeft < buffLen)
+ throw std::runtime_error("Required data is more, than in buffer available");
+ std::memcpy(buffPtr, bufferPtr, buffLen);
+ bufferPtr += buffLen;
+}
+
+void StreamBuffer::WriteData(unsigned char *buffPtr, size_t buffLen) {
+ size_t bufferLengthLeft = buffer + bufferLength - bufferPtr;
+ if (bufferLengthLeft < buffLen)
+ throw std::runtime_error("Required data is more, than in buffer available");
+ std::memcpy(bufferPtr, buffPtr, buffLen);
+ bufferPtr += buffLen;
+}
+
+StreamBuffer::StreamBuffer(unsigned char *data, size_t dataLen) {
+ buffer = new unsigned char[dataLen];
+ bufferPtr = buffer;
+ bufferLength = dataLen;
+ std::memcpy(buffer, data, dataLen);
+}
+
+StreamBuffer::StreamBuffer(size_t bufferLen) {
+ buffer = new unsigned char[bufferLen];
+ bufferPtr = buffer;
+ bufferLength = bufferLen;
+ for (unsigned char *p = buffer; p != buffer + bufferLength; ++p)
+ *p = 0;
+}
+
+StreamBuffer::~StreamBuffer() {
+ delete buffer;
+}
+
+std::vector<unsigned char> StreamBuffer::GetBuffer() {
+ return std::vector<unsigned char>(buffer, buffer + bufferLength);
+}
+
+void StreamCounter::WriteData(unsigned char *buffPtr, size_t buffLen) {
+ buffPtr++;
+ size += buffLen;
+}
+
+StreamCounter::StreamCounter(size_t initialSize) : size(initialSize) {
+
+}
+
+StreamCounter::~StreamCounter() {
+
+}
+
+size_t StreamCounter::GetCountedSize() {
+ return size;
+}
+
+void StreamSocket::ReadData(unsigned char *buffPtr, size_t buffLen) {
+ socket->Read(buffPtr, buffLen);
+}
+
+void StreamSocket::WriteData(unsigned char *buffPtr, size_t buffLen) {
+ socket->Write(buffPtr, buffLen);
+}
+
+StreamSocket::StreamSocket(Socket *socketPtr) : socket(socketPtr) {
+
+} \ No newline at end of file
diff --git a/src/network/Stream.hpp b/src/Stream.hpp
index a24dfbe..b856d5f 100644
--- a/src/network/Stream.hpp
+++ b/src/Stream.hpp
@@ -9,9 +9,9 @@
#include <nlohmann/json.hpp>
#include <easylogging++.h>
-#include <network/Socket.hpp>
-#include <Vector.hpp>
-#include <Utility.hpp>
+#include "Socket.hpp"
+#include "Vector.hpp"
+#include "Utility.hpp"
class Stream {
public:
diff --git a/src/Texture.cpp b/src/Texture.cpp
new file mode 100644
index 0000000..5d183c3
--- /dev/null
+++ b/src/Texture.cpp
@@ -0,0 +1,37 @@
+#include "Texture.hpp"
+
+Texture::Texture(std::string filename, GLenum textureWrapping, GLenum textureFiltering) {
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ //Texture options
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrapping);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrapping);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, textureFiltering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ //Image load
+ sf::Image image;
+ if (!image.loadFromFile(filename)) {
+ LOG(ERROR) << "Can't open image " << filename;
+ throw 201;
+ }
+ if (image.getPixelsPtr() == nullptr) {
+ LOG(ERROR) << "Image data is corrupted!";
+ throw 202;
+ }
+ image.flipVertically();
+
+
+ //Creating texture
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ (GLvoid *) image.getPixelsPtr());
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+}
+
+Texture::~Texture() {
+ glDeleteTextures(1, &texture);
+}
diff --git a/src/graphics/Texture.hpp b/src/Texture.hpp
index 5b2afcf..5b2afcf 100644
--- a/src/graphics/Texture.hpp
+++ b/src/Texture.hpp
diff --git a/src/Utility.cpp b/src/Utility.cpp
new file mode 100644
index 0000000..9fecc08
--- /dev/null
+++ b/src/Utility.cpp
@@ -0,0 +1,73 @@
+#include <thread>
+#include "Utility.hpp"
+
+GLenum glCheckError_(const char *file, int line) {
+ GLenum errorCode;
+ while ((errorCode = glGetError()) != GL_NO_ERROR) {
+ std::string error;
+ switch (errorCode) {
+ case GL_INVALID_ENUM:
+ error = "INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ error = "INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ error = "INVALID_OPERATION";
+ break;
+ case GL_STACK_OVERFLOW:
+ error = "STACK_OVERFLOW";
+ break;
+ case GL_STACK_UNDERFLOW:
+ error = "STACK_UNDERFLOW";
+ break;
+ case GL_OUT_OF_MEMORY:
+ error = "OUT_OF_MEMORY";
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ error = "INVALID_FRAMEBUFFER_OPERATION";
+ break;
+ }
+ static int t = 0;
+ t++;
+ if (t > 10)
+ LOG(FATAL);
+ LOG(ERROR) << "OpenGL error: " << error << " at " << file << ":" << line;
+ }
+ return errorCode;
+}
+
+LoopExecutionTimeController::LoopExecutionTimeController(duration delayLength) : delayLength(delayLength) {
+ previousUpdate = clock::now();
+}
+
+LoopExecutionTimeController::~LoopExecutionTimeController() {
+
+}
+
+void LoopExecutionTimeController::SetDelayLength(duration length) {
+ delayLength = length;
+}
+
+unsigned long long LoopExecutionTimeController::GetIterations() {
+ return iterations;
+}
+
+void LoopExecutionTimeController::Update() {
+ iterations++;
+ auto timeToSleep = delayLength - GetDelta();
+ if (timeToSleep.count()>0)
+ std::this_thread::sleep_for(timeToSleep);
+ previousUpdate = clock::now();
+}
+
+double LoopExecutionTimeController::GetDeltaMs() {
+ auto now = clock::now();
+ return duration(now-previousUpdate).count();
+}
+
+LoopExecutionTimeController::duration LoopExecutionTimeController::GetDelta() {
+ auto now = clock::now();
+ //std::cerr<<duration(now-previousUpdate).count()<<std::endl;
+ return duration(now-previousUpdate);
+}
diff --git a/src/Utility.hpp b/src/Utility.hpp
index 11b4ff7..52d6016 100644
--- a/src/Utility.hpp
+++ b/src/Utility.hpp
@@ -1,7 +1,10 @@
#pragma once
#include <algorithm>
+#include <string>
+#include <chrono>
+#include <easylogging++.h>
#include <GL/glew.h>
template<class T>
@@ -20,40 +23,30 @@ inline void endswap(unsigned char *arr, size_t arrLen) {
std::reverse(arr, arr + arrLen);
}
-inline GLenum glCheckError_(const char *file, int line) {
- GLenum errorCode;
- while ((errorCode = glGetError()) != GL_NO_ERROR) {
- std::string error;
- switch (errorCode) {
- case GL_INVALID_ENUM:
- error = "INVALID_ENUM";
- break;
- case GL_INVALID_VALUE:
- error = "INVALID_VALUE";
- break;
- case GL_INVALID_OPERATION:
- error = "INVALID_OPERATION";
- break;
- case GL_STACK_OVERFLOW:
- error = "STACK_OVERFLOW";
- break;
- case GL_STACK_UNDERFLOW:
- error = "STACK_UNDERFLOW";
- break;
- case GL_OUT_OF_MEMORY:
- error = "OUT_OF_MEMORY";
- break;
- case GL_INVALID_FRAMEBUFFER_OPERATION:
- error = "INVALID_FRAMEBUFFER_OPERATION";
- break;
- }
- static int t = 0;
- t++;
- if (t>10)
- LOG(FATAL);
- LOG(ERROR) << "OpenGL error: " << error << " at " << file << ":" << line;
- }
- return errorCode;
-}
+GLenum glCheckError_(const char *file, int line);
+#define glCheckError() glCheckError_(__FILE__, __LINE__)
+
+
+
+class LoopExecutionTimeController {
+ using clock = std::chrono::steady_clock ;
+ using timePoint = std::chrono::time_point<clock>;
+ using duration = std::chrono::duration<double,std::milli>;
+ timePoint previousUpdate;
+ duration delayLength;
+ unsigned long long iterations=0;
+public:
+ LoopExecutionTimeController(duration delayLength);
+
+ ~LoopExecutionTimeController();
+
+ void SetDelayLength(duration length);
+
+ unsigned long long GetIterations();
+
+ void Update();
+
+ double GetDeltaMs();
-#define glCheckError() glCheckError_(__FILE__, __LINE__) \ No newline at end of file
+ duration GetDelta();
+};
diff --git a/src/World.cpp b/src/World.cpp
new file mode 100644
index 0000000..487f4ba
--- /dev/null
+++ b/src/World.cpp
@@ -0,0 +1,129 @@
+#include "World.hpp"
+
+void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) {
+ StreamBuffer chunkData(packet->Data.data(), packet->Data.size());
+ std::bitset<16> bitmask(packet->PrimaryBitMask);
+ for (int i = 0; i < 16; i++) {
+ if (bitmask[i]) {
+ Vector chunkPosition = Vector(packet->ChunkX, i, packet->ChunkZ);
+ Section section = ParseSection(&chunkData, chunkPosition);
+ section.Parse();
+ sectionMutexes[chunkPosition].lock();
+ auto it = sections.find(chunkPosition);
+ if (it == sections.end()) {
+ sections.insert(std::make_pair(chunkPosition, section));
+ } else {
+ using std::swap;
+ swap(it->second, section);
+ }
+ sectionMutexes[chunkPosition].unlock();
+ }
+ }
+}
+
+Section World::ParseSection(StreamInput *data, Vector position) {
+ unsigned char bitsPerBlock = data->ReadUByte();
+ int paletteLength = data->ReadVarInt();
+ std::vector<unsigned short> palette;
+ for (int i = 0; i < paletteLength; i++) {
+ palette.push_back(data->ReadVarInt());
+ }
+ int dataArrayLength = data->ReadVarInt();
+ auto dataArray = data->ReadByteArray(dataArrayLength * 8);
+ auto blockLight = data->ReadByteArray(4096 / 2);
+ std::vector<unsigned char> skyLight;
+ if (dimension == 0)
+ skyLight = data->ReadByteArray(4096 / 2);
+ return Section(position, dataArray.data(), dataArray.size(), blockLight.data(),
+ (skyLight.size() > 0 ? skyLight.data() : nullptr), bitsPerBlock, palette);
+}
+
+World::~World() {
+}
+
+World::World() {
+
+}
+
+bool World::isPlayerCollides(double X, double Y, double Z) {
+ Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0));
+ std::vector<Vector> closestSectionsCoordinates = {
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX() + 1, PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX() - 1, PlayerChunk.GetY(), PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY() + 1, PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY() - 1, PlayerChunk.GetZ()),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ() + 1),
+ Vector(PlayerChunk.GetX(), PlayerChunk.GetY(), PlayerChunk.GetZ() - 1),
+ };
+ std::vector<std::map<Vector, Section>::iterator> closestSections;
+ for (auto &coord:closestSectionsCoordinates) {
+ auto it = sections.find(coord);
+ if (it != sections.end())
+ closestSections.push_back(it);
+ }
+ if (closestSections.empty())
+ return false;
+
+ for (auto &it:closestSections) {
+
+ const double PlayerWidth = 0.6;
+ const double PlayerHeight = 1.82;
+ const double PlayerLength = 0.6;
+
+ AABB playerColl;
+ playerColl.x = X - PlayerWidth / 2.0;
+ playerColl.w = PlayerWidth;
+ playerColl.y = Y;
+ playerColl.h = PlayerHeight;
+ playerColl.z = Z - PlayerLength / 2.0;
+ playerColl.l = PlayerLength;
+
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ Block block = it->second.GetBlock(Vector(x, y, z));
+ if (block.id == 0 || block.id == 31)
+ continue;
+ AABB blockColl{(x + it->first.GetX() * 16.0),
+ (y + it->first.GetY() * 16.0),
+ (z + it->first.GetZ() * 16.0), 1, 1, 1};
+ if (TestCollision(playerColl, blockColl))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+Block &World::GetBlock(Vector pos) {
+ Vector sectionPos (floor(pos.GetX() / 16.0f),floor(pos.GetY() / 16.0f),floor(pos.GetZ()/16.0f));
+ Vector inSectionPos = pos - (sectionPos * 16);
+ if (sections.find(sectionPos)==sections.end()){
+ static Block block(0,0);
+ return block;
+ }
+ sectionMutexes[sectionPos].lock();
+ Block& block = sections.find(sectionPos)->second.GetBlock(inSectionPos);
+ sectionMutexes[sectionPos].unlock();
+ return block;
+}
+
+std::vector<Vector> World::GetSectionsList() {
+ std::vector<Vector> sectionsList;
+ for (auto& it:sections) {
+ sectionsList.push_back(it.first);
+ }
+ return sectionsList;
+}
+
+Section &World::GetSection(Vector sectionPos) {
+ sectionMutexes[sectionPos].lock();
+ sectionMutexes[sectionPos].unlock();
+ return sections.find(sectionPos)->second;
+}
+
+glm::vec3 World::Raycast(glm::vec3 position, glm::vec3 direction, float maxLength, float minPrecision) {
+ return glm::vec3(position * direction / maxLength * minPrecision);
+}
diff --git a/src/world/World.hpp b/src/World.hpp
index 6b09f1f..52493a7 100644
--- a/src/world/World.hpp
+++ b/src/World.hpp
@@ -5,10 +5,11 @@
#include <easylogging++.h>
-#include <world/Block.hpp>
-#include <world/Section.hpp>
-#include <network/Packet.hpp>
-#include <world/Collision.hpp>
+#include "Block.hpp"
+#include "Section.hpp"
+#include "Packet.hpp"
+#include "Collision.hpp"
+#include "Vector.hpp"
class World {
std::map<Vector, Section> sections;
diff --git a/src/core/AssetManager.cpp b/src/core/AssetManager.cpp
index 14ea677..d263c4a 100644
--- a/src/core/AssetManager.cpp
+++ b/src/core/AssetManager.cpp
@@ -1,4 +1,4 @@
-#include <core/AssetManager.hpp>
+#include <AssetManager.hpp>
namespace fs = std::experimental::filesystem;
diff --git a/src/core/Core.cpp b/src/core/Core.cpp
index e98d204..dcfa890 100644
--- a/src/core/Core.cpp
+++ b/src/core/Core.cpp
@@ -1,6 +1,5 @@
#include "Core.hpp"
-//Core::Core():toRenderMutex("toRender"),availableChunksMutex("availableChunks") {
Core::Core() {
LOG(INFO) << "Core initializing...";
InitSfml(900, 450, "AltCraft");
@@ -9,8 +8,8 @@ Core::Core() {
glCheckError();
client = new NetworkClient("127.0.0.1", 25565, "HelloOne", isRunning);
gameState = new GameState(client, isRunning);
- gameStateLoopThread = std::thread(&Core::UpdateGameState, this);
- sectionUpdateLoopThread = std::thread(&Core::UpdateSections, this);
+ std::thread loop = std::thread(&Core::UpdateGameState, this);
+ std::swap(loop, gameStateLoopThread);
assetManager = new AssetManager;
PrepareToRendering();
LOG(INFO) << "Core is initialized";
@@ -20,7 +19,6 @@ Core::Core() {
Core::~Core() {
LOG(INFO) << "Core stopping...";
gameStateLoopThread.join();
- sectionUpdateLoopThread.join();
delete shader;
delete gameState;
delete client;
@@ -56,7 +54,6 @@ void Core::Exec() {
toWindow << "FPS: " << (1.0f / deltaTime) << " ";
toWindow << " (" << deltaTime * 1000 << "ms); ";
toWindow << "Tickrate: " << tickRate << " (" << (1.0 / tickRate * 1000) << "ms); ";
- toWindow << "Sections: " << sectionRate << " (" << (1.0 / sectionRate * 1000) << "ms); ";
window->setTitle(toWindow.str());
HandleEvents();
@@ -64,17 +61,6 @@ void Core::Exec() {
glCheckError();
RenderFrame();
- if (isRendersShouldBeCreated) {
- availableChunksMutex.lock();
- for (auto &it:renders) {
- auto pair = std::make_pair(it, RenderSection(&gameState->world, it));
- availableChunks.insert(pair);
- }
- renders.clear();
- availableChunksMutex.unlock();
- isRendersShouldBeCreated = false;
- waitRendersCreated.notify_all();
- }
}
}
@@ -112,7 +98,7 @@ void Core::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string W
contextSetting.depthBits = 24;
window = new sf::Window(sf::VideoMode(WinWidth, WinHeight), WinTitle, sf::Style::Default, contextSetting);
glCheckError();
- //window->setVerticalSyncEnabled(true);
+ window->setVerticalSyncEnabled(true);
//window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2, sf::VideoMode::getDesktopMode().height / 2));
window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2,
sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2));
@@ -180,6 +166,11 @@ void Core::HandleEvents() {
default:
break;
}
+ /*case sf::Event::MouseWheelScrolled:
+ if (!window->hasFocus())
+ break;
+ camera.ProcessMouseScroll(event.mouseWheelScroll.delta);
+ break;*/
default:
break;
}
@@ -220,16 +211,8 @@ void Core::RenderWorld() {
glCheckError();
- toRenderMutex.lock();
for (auto &render : toRender) {
- availableChunksMutex.lock();
- auto iterator = availableChunks.find(render);
- if (iterator == availableChunks.end()) {
- availableChunksMutex.unlock();
- continue;
- }
- /*Section &section = *iterator->second.GetSection();
- //availableChunksMutex.unlock();
+ Section &section = *availableChunks.find(render)->second.GetSection();
std::vector<Vector> sectionCorners = {
Vector(0, 0, 0),
@@ -242,8 +225,8 @@ void Core::RenderWorld() {
Vector(16, 16, 16),
};
bool isBreak = true;
- glm::mat4 vp = projection * view;
for (auto &it:sectionCorners) {
+ glm::mat4 vp = projection * view;
glm::vec3 point(section.GetPosition().GetX() * 16 + it.GetX(),
section.GetPosition().GetY() * 16 + it.GetY(),
section.GetPosition().GetZ() * 16 + it.GetZ());
@@ -258,14 +241,10 @@ void Core::RenderWorld() {
glm::vec3(section.GetPosition().GetX() * 16,
section.GetPosition().GetY() * 16,
section.GetPosition().GetZ() * 16)) > 30.0f) {
- availableChunksMutex.unlock();
continue;
}
- //availableChunksMutex.lock();*/
- iterator->second.Render(renderState);
- availableChunksMutex.unlock();
+ availableChunks.find(render)->second.Render(renderState);
}
- toRenderMutex.unlock();
glCheckError();
}
@@ -287,7 +266,6 @@ void Core::PrepareToRendering() {
}
void Core::UpdateChunksToRender() {
- return;
Vector playerChunk = Vector(floor(gameState->g_PlayerX / 16.0f), 0, floor(gameState->g_PlayerZ / 16.0f));
static Vector previousPlayerChunk = playerChunk;
static bool firstTime = true;
@@ -332,126 +310,4 @@ void Core::UpdateGameState() {
tickRate = 1 / delta.getElapsedTime().asSeconds();
}
LOG(INFO) << "GameState thread is stopped";
-}
-
-void Core::UpdateSections() {
- glm::vec3 playerPosition = gameState->Position();
- float playerPitch = gameState->Pitch();
- float playerYaw = gameState->Yaw();
- sf::Clock delta;
- std::vector<Vector> chunksToRender;
- auto currentSectionIterator = chunksToRender.begin();
- while (isRunning) {
- delta.restart();
- if (glm::length(glm::distance(gameState->Position(), playerPosition)) > 5.0f) {
- chunksToRender.clear();
- playerPosition = gameState->Position();
- Vector playerChunk = Vector(floor(playerPosition.x / 16.0f), 0, floor(playerPosition.z / 16.0f));
- for (auto &it:gameState->world.GetSectionsList()) {
- Vector chunkPosition = it;
- chunkPosition.SetY(0);
- Vector delta = chunkPosition - playerChunk;
- if (delta.GetMagnitude() > ChunkDistance) continue;
- chunksToRender.push_back(it);
- }
- std::sort(chunksToRender.begin(), chunksToRender.end(), [playerChunk](auto first, auto second) {
- glm::vec3 fDistance = first - playerChunk;
- glm::vec3 sDistance = second - playerChunk;
- return glm::length(fDistance) < glm::length(sDistance);
- });
- for (auto &it:chunksToRender) {
- availableChunksMutex.lock();
- if (availableChunks.find(it) == availableChunks.end()) {
- availableChunksMutex.unlock();
- renders.push_back(it);
- } else
- availableChunksMutex.unlock();
- }
- if (!renders.empty()) {
- std::mutex mutex;
- std::unique_lock<std::mutex> lock(mutex);
- isRendersShouldBeCreated = true;
- while (isRendersShouldBeCreated)
- waitRendersCreated.wait(lock);
- }
- currentSectionIterator = chunksToRender.begin();
- toRenderMutex.lock();
- toRender = chunksToRender;
- toRenderMutex.unlock();
- }
- if (currentSectionIterator != chunksToRender.end()) {
- availableChunksMutex.lock();
- auto iterator = availableChunks.find(*currentSectionIterator);
- if (iterator != availableChunks.end() && iterator->second.IsNeedUpdate()) {
- RenderSection rs = std::move(iterator->second);
- availableChunks.erase(iterator);
- auto pair = std::make_pair(*currentSectionIterator, rs);
- availableChunksMutex.unlock();
-
- pair.second.UpdateState(assetManager->GetTextureAtlasIndexes());
-
- availableChunksMutex.lock();
- availableChunks.insert(pair);
- }
- availableChunksMutex.unlock();
- currentSectionIterator = std::next(currentSectionIterator);
- }
- if (gameState->Pitch() != playerPitch || gameState->Yaw() != playerYaw) {
- playerPitch = gameState->Pitch();
- playerYaw = gameState->Yaw();
- const std::vector<Vector> sectionCorners = {
- Vector(0, 0, 0),
- Vector(0, 0, 16),
- Vector(0, 16, 0),
- Vector(0, 16, 16),
- Vector(16, 0, 0),
- Vector(16, 0, 16),
- Vector(16, 16, 0),
- Vector(16, 16, 16),
- };
- const glm::mat4 projection = glm::perspective(45.0f, (float)width() / (float)height(), 0.1f, 10000000.0f);
- const glm::mat4 view = gameState->GetViewMatrix();
- const glm::mat4 vp = projection * view;
- for (auto& section: toRender) {
- bool isCulled = true;
- for (auto &it : sectionCorners) {
- glm::vec3 point(section.GetX() * 16 + it.GetX(),
- section.GetY() * 16 + it.GetY(),
- section.GetZ() * 16 + it.GetZ());
- glm::vec4 p = vp * glm::vec4(point, 1);
- glm::vec3 res = glm::vec3(p) / p.w;
- if (res.x < 1 && res.x > -1 && res.y < 1 && res.y > -1 && res.z > 0) {
- isCulled = false;
- break;
- }
- }
- bool isVisible = !isCulled || glm::length(gameState->Position() -
- glm::vec3(section.GetX() * 16, section.GetY() * 16, section.GetZ() * 16)) < 30.0f;
- availableChunksMutex.lock();
- auto iter = availableChunks.find(section);
- if (iter != availableChunks.end())
- iter->second.SetEnabled(isVisible);
- availableChunksMutex.unlock();
-
- }
- }
- using namespace std::chrono_literals;
- std::this_thread::sleep_for(5ms);
- sectionRate = delta.getElapsedTime().asSeconds();
- delta.restart();
- }
-}
-
-MyMutex::MyMutex(std::string name) {
- str = name;
-}
-
-void MyMutex::lock() {
- LOG(WARNING) << "Thread " << std::this_thread::get_id() << " locked mutex " << str;
- mtx.lock();
-}
-
-void MyMutex::unlock() {
- LOG(WARNING) << "Thread " << std::this_thread::get_id() << " unlocked mutex " << str;
- mtx.unlock();
} \ No newline at end of file
diff --git a/src/core/Core.hpp b/src/core/Core.hpp
deleted file mode 100644
index 039b3a3..0000000
--- a/src/core/Core.hpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#pragma once
-
-#include <iomanip>
-#include <tuple>
-
-#include <easylogging++.h>
-#include <GL/glew.h>
-#include <glm/gtc/type_ptr.hpp>
-#include <SFML/Window.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/graphics/Gui.hpp b/src/graphics/Gui.hpp
deleted file mode 100644
index e22a0a7..0000000
--- a/src/graphics/Gui.hpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-
-class Gui {
-
-public:
- int WHY=0;
-
-};
diff --git a/src/graphics/RenderSection.cpp b/src/graphics/RenderSection.cpp
index ae072d6..b07759a 100644
--- a/src/graphics/RenderSection.cpp
+++ b/src/graphics/RenderSection.cpp
@@ -1,5 +1,4 @@
#include <graphics/RenderSection.hpp>
-#include <thread>
const GLfloat vertices[] = {
0, 0, 0,
@@ -43,6 +42,7 @@ std::map<GLuint, int> RenderSection::refCounterVao;
RenderSection::RenderSection(World *world, Vector position) : sectionPosition(position), world(world) {
+
if (VboVertices == magicUniqueConstant) {
glGenBuffers(1, &VboVertices);
glGenBuffers(1, &VboUvs);
@@ -138,7 +138,6 @@ RenderSection::~RenderSection() {
refCounterVao[Vao]--;
if (refCounterVbo[VboTextures] <= 0)
glDeleteBuffers(1, &VboTextures);
-
if (refCounterVbo[VboModels] <= 0)
glDeleteBuffers(1, &VboTextures);
if (refCounterVbo[VboColors] <= 0)
@@ -150,9 +149,9 @@ RenderSection::~RenderSection() {
void RenderSection::UpdateState(const std::map<BlockTextureId, glm::vec4> &textureAtlas) {
Section &section = world->GetSection(sectionPosition);
- models.clear();
- textures.clear();
- colors.clear();
+ std::vector<glm::mat4> models;
+ std::vector<glm::vec4> textures;
+ std::vector<glm::vec3> colors;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
@@ -296,27 +295,24 @@ void RenderSection::UpdateState(const std::map<BlockTextureId, glm::vec4> &textu
}
}
}
- numOfFaces = textures.size();
- hash = section.GetHash();
-}
-void RenderSection::Render(RenderState &state) {
- if (!isEnabled) return;
- if (!models.empty()) {
- glBindBuffer(GL_ARRAY_BUFFER, VboTextures);
- glBufferData(GL_ARRAY_BUFFER, textures.size() * sizeof(glm::vec4), textures.data(), GL_DYNAMIC_DRAW);
- textures.clear();
+ glBindBuffer(GL_ARRAY_BUFFER, VboTextures);
+ glBufferData(GL_ARRAY_BUFFER, textures.size() * sizeof(glm::vec4), textures.data(), GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, VboModels);
- glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW);
- models.clear();
+ glBindBuffer(GL_ARRAY_BUFFER, VboModels);
+ glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, VboColors);
- glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_DYNAMIC_DRAW);
- colors.clear();
+ glBindBuffer(GL_ARRAY_BUFFER, VboColors);
+ glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_DYNAMIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glCheckError();
+
+ numOfFaces = textures.size();
+}
+
+void RenderSection::Render(RenderState &state) {
state.SetActiveVao(Vao);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numOfFaces);
glCheckError();
@@ -334,23 +330,9 @@ RenderSection::RenderSection(const RenderSection &other) {
this->sectionPosition = other.sectionPosition;
this->Vao = other.Vao;
this->numOfFaces = other.numOfFaces;
- this->models = other.models;
- this->textures = other.textures;
- this->colors = other.colors;
- this->hash = other.hash;
refCounterVbo[VboTextures]++;
refCounterVbo[VboModels]++;
refCounterVbo[VboColors]++;
refCounterVao[Vao]++;
}
-
-void RenderSection::SetEnabled(bool isEnabled) {
- this->isEnabled = isEnabled;
-}
-
-bool RenderSection::IsNeedUpdate() {
- size_t currentHash = world->GetSection(sectionPosition).GetHash();
- bool isNeedUpdate = currentHash != hash;
- return isNeedUpdate;
-} \ No newline at end of file
diff --git a/src/graphics/RenderSection.hpp b/src/graphics/RenderSection.hpp
deleted file mode 100644
index 5973909..0000000
--- a/src/graphics/RenderSection.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <GL/glew.h>
-#include <glm/detail/type_mat.hpp>
-#include <glm/vec2.hpp>
-#include <glm/detail/type_mat4x4.hpp>
-#include <glm/gtx/transform.hpp>
-#include <easylogging++.h>
-
-#include <core/AssetManager.hpp>
-#include <world/Section.hpp>
-#include <world/World.hpp>
-
-class RenderState {
- GLuint ActiveVao;
- GLuint ActiveShader;
-public:
- void SetActiveVao(GLuint Vao);
- void SetActiveShader(GLuint Shader);
-};
-
-class RenderSection {
- Vector sectionPosition;
- World *world;
- GLuint Vao, VboTextures, VboModels, VboColors;
- std::vector<glm::mat4> models;
- std::vector<glm::vec4> textures;
- std::vector<glm::vec3> colors;
-
- static GLuint VboVertices, VboUvs;
- static std::map<GLuint, int> refCounterVbo;
- static std::map<GLuint, int> refCounterVao;
-
- size_t numOfFaces = 0;
-
- bool isEnabled = true;
-
- size_t hash = 0;
-public:
- RenderSection(World *world, Vector position);
- RenderSection(const RenderSection &other);
- ~RenderSection();
-
- void UpdateState(const std::map<BlockTextureId, glm::vec4> &textureAtlas);
- void Render(RenderState &state);
-
- void SetEnabled(bool isEnabled);
-
- Section *GetSection();
-
- bool IsNeedUpdate();
-}; \ No newline at end of file
diff --git a/src/graphics/Widget.hpp b/src/graphics/Widget.hpp
deleted file mode 100644
index c4d5dc1..0000000
--- a/src/graphics/Widget.hpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-
-class Widget {
- unsigned int x,y,w,h;
-public:
- Widget(Widget *parent);
- ~Widget();
-};
diff --git a/src/main.cpp b/src/main.cpp
index 85fe70d..7bc0fb6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,6 @@
-#include "core/Core.hpp"
-#include <core/Event.hpp>
+#include "Core.hpp"
+#include "Event.hpp"
+#include "Utility.hpp"
const char *getTimeSinceProgramStart(void) {
static auto initialTime = std::chrono::steady_clock().now();
@@ -29,7 +30,7 @@ int main() {
LOG(WARNING)<<"Sizeof EventData is "<<sizeof(EventData);
Core core;
- core.Exec();
+ core.ExecuteRenderLoop();
return 0;
} \ No newline at end of file
diff --git a/src/network/Network.cpp b/src/network/Network.cpp
index 798756d..91cb481 100644
--- a/src/network/Network.cpp
+++ b/src/network/Network.cpp
@@ -1,12 +1,8 @@
#include <network/Network.hpp>
Network::Network(std::string address, unsigned short port) {
- try {
- socket = new Socket(address, port);
- stream = new StreamSocket(socket);
- } catch (std::exception &e) {
- LOG(FATAL)<<e.what();
- }
+ socket = new Socket(address, port);
+ stream = new StreamSocket(socket);
}
Network::~Network() {
diff --git a/src/network/Stream.cpp b/src/network/Stream.cpp
index 2545b48..447b13f 100644
--- a/src/network/Stream.cpp
+++ b/src/network/Stream.cpp
@@ -30,10 +30,11 @@ short StreamInput::ReadShort() {
}
unsigned short StreamInput::ReadUShort() {
- unsigned short value;
- ReadData((unsigned char *) &value, 2);
- endswap(value);
- return value;
+ unsigned char buff[2];
+ ReadData(buff, 2);
+ unsigned short val = *(reinterpret_cast<unsigned short *>(buff));
+ endswap(val);
+ return val;
}
int StreamInput::ReadInt() {
diff --git a/src/world/GameState.cpp b/src/world/GameState.cpp
index d3a6bd3..79e2f1b 100644
--- a/src/world/GameState.cpp
+++ b/src/world/GameState.cpp
@@ -1,4 +1,4 @@
-#include <world/GameState.hpp>
+#include <GameState.hpp>
GameState::GameState(NetworkClient *Net, bool &quit) : nc(Net), isRunning(quit) {
Front = glm::vec3(0.0f, 0.0f, -1.0f);
diff --git a/src/world/Section.cpp b/src/world/Section.cpp
index ff2a4fb..d97d163 100644
--- a/src/world/Section.cpp
+++ b/src/world/Section.cpp
@@ -36,10 +36,8 @@ Block &Section::GetBlock(Vector pos) {
return m_blocks[pos.GetY() * 256 + pos.GetZ() * 16 + pos.GetX()];
}
-double totalParsingTime = 0;
-
void Section::Parse() {
- if (!m_blocks.empty())
+ if (m_dataBlocks == nullptr)
return;
long long *longArray = reinterpret_cast<long long *>(m_dataBlocks);
@@ -47,28 +45,23 @@ void Section::Parse() {
endswap(&longArray[i]);
std::vector<unsigned short> blocks;
blocks.reserve(4096);
- {
- auto begin = std::chrono::steady_clock::now();
- int bitPos = 0;
- unsigned short t = 0;
- for (size_t i = 0; i < m_dataBlocksLen; i++) {
- for (int j = 0; j < 8; j++) {
- t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00;
- t >>= 1;
- m_dataBlocks[i] >>= 1;
- bitPos++;
- if (bitPos >= m_bitsPerBlock) {
- bitPos = 0;
- t >>= m_bitsPerBlock - 1;
- blocks.push_back(t);
- t = 0;
- }
+ int bitPos = 0;
+ unsigned short t = 0;
+ for (size_t i = 0; i < m_dataBlocksLen; i++) {
+ for (int j = 0; j < 8; j++) {
+ t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00;
+ t >>= 1;
+ m_dataBlocks[i] >>= 1;
+ bitPos++;
+ if (bitPos >= m_bitsPerBlock) {
+ bitPos = 0;
+ t >>= m_bitsPerBlock - 1;
+ blocks.push_back(t);
+ t = 0;
}
}
- auto end = std::chrono::steady_clock::now();
- std::chrono::duration<double, std::milli> time = end - begin;
- totalParsingTime += time.count();
}
+
std::vector<byte> light;
light.reserve(4096);
for (int i = 0; i < 2048; i++) {
@@ -83,6 +76,9 @@ void Section::Parse() {
Block block(blockId >> 4, blockId & 0xF);
m_blocks.push_back(block);
}
+ if ((light.size() + blocks.size()) / 2 != 4096) {
+ throw 118;
+ }
delete[] m_dataBlocks;
m_dataBlocksLen = 0;
m_dataBlocks = nullptr;
@@ -135,13 +131,3 @@ Section::Section(const Section &other) {
Vector Section::GetPosition() {
return worldPosition;
}
-
-size_t Section::GetHash() {
- if (m_blocks.empty()) return 0;
-
- unsigned char *from = reinterpret_cast<unsigned char *>(m_blocks.data());
- size_t length = m_blocks.size() * sizeof(Block);
-
- std::string str(from, from + length);
- return std::hash<std::string>{}(str);
-} \ No newline at end of file