diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
m--------- | external/imgui | 0 | ||||
-rw-r--r-- | src/AssetManager.cpp | 96 | ||||
-rw-r--r-- | src/AssetManager.hpp | 6 | ||||
-rw-r--r-- | src/Block.cpp | 4 | ||||
-rw-r--r-- | src/Block.hpp | 4 | ||||
-rw-r--r-- | src/GameState.cpp | 20 | ||||
-rw-r--r-- | src/GameState.hpp | 4 | ||||
-rw-r--r-- | src/Network.cpp | 13 | ||||
-rw-r--r-- | src/Packet.hpp | 198 | ||||
-rw-r--r-- | src/Render.cpp | 73 | ||||
-rw-r--r-- | src/Render.hpp | 2 | ||||
-rw-r--r-- | src/RendererSection.cpp | 234 | ||||
-rw-r--r-- | src/RendererSection.hpp | 8 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 20 | ||||
-rw-r--r-- | src/RendererWorld.hpp | 5 | ||||
-rw-r--r-- | src/Section.cpp | 46 | ||||
-rw-r--r-- | src/Section.hpp | 6 | ||||
-rw-r--r-- | src/Stream.cpp | 27 | ||||
-rw-r--r-- | src/Stream.hpp | 11 | ||||
-rw-r--r-- | src/Utility.hpp | 2 | ||||
-rw-r--r-- | src/Vector.hpp | 5 | ||||
-rw-r--r-- | src/Window.cpp | 6 | ||||
-rw-r--r-- | src/Window.hpp | 20 | ||||
-rw-r--r-- | src/World.cpp | 227 | ||||
-rw-r--r-- | src/World.hpp | 33 |
26 files changed, 687 insertions, 385 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bcef8ee..edf5588 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,6 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -include(externalProject) ########## # SOURCES @@ -72,7 +71,6 @@ find_package(OpenGL REQUIRED) target_link_libraries(AltCraft ${OPENGL_LIBRARIES}) target_include_directories(AltCraft PUBLIC ${OPENGL_INCLUDE_DIRS}) - ################# # COPY RESOURCES ################# diff --git a/external/imgui b/external/imgui deleted file mode 160000 -Subproject 7a7327addec8cde30c13d6224a121033043874b diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 6e35160..02ee7ee 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -1,6 +1,6 @@ #include <fstream> #include "AssetManager.hpp" -#include <filesystem> +#include <experimental/filesystem> namespace fs = std::experimental::filesystem::v1; @@ -15,7 +15,7 @@ const fs::path pathToModels = "./assets/minecraft/models/"; AssetManager::AssetManager() { LoadIds(); LoadTextureResources(); - //LoadBlockModels(); + LoadBlockModels(); } void AssetManager::LoadIds() { @@ -194,32 +194,58 @@ AssetManager &AssetManager::Instance() { } const BlockModel *AssetManager::GetBlockModelByBlockId(BlockId block) { - std::string blockName = ""; - for (const auto& it : assetIds) { - if (BlockId{ it.second.id,0 } == BlockId{ block.id,0 }) { - blockName = it.first; - break; + block.state = 0; + if (blockIdToBlockName.find(block) == blockIdToBlockName.end()) { + std::string blockName = ""; + for (const auto& it : assetIds) { + if (BlockId{ it.second.id,0 } == block) { + blockName = it.first; + break; + } } + if (blockName == "grass") + blockName = "grass_normal"; + if (blockName == "torch") + blockName = "normal_torch"; + if (blockName == "leaves") + blockName = "oak_leaves"; + if (blockName == "tallgrass") + blockName = "tall_grass"; + if (blockName == "log") + blockName = "oak_bark"; + if (blockName == "snow_layer") + blockName = "snow_height2"; + + blockName = "block/" + blockName; + + if (blockName == "") + return nullptr; + + blockIdToBlockName[block] = blockName; } - blockName = "block/" + blockName; + std::string blockName = blockIdToBlockName[block]; - if (blockName == "" || models.find(blockName) == models.end()) + auto modelIt = models.find(blockName); + if (modelIt == models.end()) return nullptr; - - return &models[blockName]; + + return &modelIt->second; } void AssetManager::LoadBlockModels() { std::function<void(std::string)> parseModel = [&](std::string ModelName) { + if (models.find(ModelName) != models.end()) + return; + fs::path ModelPath = pathToModels / fs::path(ModelName + ".json"); std::ifstream in(ModelPath); if (!in.is_open()) throw std::runtime_error("Trying to load unknown model \"" + ModelName + "\" at " + ModelPath.generic_string()); nlohmann::json modelData; in >> modelData; - BlockModel model; + BlockModel model; if (modelData.find("parent") != modelData.end()) { if (models.find(modelData["parent"]) == models.end()) @@ -228,6 +254,14 @@ void AssetManager::LoadBlockModels() { model = models.find(modelData["parent"])->second; } + model.BlockName = ModelName; + + if (model.BlockName == "block/block") + model.IsBlock = true; + + if (model.BlockName == "block/thin_block" || model.BlockName=="block/leaves") + model.IsBlock = false; + if (modelData.find("ambientocclusion") != modelData.end()) model.AmbientOcclusion = modelData["ambientocclusion"].get<bool>(); @@ -240,6 +274,7 @@ void AssetManager::LoadBlockModels() { } if (modelData.find("elements") != modelData.end()) { + model.Elements.clear(); for (auto& it : modelData["elements"]) { BlockModel::ElementData element; @@ -257,8 +292,11 @@ void AssetManager::LoadBlockModels() { element.rotationOrigin = rotOrig; element.rotationAxis = (it["rotation"]["axis"].get<std::string>() == "x") ? BlockModel::ElementData::Axis::x : ((it["rotation"]["axis"].get<std::string>() == "y") ? BlockModel::ElementData::Axis::y : BlockModel::ElementData::Axis::z); - element.rotationAngle = it["rotation"]["angle"].get<int>(); - element.rotationRescale = it["rotation"]["recale"].get<bool>(); + if (it["rotation"].find("angle") != it["rotation"].end()) + element.rotationAngle = it["rotation"]["angle"].get<int>(); + + if (it["rotation"].find("rescale") != it["rotation"].end()) + element.rotationRescale = it["rotation"]["rescale"].get<bool>(); } if (it.find("shade") != it.end()) @@ -291,7 +329,7 @@ void AssetManager::LoadBlockModels() { faceData.uv = uv; } - BlockModel::ElementData::FaceDirection cullface; + BlockModel::ElementData::FaceDirection cullface = faceDir; if (face.find("cullface") != face.end()) { if (face["cullface"] == "down") cullface = BlockModel::ElementData::FaceDirection::down; @@ -304,9 +342,9 @@ void AssetManager::LoadBlockModels() { else if (face["cullface"] == "west") cullface = BlockModel::ElementData::FaceDirection::west; else if (face["cullface"] == "east") - cullface = BlockModel::ElementData::FaceDirection::east; - faceData.cullface = cullface; - } + cullface = BlockModel::ElementData::FaceDirection::east; + } + faceData.cullface = cullface; faceData.texture = face["texture"].get<std::string>(); @@ -314,7 +352,7 @@ void AssetManager::LoadBlockModels() { faceData.rotation = face["rotation"].get<int>(); if (face.find("tintindex") != face.end()) - faceData.tintIndex = face["tintindex"]; + faceData.tintIndex = true; element.faces[faceDir] = faceData; } @@ -326,12 +364,24 @@ void AssetManager::LoadBlockModels() { models.insert(std::make_pair(ModelName, model)); }; - parseModel("block/stone"); + fs::path pathToBlockModels = pathToModels.generic_string() + "/block/"; - /*for (auto& dirEntry : fs::directory_iterator(pathToBlockModels)) { + for (auto& dirEntry : fs::recursive_directory_iterator(pathToBlockModels)) { if (dirEntry.path().extension() != ".json") continue; + + std::string modelName = dirEntry.path().stem().generic_string(); + + parseModel("block/" + modelName); + } +} - parseModel(dirEntry.path().generic_string()); - }*/ +std::string AssetManager::GetAssetNameByBlockId(BlockId block) { + for (auto& it : assetIds) { + BlockId value = it.second; + value.state = 0; + if (value == block) + return it.first; + } + return "#NF"; }
\ No newline at end of file diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index 96f9741..50d9bbf 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -55,6 +55,9 @@ struct BlockTextureId { }; struct BlockModel { + bool IsBlock = false; + std::string BlockName; + bool AmbientOcclusion=true; enum DisplayVariants { @@ -123,6 +126,7 @@ class AssetManager { std::map<std::string, TextureCoordinates> assetTextures; std::map<BlockTextureId,glm::vec4> textureAtlasIndexes; std::map<std::string, BlockModel> models; + std::map<BlockId, std::string> blockIdToBlockName; public: AssetManager(); @@ -147,4 +151,6 @@ public: const BlockModel *GetBlockModelByBlockId(BlockId block); void LoadBlockModels(); + + std::string GetAssetNameByBlockId(BlockId block); }; diff --git a/src/Block.cpp b/src/Block.cpp index 840dbcf..667670d 100644 --- a/src/Block.cpp +++ b/src/Block.cpp @@ -8,4 +8,8 @@ Block::Block() : id(0), state(0), light(0), sky(0) {} bool operator==(const BlockId& lhs, const BlockId &rhs) { return (lhs.id == rhs.id) && (lhs.state == rhs.state); +} + +bool operator<(const BlockId& lhs, const BlockId &rhs) { + return (lhs.id < rhs.id); }
\ No newline at end of file diff --git a/src/Block.hpp b/src/Block.hpp index 78c9cca..c3dfcec 100644 --- a/src/Block.hpp +++ b/src/Block.hpp @@ -18,4 +18,6 @@ struct BlockId { unsigned char state : 4; }; -bool operator==(const BlockId& lhs, const BlockId &rhs);
\ No newline at end of file +bool operator==(const BlockId& lhs, const BlockId &rhs); + +bool operator<(const BlockId& lhs, const BlockId &rhs);
\ No newline at end of file diff --git a/src/GameState.cpp b/src/GameState.cpp index b9f9b28..46b236c 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -144,10 +144,20 @@ void GameState::UpdatePacket() break; case CloseWindowCB: break; - case OpenWindow: + case OpenWindow: { + auto packet = std::static_pointer_cast<PacketOpenWindow>(ptr); + + LOG(INFO) << "Open new window " << packet->WindowTitle << ": " << packet->WindowId; break; - case WindowItems: + } + case WindowItems: { + auto packet = std::static_pointer_cast<PacketWindowItems>(ptr); + if (packet->WindowId == 0) { + playerInventory.WindowId = 0; + playerInventory.slots = packet->SlotData; + } break; + } case WindowProperty: break; case SetSlot: @@ -392,6 +402,10 @@ void GameState::UpdatePacket() } ptr = nc->ReceivePacket(); } + while (!playerInventory.pendingTransactions.empty()) { + nc->SendPacket(std::make_shared<PacketClickWindow>(playerInventory.pendingTransactions.front())); + playerInventory.pendingTransactions.pop(); + } } void GameState::HandleMovement(GameState::Direction direction, float deltaTime) { @@ -419,7 +433,7 @@ void GameState::HandleMovement(GameState::Direction direction, float deltaTime) break; case JUMP: if (g_OnGround) { - vel.y += 5; + vel.y += 10; g_OnGround = false; } break; diff --git a/src/GameState.hpp b/src/GameState.hpp index 6dbb194..659f829 100644 --- a/src/GameState.hpp +++ b/src/GameState.hpp @@ -8,6 +8,7 @@ #include "NetworkClient.hpp" #include "Vector.hpp" #include "Event.hpp" +#include "Window.hpp" class GameState { std::shared_ptr<NetworkClient> nc; @@ -73,4 +74,7 @@ public: long long TimeOfDay = 0; std::shared_ptr<GameState> gs; + + Window playerInventory; + std::vector<Window> openedWindows; }; diff --git a/src/Network.cpp b/src/Network.cpp index 4606959..cf4fe15 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -47,6 +47,7 @@ std::shared_ptr<Packet> Network::ReceivePacketByPacketId(int packetId, Connectio packet = std::make_shared<PacketHandshake>(); break; } + break; case Login: switch (packetId) { case PacketNameLoginCB::LoginSuccess: @@ -102,17 +103,17 @@ std::shared_ptr<Packet> Network::ParsePacketPlay(PacketNamePlayCB id) { case MultiBlockChange: return std::make_shared<PacketMultiBlockChange>(); case ConfirmTransactionCB: - break; + return std::make_shared<PacketConfirmTransactionCB>(); case CloseWindowCB: - break; + return std::make_shared<PacketCloseWindowCB>(); case OpenWindow: - break; + return std::make_shared<PacketOpenWindow>(); case WindowItems: - break; + return std::make_shared<PacketWindowItems>(); case WindowProperty: - break; + return std::make_shared<PacketWindowProperty>(); case SetSlot: - break; + return std::make_shared<PacketSetSlot>(); case SetCooldown: break; case PluginMessageCB: diff --git a/src/Packet.hpp b/src/Packet.hpp index d1d80e6..e00f1ed 100644 --- a/src/Packet.hpp +++ b/src/Packet.hpp @@ -1,7 +1,5 @@ #pragma once -#include <easylogging++.h> - #include "Stream.hpp" enum PacketNameLoginSB { @@ -417,7 +415,7 @@ struct PacketChunkData : Packet { stream->WriteVarInt(Data.size()); stream->WriteByteArray(Data); stream->WriteVarInt(BlockEntities.size()); - LOG(FATAL) << "Serializing unimplemented packet"; + //LOG(FATAL) << "Serializing unimplemented packet"; } void FromStream(StreamInput *stream) override { @@ -587,11 +585,10 @@ struct PacketEntityLookAndRelativeMove : Packet { DeltaX = stream->ReadShort(); DeltaY = stream->ReadShort(); DeltaZ = stream->ReadShort(); - return; //TODO: WTF? - Yaw = stream->ReadAngle(); + /*Yaw = stream->ReadAngle(); Pitch = stream->ReadAngle(); - OnGround = stream->ReadBool(); + OnGround = stream->ReadBool();*/ } int GetPacketId() override { @@ -837,4 +834,193 @@ struct PacketUnloadChunk : Packet { int ChunkX; int ChunkZ; +}; + +struct PacketCloseWindowCB : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadUByte(); + } + + int GetPacketId() override { + return PacketNamePlayCB::CloseWindowCB; + } + + unsigned char WindowId; +}; + +struct PacketOpenWindow : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadUByte(); + WindowType = stream->ReadString(); + WindowTitle = stream->ReadChat(); + NumberOfSlots = stream->ReadUByte(); + + if (WindowType == "EntityHorse") + EntityId = stream->ReadInt(); + } + + int GetPacketId() override { + return PacketNamePlayCB::OpenWindow; + } + + unsigned char WindowId; + std::string WindowType; + std::string WindowTitle; + unsigned char NumberOfSlots; + int EntityId; +}; + +struct PacketWindowItems : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadUByte(); + short count = stream->ReadShort(); + for (int i = 0; i < count; i++) + SlotData.push_back(stream->ReadSlot()); + } + + int GetPacketId() override { + return PacketNamePlayCB::WindowItems; + } + + unsigned char WindowId; + std::vector<SlotData> SlotData; +}; + +struct PacketWindowProperty : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadUByte(); + Property = stream->ReadShort(); + Value = stream->ReadShort(); + } + + int GetPacketId() override { + return PacketNamePlayCB::WindowProperty; + } + + unsigned char WindowId; + short Property; + short Value; +}; + +struct PacketSetSlot : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadByte(); + Slot = stream->ReadShort(); + SlotData = stream->ReadSlot(); + } + + int GetPacketId() override { + return PacketNamePlayCB::SetSlot; + } + + signed char WindowId; + short Slot; + SlotData SlotData; +}; + +struct PacketConfirmTransactionCB : Packet { + void ToStream(StreamOutput *stream) override { + + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadByte(); + ActionNumber = stream->ReadShort(); + Accepted = stream->ReadBool(); + } + + int GetPacketId() override { + return PacketNamePlayCB::ConfirmTransactionCB; + } + + signed char WindowId; + short ActionNumber; + bool Accepted; +}; + +struct PacketConfirmTransactionSB : Packet { + void ToStream(StreamOutput *stream) override { + stream->WriteByte(WindowId); + stream->WriteShort(ActionNumber); + stream->WriteBool(Accepted); + } + + void FromStream(StreamInput *stream) override { + WindowId = stream->ReadByte(); + ActionNumber = stream->ReadShort(); + Accepted = stream->ReadBool(); + } + + int GetPacketId() override { + return PacketNamePlaySB::ConfirmTransactionSB; + } + + signed char WindowId; + short ActionNumber; + bool Accepted; +}; + +struct PacketClickWindow : Packet { + void ToStream(StreamOutput *stream) override { + stream->WriteUByte(WindowId); + stream->WriteShort(Slot); + stream->WriteByte(Button); + stream->WriteShort(ActionNumber); + stream->WriteInt(Mode); + stream->WriteSlot(ClickedItem); + } + + void FromStream(StreamInput *stream) override { + + } + + int GetPacketId() override { + return PacketNamePlaySB::ClickWindow; + } + + unsigned char WindowId; + short Slot; + signed char Button; + short ActionNumber; + int Mode; + SlotData ClickedItem; + + PacketClickWindow(unsigned char windowId, short slot, signed char button, short actionNumber, int mode, SlotData ClickedItem) : WindowId(windowId), Slot(slot), + Button(button), ActionNumber(actionNumber), Mode(mode), ClickedItem(ClickedItem) {}; +}; + +struct PacketCloseWindowSB : Packet { + void ToStream(StreamOutput *stream) override { + stream->WriteUByte(WindowId); + } + + void FromStream(StreamInput *stream) override { + + } + + int GetPacketId() override { + return PacketNamePlaySB::CloseWindowSB; + } + + unsigned char WindowId; };
\ No newline at end of file diff --git a/src/Render.cpp b/src/Render.cpp index 0504d0a..2382ec2 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -16,6 +16,8 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight, std::string glCheckError(); PrepareToRendering(); glCheckError(); + + LOG(INFO) << "Supported threads: " << std::thread::hardware_concurrency(); } Render::~Render() { @@ -60,10 +62,11 @@ void Render::InitGlew() { int width, height; SDL_GL_GetDrawableSize(window, &width, &height); glViewport(0, 0, width, height); + glClearColor(0.8,0.8,0.8, 1.0f); glEnable(GL_DEPTH_TEST); - /*glEnable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glCullFace(GL_BACK); - glFrontFace(GL_CCW);*/ + glFrontFace(GL_CCW); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glCheckError(); @@ -102,13 +105,15 @@ void Render::UpdateKeyboard() { } } -void Render::RenderFrame() { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); +void Render::RenderFrame() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + if (isWireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); if (renderWorld) world->Render(renderState); + if (isWireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); if (world) { world->Update(timer.RemainTimeMs()); @@ -141,11 +146,13 @@ void Render::HandleEvents() { break; } case SDL_WINDOWEVENT_FOCUS_GAINED: + HasFocus = true; break; case SDL_WINDOWEVENT_FOCUS_LOST: HasFocus = false; SetMouseCapture(false); - state = GlobalState::Paused; + if (state == GlobalState::Playing) + state = GlobalState::Paused; break; } break; @@ -156,6 +163,7 @@ void Render::HandleEvents() { if (state == GlobalState::Playing) { state = GlobalState::Paused; SetMouseCapture(false); + isDisplayInventory = false; } else if (state == GlobalState::Paused) { state = GlobalState::Playing; @@ -166,8 +174,14 @@ void Render::HandleEvents() { isRunning = false; } break; + case SDL_SCANCODE_E: + if (state != GlobalState::Playing) + return; + isDisplayInventory = !isDisplayInventory; + SetMouseCapture(!isDisplayInventory); + break; } - break; + break; case SDL_MOUSEMOTION: if (isMouseCaptured) { double deltaX = event.motion.xrel; @@ -207,7 +221,7 @@ void Render::ExecuteRenderLoop() { listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) { auto data = std::get<ConnectionSuccessfullData>(eventData); - stateString = "Logging in..."; + stateString = "Logging in..."; }); listener.RegisterHandler(EventType::PlayerConnected, [this](EventData eventData) { @@ -221,6 +235,7 @@ void Render::ExecuteRenderLoop() { renderWorld = true; state = GlobalState::Playing; SetMouseCapture(true); + glClearColor(0, 0, 0, 1.0f); }); listener.RegisterHandler(EventType::ConnectionFailed, [this](EventData eventData) { @@ -228,6 +243,7 @@ void Render::ExecuteRenderLoop() { renderWorld = false; world.reset(); state = GlobalState::MainMenu; + glClearColor(0.8, 0.8, 0.8, 1.0f); }); listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) { @@ -235,6 +251,8 @@ void Render::ExecuteRenderLoop() { renderWorld = false; world.reset(); state = GlobalState::MainMenu; + SetMouseCapture(false); + glClearColor(0.8, 0.8, 0.8, 1.0f); }); listener.RegisterHandler(EventType::Connecting, [this](EventData eventData) { @@ -246,13 +264,14 @@ void Render::ExecuteRenderLoop() { while (isRunning) { HandleEvents(); - if (HasFocus) UpdateKeyboard(); + if (HasFocus && state == GlobalState::Playing) UpdateKeyboard(); if (isMouseCaptured) HandleMouseCapture(); glCheckError(); RenderFrame(); - while (listener.IsEventsQueueIsNotEmpty()) - listener.HandleEvent(); + while (listener.IsEventsQueueIsNotEmpty()) { + listener.HandleEvent(); + } timer.Update(); } EventAgregator::PushEvent(EventType::Exit, ExitData{}); @@ -279,6 +298,8 @@ void Render::RenderGui() { ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f/gameTime, gameTime); ImGui::Text("Sections loaded: %d", (int)DebugInfo::totalSections); ImGui::Text("SectionsRenderer: %d (%d)", (int)DebugInfo::renderSections, (int)DebugInfo::readyRenderer); + if (world) + ImGui::Text("Player pos: %.1f %.1f %.1f", world->GameStatePtr()->g_PlayerX, world->GameStatePtr()->g_PlayerY, world->GameStatePtr()->g_PlayerZ); ImGui::End(); @@ -302,6 +323,29 @@ void Render::RenderGui() { case GlobalState::Loading: break; case GlobalState::Playing: + if (isDisplayInventory) { + ImGui::SetNextWindowPosCenter(); + ImGui::Begin("Inventory", 0, windowFlags); + Window& inventory = world->GameStatePtr()->playerInventory; + for (int i = 0; i < inventory.slots.size()+1; i++) { + SlotData slot; + if (i == inventory.slots.size()) + slot = inventory.handSlot; + else + slot = inventory.slots[i]; + + if (slot.BlockId == -1) { + ImGui::Button("Empty"); + continue; + } + std::string slotName = AssetManager::Instance().GetAssetNameByBlockId(BlockId{(unsigned short) slot.BlockId,0 }); + if (ImGui::Button((slotName + "##"+std::to_string(i)).c_str())) { + inventory.MakeClick(i, true); + LOG(INFO) << "Clicked " << slotName << "("<<slot.BlockId<<") in slot " << i; + } + } + ImGui::End(); + } break; case GlobalState::Paused: { ImGui::SetNextWindowPosCenter(); @@ -317,13 +361,20 @@ void Render::RenderGui() { static float sense = sensetivity; ImGui::SliderFloat("Sensetivity", &sense, 0.01f, 1.0f); + static bool wireframe = isWireframe; + + ImGui::Checkbox("Wireframe", &wireframe); + if (ImGui::Button("Apply settings")) { if (distance != world->MaxRenderingDistance) { world->MaxRenderingDistance = distance; EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); } + if (sense != sensetivity) sensetivity = sense; + + isWireframe = wireframe; } ImGui::Separator(); diff --git a/src/Render.hpp b/src/Render.hpp index 0b67218..2a48356 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -21,6 +21,8 @@ class Render { std::map<SDL_Scancode, bool> isKeyPressed; bool HasFocus=true; float sensetivity = 0.1f; + bool isWireframe = false; + bool isDisplayInventory = false; enum GlobalState { InitialLoading, diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp index 2b5fc1e..22acc61 100644 --- a/src/RendererSection.cpp +++ b/src/RendererSection.cpp @@ -170,9 +170,7 @@ size_t RendererSection::GetHash() RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) { const std::map<BlockTextureId, glm::vec4> &textureAtlas = AssetManager::Instance().GetTextureAtlasIndexes(); - if (!world->GetSection(sectionPosition)) - return; - const Section §ion = *world->GetSection(sectionPosition); + const Section §ion = world->GetSection(sectionPosition); hash = section.GetHash(); sectionPos = sectionPosition; @@ -187,217 +185,72 @@ RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) if (block.id == 0) continue; - /*transform = glm::translate(baseOffset, Vector(x, y, z).glm()); + const bool useNewMethod = true; + + + transform = glm::translate(baseOffset, Vector(x, y, z).glm()); const BlockModel* model = AssetManager::Instance().GetBlockModelByBlockId(block); - if (model ) { - this->AddFacesByBlockModel(world, Vector(x,y,z), *model, transform, section.GetBlockLight(Vector(x,y,z)),section.GetBlockSkyLight(Vector(x,y,z))); - } else { + if (model) { + this->AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, section.GetBlockLight(Vector(x, y, z)), section.GetBlockSkyLight(Vector(x, y, z))); + } + else { transform = glm::translate(transform, glm::vec3(0, 1, 0)); + + if (block.id == 8 || block.id == 9) { + textures.push_back(AssetManager::Instance().GetTextureByAssetName("minecraft/textures/blocks/water_still")); + textures.back().w /= 32.0f; + transform = glm::translate(transform, glm::vec3(0, -0.2, 0)); + } else + textures.push_back(AssetManager::Instance().GetTextureByAssetName("minecraft/textures/blocks/tnt_side")); + models.push_back(transform); - textures.push_back(glm::vec4(0.0546875, 0.00442477876106194690, 0.0078125, 0.00442477876106194690)); //Fallback TNT texture colors.push_back(glm::vec3(0, 0, 0)); lights.push_back(glm::vec2(16, 16)); - }*/ - - auto testBlockNonExist = [&](Vector block) -> bool { - Vector offset; - if (block.x == -1) { - offset = Vector(-1, 0, 0); - block.x = 15; - } else if (block.x == 16) { - offset = Vector(1, 0, 0); - block.x = 0; - } else if (block.y == -1) { - offset = Vector(0, -1, 0); - block.y = 15; - } else if (block.y == 16) { - offset = Vector(0, 1, 0); - block.y = 0; - } else if (block.z == -1) { - offset = Vector(0, 0, -1); - block.z = 15; - } else if (block.z == 16) { - offset = Vector(0, 0, 1); - block.z = 0; - } - if (offset != Vector(0, 0, 0)) { - if (std::find(sectionsList.begin(), sectionsList.end(), sectionPosition + offset) == sectionsList.end()) - return true; - const Section& blockSection = *world->GetSection(sectionPosition + offset); - return blockSection.GetBlockId(block).id == 0 || blockSection.GetBlockId(block).id == 31 || blockSection.GetBlockId(block).id == 18; - } - return section.GetBlockId(block).id == 0 || section.GetBlockId(block).id == 31 || section.GetBlockId(block).id == 18; - }; - - unsigned char isVisible = 0; - isVisible |= testBlockNonExist(Vector(x - 1, y, z)) << 0; - isVisible |= testBlockNonExist(Vector(x + 1, y, z)) << 1; - isVisible |= testBlockNonExist(Vector(x, y + 1, z)) << 2; - isVisible |= testBlockNonExist(Vector(x, y - 1, z)) << 3; - isVisible |= testBlockNonExist(Vector(x, y, z - 1)) << 4; - isVisible |= testBlockNonExist(Vector(x, y, z + 1)) << 5; - - if (isVisible == 0x00) - continue; - - glm::mat4 transform; - transform = glm::translate(transform, glm::vec3(sectionPosition * 16u)); - 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); - lights.push_back(glm::vec2(0, 0)); - } - 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); - lights.push_back(glm::vec2(0, 0)); - } - 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); - lights.push_back(glm::vec2(0, 0)); - } - 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); - lights.push_back(glm::vec2(0, 0)); - } - 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); - lights.push_back(glm::vec2(0, 0)); - } - 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); - lights.push_back(glm::vec2(0, 0)); - } - 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); - lights.push_back(glm::vec2(0, 0)); - } } } - } + } textures.shrink_to_fit(); models.shrink_to_fit(); colors.shrink_to_fit(); } -void RendererSectionData::AddFacesByBlockModel(World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight) { +void RendererSectionData::AddFacesByBlockModel(const std::vector<Vector> §ionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight) { glm::mat4 elementTransform, faceTransform; for (const auto& element : model.Elements) { - VectorF elementSize(VectorF(element.to - element.from) / 16.0f); - VectorF elementOrigin(VectorF(element.from) / 16.0f); + Vector t = element.to - element.from; + VectorF elementSize(VectorF(t.x,t.y,t.z) / 16.0f); + VectorF elementOrigin(VectorF(element.from.x,element.from.y,element.from.z) / 16.0f); elementTransform = glm::translate(transform, elementOrigin.glm()); - elementTransform = glm::scale(elementTransform, elementSize.glm()); + elementTransform = glm::scale(elementTransform, elementSize.glm()); for (const auto& face : element.faces) { if (face.second.cullface != BlockModel::ElementData::FaceDirection::none) { switch (face.second.cullface) { case BlockModel::ElementData::FaceDirection::down: - if (TestBlockExists(world, blockPos - Vector(0, -1, 0))) + if (TestBlockExists(sectionsList, world, blockPos - Vector(0, +1, 0))) continue; break; case BlockModel::ElementData::FaceDirection::up: - if (TestBlockExists(world, blockPos - Vector(0, +1, 0))) + if (TestBlockExists(sectionsList, world, blockPos - Vector(0, -1, 0))) continue; break; case BlockModel::ElementData::FaceDirection::north: - if (TestBlockExists(world, blockPos - Vector(0, 0, -1))) + if (TestBlockExists(sectionsList, world, blockPos - Vector(0, 0, -1))) continue; break; case BlockModel::ElementData::FaceDirection::south: - if (TestBlockExists(world, blockPos - Vector(0, 0, +1))) + if (TestBlockExists(sectionsList, world, blockPos - Vector(0, 0, +1))) continue; break; case BlockModel::ElementData::FaceDirection::west: - if (TestBlockExists(world, blockPos - Vector(-1, 0, 0))) + if (TestBlockExists(sectionsList, world, blockPos - Vector(-1, 0, 0))) continue; break; case BlockModel::ElementData::FaceDirection::east: - if (TestBlockExists(world, blockPos - Vector(+1, 0, 0))) + if (TestBlockExists(sectionsList, world, blockPos - Vector(+1, 0, 0))) continue; break; } @@ -443,41 +296,48 @@ void RendererSectionData::AddFacesByBlockModel(World *world, Vector blockPos, co } glm::vec4 texture = AssetManager::Instance().GetTextureByAssetName("minecraft/textures/" + textureName); textures.push_back(texture); - colors.push_back(glm::vec3(0, 0, 0)); + if (face.second.tintIndex) + colors.push_back(glm::vec3(0.275, 0.63, 0.1)); + else + colors.push_back(glm::vec3(0, 0, 0)); lights.push_back(glm::vec2(light, skyLight)); } } } -bool RendererSectionData::TestBlockExists(World *world, Vector blockPos) { +bool RendererSectionData::TestBlockExists(const std::vector<Vector> §ionsList, World *world, Vector blockPos) { Vector section = sectionPos; if (blockPos.x == -1) { - section = section - Vector(-1, 0, 0); + section = section + Vector(-1, 0, 0); blockPos.x = 15; } else if (blockPos.x == 16) { - section = section - Vector(+1, 0, 0); + section = section + Vector(+1, 0, 0); blockPos.x = 0; } else if (blockPos.y == -1) { - section = section - Vector(0, -1, 0); + section = section + Vector(0, -1, 0); blockPos.y = 15; } else if (blockPos.y == 16) { - section = section - Vector(0, +1, 0); + section = section + Vector(0, +1, 0); blockPos.y = 0; } else if (blockPos.z == -1) { - section = section - Vector(0, 0, -1); + section = section + Vector(0, 0, -1); blockPos.z = 15; } else if (blockPos.z == 16) { - section = section - Vector(0, 0, +1); + section = section + Vector(0, 0, +1); blockPos.z = 0; } - auto ptr = world->GetSection(sectionPos); - if (!ptr) + + if (std::find(sectionsList.begin(), sectionsList.end(),section) == sectionsList.end()) return true; - return ptr->GetBlockId(blockPos).id != 0; + BlockId blockId = world->GetSection(section).GetBlockId(blockPos); + + auto blockModel = AssetManager::Instance().GetBlockModelByBlockId(world->GetSection(section).GetBlockId(blockPos)); + + return blockId.id != 0 && blockModel && blockModel->IsBlock; }
\ No newline at end of file diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp index 9931239..1c7fc3d 100644 --- a/src/RendererSection.hpp +++ b/src/RendererSection.hpp @@ -21,11 +21,11 @@ struct RendererSectionData { size_t hash; Vector sectionPos; - bool TestBlockExists(World *world, Vector blockPos); - - void AddFacesByBlockModel(World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight); - RendererSectionData(World *world, Vector sectionPosition); +private: + bool TestBlockExists(const std::vector<Vector> §ionsList, World *world, Vector blockPos); + + void AddFacesByBlockModel(const std::vector<Vector> §ionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight); }; class RendererSection { enum Vbos { diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index a0cb8a7..3e5868b 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -13,7 +13,7 @@ void RendererWorld::WorkerFunction(size_t workerId) { sectionsMutex.lock(); auto result = sections.find(vec); if (result != sections.end()) { - if (result->second.GetHash() != gs->world.GetSection(result->first)->GetHash()) { + if (result->second.GetHash() != gs->world.GetSection(result->first).GetHash()) { sectionsMutex.unlock(); RendererSectionData data(&gs->world, vec); renderDataMutex.lock(); @@ -76,7 +76,9 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) playerChunk.y = std::floor(gs->g_PlayerY / 16.0); std::sort(suitableChunks.begin(), suitableChunks.end(), [playerChunk](Vector lhs, Vector rhs) { - return (playerChunk - lhs).GetLength() < (playerChunk - rhs).GetLength(); + double leftLengthToPlayer = (playerChunk - lhs).GetLength(); + double rightLengthToPlayer = (playerChunk - rhs).GetLength(); + return leftLengthToPlayer < rightLengthToPlayer; }); for (auto& it : suitableChunks) { @@ -86,7 +88,7 @@ void RendererWorld::UpdateAllSections(VectorF playerPos) RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) { MaxRenderingDistance = 1; - numOfWorkers = 1; + numOfWorkers = std::thread::hardware_concurrency() - 2; PrepareRender(); @@ -105,7 +107,7 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) { listener.RegisterHandler(EventType::NewRenderDataAvailable,[this](EventData eventData) { renderDataMutex.lock(); int i = 0; - while (!renderData.empty() && i<20) { + while (!renderData.empty() && i++ < 20) { auto &data = renderData.front(); isParsingMutex.lock(); if (isParsing[data.sectionPos] != true) @@ -188,8 +190,6 @@ RendererWorld::RendererWorld(std::shared_ptr<GameState> ptr):gs(ptr) { workers.push_back(std::thread(&RendererWorld::WorkerFunction, this, i)); EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); - - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } RendererWorld::~RendererWorld() { @@ -226,7 +226,7 @@ void RendererWorld::Render(RenderState & renderState) { glCheckError(); sectionsMutex.lock(); - for (auto& section : sections) { + for (auto& section : sections) { sectionsMutex.unlock(); std::vector<Vector> sectionCorners = { Vector(0, 0, 0), @@ -253,7 +253,7 @@ void RendererWorld::Render(RenderState & renderState) { } double lengthToSection = (VectorF(gs->g_PlayerX, gs->g_PlayerY, gs->g_PlayerZ) - VectorF(section.first.x*16,section.first.y*16,section.first.z*16)).GetLength(); - if (isBreak && lengthToSection > 30.0f) { + if (isBreak && lengthToSection > 30.0f && false) { sectionsMutex.lock(); continue; } @@ -364,3 +364,7 @@ void RendererWorld::Update(double timeToUpdate) { DebugInfo::readyRenderer = this->renderData.size(); DebugInfo::renderSections = this->sections.size(); } + +GameState* RendererWorld::GameStatePtr() { + return gs.get(); +}
\ No newline at end of file diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp index 4e098e5..751f1a7 100644 --- a/src/RendererWorld.hpp +++ b/src/RendererWorld.hpp @@ -20,6 +20,8 @@ class RendererWorld { std::mutex isParsingMutex; std::map<Vector, bool> isParsing; //Blocks + std::mutex renderDataMutex; + std::queue<RendererSectionData> renderData; std::vector<Vector> renderList; std::mutex sectionsMutex; std::map<Vector, RendererSection> sections; @@ -43,6 +45,5 @@ public: void Update(double timeToUpdate); - std::mutex renderDataMutex; - std::queue<RendererSectionData> renderData; + GameState *GameStatePtr(); };
\ No newline at end of file diff --git a/src/Section.cpp b/src/Section.cpp index 554cdbf..67dde70 100644 --- a/src/Section.cpp +++ b/src/Section.cpp @@ -2,14 +2,26 @@ #include <bitset> -void Section::CalculateHash() { - std::vector<unsigned char> rawData; - rawData.reserve(block.size() * sizeof(long long) + light.size() + sky.size()); - std::copy(block.begin(), block.end(), std::back_inserter(rawData)); - std::copy(light.begin(), light.end(), std::back_inserter(rawData)); +void Section::CalculateHash() const { + size_t offset = 0; + + std::vector<unsigned char> rawData; + rawData.resize(block.size() * sizeof(long long) + light.size() + sky.size()); + + std::memcpy(rawData.data() + offset, block.data(), block.size() * sizeof(BlockId)); + offset += block.size() * sizeof(BlockId); + + std::memcpy(rawData.data() + offset, light.data(), light.size() * sizeof(unsigned char)); + offset += light.size() * sizeof(unsigned char); + if (!sky.empty()) - std::copy(sky.begin(), sky.end(), std::back_inserter(rawData)); + std::memcpy(rawData.data() + offset, sky.data(), sky.size() * sizeof(unsigned char)); + for (auto& it : overrideList) { + rawData.push_back(*reinterpret_cast<const unsigned short*> (&it.second) & 0xF); + rawData.push_back(*reinterpret_cast<const unsigned short*> (&it.second) >> 0xF); + } + const unsigned char *from = reinterpret_cast<const unsigned char *>(rawData.data()); size_t length = rawData.size(); @@ -30,12 +42,10 @@ Section::Section(Vector pos, unsigned char bitsPerBlock, std::vector<unsigned sh this->light = std::move(lightData); this->sky = std::move(skyData); - CalculateHash(); + hash = -1; } -Section::Section() { - - CalculateHash(); +Section::Section():hash(-1),bitsPerBlock(0) { } Section::~Section() { @@ -45,19 +55,24 @@ Section::~Section() { Section::Section(Section && other) noexcept { using std::swap; swap(*this, other); - CalculateHash(); + hash = -1; } Section &Section::operator=(Section other) noexcept { using std::swap; swap(*this, other); - CalculateHash(); + hash = -1; return *this; } BlockId Section::GetBlockId(Vector pos) const { if (block.empty()) return BlockId{ 0,0 }; + + auto iter = overrideList.find(pos); + if (iter != overrideList.end()) + return iter->second; + int value; unsigned char individualValueMask = ((1 << bitsPerBlock) - 1); @@ -67,7 +82,7 @@ BlockId Section::GetBlockId(Vector pos) const { int startOffset = (blockNumber * bitsPerBlock) % 64; int endLong = ((blockNumber + 1) * bitsPerBlock - 1) / 64; - unsigned short t; + unsigned char t; if (startLong == endLong) { t = (block[startLong] >> startOffset); @@ -108,7 +123,8 @@ unsigned char Section::GetBlockSkyLight(Vector pos) const } void Section::SetBlockId(Vector pos, BlockId value) { - LOG(WARNING) << "Block changing not implemented!"; + overrideList[pos] = value; + hash = -1; } void swap(Section& lhs, Section& rhs) noexcept { @@ -137,5 +153,7 @@ Vector Section::GetPosition() const { } size_t Section::GetHash() const { + if (hash == -1) + CalculateHash(); return hash; }
\ No newline at end of file diff --git a/src/Section.hpp b/src/Section.hpp index 7a7a3d0..41bef7b 100644 --- a/src/Section.hpp +++ b/src/Section.hpp @@ -19,9 +19,11 @@ class Section { std::vector<unsigned short> palette; Vector worldPosition; - size_t hash; + mutable size_t hash; - void CalculateHash(); + void CalculateHash() const; + + std::map<Vector, BlockId> overrideList; public: Section(Vector pos, unsigned char bitsPerBlock, std::vector<unsigned short> palette, std::vector<long long> blockData, std::vector<unsigned char> lightData, std::vector<unsigned char> skyData); diff --git a/src/Stream.cpp b/src/Stream.cpp index 28680c6..665247d 100644 --- a/src/Stream.cpp +++ b/src/Stream.cpp @@ -118,14 +118,28 @@ long long StreamInput::ReadVarLong() { } std::vector<unsigned char> StreamInput::ReadEntityMetadata() { + LOG(FATAL) << "Reading EntityMetadata is not implemented"; return std::vector<unsigned char>(); } -std::vector<unsigned char> StreamInput::ReadSlot() { - return std::vector<unsigned char>(); +SlotData StreamInput::ReadSlot() { + SlotData slot; + slot.BlockId = ReadShort(); + + if (slot.BlockId == -1) + return slot; + + slot.ItemCount = ReadByte(); + slot.ItemDamage = ReadShort(); + + if (ReadByte() != 0) + throw std::runtime_error("Slot data with NBT not supported"); + + return slot; } std::vector<unsigned char> StreamInput::ReadNbtTag() { + LOG(FATAL) << "Reading NBT is not implemented"; return std::vector<unsigned char>(); } @@ -255,8 +269,13 @@ 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::WriteSlot(SlotData value) { + WriteShort(value.BlockId); + if (value.BlockId == -1) + return; + WriteByte(value.ItemCount); + WriteShort(value.ItemDamage); + WriteUByte(0); } void StreamOutput::WriteNbtTag(std::vector<unsigned char> value) { diff --git a/src/Stream.hpp b/src/Stream.hpp index 012addf..5432383 100644 --- a/src/Stream.hpp +++ b/src/Stream.hpp @@ -13,6 +13,13 @@ #include "Vector.hpp" #include "Utility.hpp" +struct SlotData { + short BlockId = -1; + signed char ItemCount = 1; + short ItemDamage = 0; + //Nbt NBT; +}; + class Stream { public: virtual ~Stream() {}; @@ -36,7 +43,7 @@ public: int ReadVarInt(); long long ReadVarLong(); std::vector<unsigned char> ReadEntityMetadata(); - std::vector<unsigned char> ReadSlot(); + SlotData ReadSlot(); std::vector<unsigned char> ReadNbtTag(); Vector ReadPosition(); unsigned char ReadAngle(); @@ -62,7 +69,7 @@ public: void WriteVarInt(int value); void WriteVarLong(long long value); void WriteEntityMetadata(std::vector<unsigned char> value); - void WriteSlot(std::vector<unsigned char> value); + void WriteSlot(SlotData value); void WriteNbtTag(std::vector<unsigned char> value); void WritePosition(Vector value); void WriteAngle(unsigned char value); diff --git a/src/Utility.hpp b/src/Utility.hpp index d31a1a3..064f4dd 100644 --- a/src/Utility.hpp +++ b/src/Utility.hpp @@ -59,4 +59,4 @@ public: double GetRealDeltaS(); double RemainTimeMs(); -}; +};
\ No newline at end of file diff --git a/src/Vector.hpp b/src/Vector.hpp index 6389bbb..c89154f 100644 --- a/src/Vector.hpp +++ b/src/Vector.hpp @@ -14,11 +14,6 @@ struct Vector3 { Vector3(const Vector3 &rhs) : x(rhs.x), y(rhs.y), z(rhs.z) {} - template<class U> - Vector3(const Vector3<U> &rhs) : x(rhs.x), y(rhs.y), z(rhs.z) {} - - Vector3(Vector3 &&rhs) = default; - ~Vector3() = default; double GetLength() const { return std::sqrt(std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2)); } diff --git a/src/Window.cpp b/src/Window.cpp new file mode 100644 index 0000000..fbf9aaa --- /dev/null +++ b/src/Window.cpp @@ -0,0 +1,6 @@ +#include "Window.hpp" + +void Window::MakeClick(short ClickedSlot, bool Lmb) { + PacketClickWindow packet(WindowId, ClickedSlot, Lmb? 0 : 1, actions++, 0, slots[ClickedSlot]); + this->pendingTransactions.push(packet); +}
\ No newline at end of file diff --git a/src/Window.hpp b/src/Window.hpp new file mode 100644 index 0000000..4dae294 --- /dev/null +++ b/src/Window.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include <string> +#include <queue> + +#include "Packet.hpp" + +struct Window { + unsigned char WindowId = 0; + std::string type; + + SlotData handSlot; + std::vector<SlotData> slots; + + short actions = 1; + + void MakeClick(short ClickedSlot, bool Lmb); + + std::queue<PacketClickWindow> pendingTransactions; +};
\ No newline at end of file diff --git a/src/World.cpp b/src/World.cpp index 19eddbf..5b4bb03 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -3,122 +3,128 @@ #include "DebugInfo.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); - + 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); + if (packet->GroundUpContinuous) { - if (!sections.insert(std::make_pair(chunkPosition, section)).second) { + if (!sections.insert(std::make_pair(chunkPosition, std::make_unique<Section>(section))).second) { LOG(ERROR) << "New chunk not created " << chunkPosition << " potential memory leak"; } - UpdateSectionList(); - } else { + UpdateSectionsList(); + } + else { using std::swap; - swap(sections.at(chunkPosition), section); + swap(*sections.at(chunkPosition).get(), section); } EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ chunkPosition }); } - } + } } 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(2048); - std::vector<unsigned char> skyLight; - if (dimension == 0) - skyLight = data->ReadByteArray(2048); + 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(2048); + std::vector<unsigned char> skyLight; + if (dimension == 0) + skyLight = data->ReadByteArray(2048); long long *blockData = reinterpret_cast<long long*>(dataArray.data()); for (int i = 0; i < dataArray.size() / sizeof(long long); i++) endswap(blockData[i]); - std::vector<long long> blockArray (blockData, blockData + dataArray.size() / sizeof (long long)); + std::vector<long long> blockArray(blockData, blockData + dataArray.size() / sizeof(long long)); return Section(position, bitsPerBlock, std::move(palette), std::move(blockArray), std::move(blockLight), std::move(skyLight)); } World::~World() { - DebugInfo::totalSections = 0; } 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)); - if (sections.find(PlayerChunk) == sections.end() || sections.find(PlayerChunk - Vector(0,1,0)) == sections.end()) - return true; - std::vector<Vector> closestSectionsCoordinates = { - Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z), - Vector(PlayerChunk.x + 1, PlayerChunk.y, PlayerChunk.z), - Vector(PlayerChunk.x - 1, PlayerChunk.y, PlayerChunk.z), - Vector(PlayerChunk.x, PlayerChunk.y + 1, PlayerChunk.z), - Vector(PlayerChunk.x, PlayerChunk.y - 1, PlayerChunk.z), - Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z + 1), - Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z - 1), - }; - std::vector<Vector> closestSections; - for (auto &coord:closestSectionsCoordinates) { + Vector PlayerChunk(floor(X / 16.0), floor(Y / 16.0), floor(Z / 16.0)); + if (sections.find(PlayerChunk) == sections.end() || sections.find(PlayerChunk - Vector(0, 1, 0)) == sections.end()) + return false; + + std::vector<Vector> closestSectionsCoordinates = { + Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z), + Vector(PlayerChunk.x + 1, PlayerChunk.y, PlayerChunk.z), + Vector(PlayerChunk.x - 1, PlayerChunk.y, PlayerChunk.z), + Vector(PlayerChunk.x, PlayerChunk.y + 1, PlayerChunk.z), + Vector(PlayerChunk.x, PlayerChunk.y - 1, PlayerChunk.z), + Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z + 1), + Vector(PlayerChunk.x, PlayerChunk.y, PlayerChunk.z - 1), + }; + std::vector<Vector> closestSections; + for (auto &coord : closestSectionsCoordinates) { if (sections.find(coord) != sections.end()) closestSections.push_back(coord); - } - - 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; - - const Section §ion = *this->GetSection(it); - for (int x = 0; x < 16; x++) { - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - BlockId block = section.GetBlockId(Vector(x, y, z)); - if (block.id == 0 || block.id == 31) - continue; - AABB blockColl{(x + it.x * 16.0), - (y + it.y * 16.0), - (z + it.z * 16.0), 1, 1, 1}; - if (TestCollision(playerColl, blockColl)) - return true; - } - } - } - } - return false; -} - -const std::vector<Vector>& World::GetSectionsList() { - return sectionsList; + } + + 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; + + const Section §ion = this->GetSection(it); + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + BlockId block = section.GetBlockId(Vector(x, y, z)); + if (block.id == 0 || block.id == 31) + continue; + AABB blockColl{ (x + it.x * 16.0), + (y + it.y * 16.0), + (z + it.z * 16.0), 1, 1, 1 }; + if (TestCollision(playerColl, blockColl)) + return true; + } + } + } + } + return false; +} + +std::vector<Vector> World::GetSectionsList() { + sectionsListMutex.lock(); + auto vec = sectionsList; + sectionsListMutex.unlock(); + return vec; } static Section fallbackSection; -const Section* World::GetSection(Vector sectionPos) { +const Section &World::GetSection(Vector sectionPos) { auto result = sections.find(sectionPos); if (result == sections.end()) { - return nullptr; - } else { - return &result->second; + LOG(ERROR) << "Accessed not loaded section " << sectionPos; + return fallbackSection; + } + else { + return *result->second.get(); } } @@ -128,7 +134,7 @@ glm::vec3 World::Raycast(glm::vec3 position, glm::vec3 direction, float maxLengt void World::UpdatePhysics(float delta) { - //delta /= 5; + delta /= 5; entitiesMutex.lock(); for (auto& it : entities) { it.pos = it.pos + it.vel * delta; @@ -190,32 +196,32 @@ void World::DeleteEntity(unsigned int EntityId) } void World::ParseChunkData(std::shared_ptr<PacketBlockChange> packet) { - /*Block& block = this->GetBlock(packet->Position); - block = Block(packet->BlockId >> 4, packet->BlockId & 15, block.light, block.sky); + SetBlockId(packet->Position, BlockId{(unsigned short) (packet->BlockId >> 4),(unsigned char) (packet->BlockId & 0xF) }); + Vector sectionPos(std::floor(packet->Position.x / 16.0), std::floor(packet->Position.y / 16.0), std::floor(packet->Position.z / 16.0)); - EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos });*/ + EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos }); } void World::ParseChunkData(std::shared_ptr<PacketMultiBlockChange> packet) { - /*std::vector<Vector> changedSections; + std::vector<Vector> changedSections; for (auto& it : packet->Records) { int x = (it.HorizontalPosition >> 4 & 15) + (packet->ChunkX * 16); int y = it.YCoordinate; int z = (it.HorizontalPosition & 15) + (packet->ChunkZ * 16); Vector worldPos(x, y, z); - Block& block = GetBlock(worldPos); - block = Block(it.BlockId >> 4, it.BlockId & 15, block.light, block.sky); + SetBlockId(worldPos, BlockId{(unsigned short) (it.BlockId >> 4),(unsigned char) (it.BlockId & 0xF) }); Vector sectionPos(packet->ChunkX, std::floor(it.YCoordinate / 16.0), packet->ChunkZ); if (std::find(changedSections.begin(), changedSections.end(), sectionPos) == changedSections.end()) changedSections.push_back(sectionPos); } - for (auto& sectionPos: changedSections) - EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos });*/ + + for (auto& sectionPos : changedSections) + EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ sectionPos }); } void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) { - std::vector<std::map<Vector,Section>::iterator> toRemove; + std::vector<std::map<Vector, std::unique_ptr<Section>>::iterator> toRemove; for (auto it = sections.begin(); it != sections.end(); ++it) { if (it->first.x == packet->ChunkX && it->first.z == packet->ChunkZ) toRemove.push_back(it); @@ -224,12 +230,45 @@ void World::ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet) { EventAgregator::PushEvent(EventType::ChunkDeleted, ChunkDeletedData{ it->first }); sections.erase(it); } - UpdateSectionList(); + UpdateSectionsList(); } -void World::UpdateSectionList() { +void World::UpdateSectionsList() { + sectionsListMutex.lock(); sectionsList.clear(); for (auto& it : sections) { sectionsList.push_back(it.first); } + sectionsListMutex.unlock(); +} + +BlockId World::GetBlockId(Vector pos) { + Vector sectionPos(std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0)); + + Section* section = GetSectionPtr(sectionPos); + return section->GetBlockId(pos - (sectionPos * 16)); +} + +void World::SetBlockId(Vector pos, BlockId block) { + Vector sectionPos(std::floor(pos.x / 16.0), std::floor(pos.y / 16.0), std::floor(pos.z / 16.0)); + + Section* section = GetSectionPtr(sectionPos); + section->SetBlockId(pos - (sectionPos * 16), block); +} + +void World::SetBlockLight(Vector pos, unsigned char light) { + +} + +void World::SetBlockSkyLight(Vector pos, unsigned char light) { + +} + +Section *World::GetSectionPtr(Vector position) { + auto it = sections.find(position); + + if (it == sections.end()) + return nullptr; + + return it->second.get(); }
\ No newline at end of file diff --git a/src/World.hpp b/src/World.hpp index 89c40d4..6b8b5d1 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -3,6 +3,7 @@ #include <map> #include <bitset> #include <queue> +#include <memory> #include <easylogging++.h> @@ -17,9 +18,9 @@ class World { int dimension = 0; - std::map<Vector, Section> sections; + std::map<Vector, std::unique_ptr<Section>> sections; - Section ParseSection(StreamInput *data, Vector position); + Section ParseSection(StreamInput *data, Vector position); std::vector<Entity> entities; @@ -27,14 +28,16 @@ class World { std::vector<Vector> sectionsList; - void UpdateSectionList(); + std::mutex sectionsListMutex; + + void UpdateSectionsList(); public: - World(); + World(); - ~World(); + ~World(); - void ParseChunkData(std::shared_ptr<PacketChunkData> packet); + void ParseChunkData(std::shared_ptr<PacketChunkData> packet); void ParseChunkData(std::shared_ptr<PacketBlockChange> packet); @@ -42,13 +45,13 @@ public: void ParseChunkData(std::shared_ptr<PacketUnloadChunk> packet); - bool isPlayerCollides(double X, double Y, double Z); + bool isPlayerCollides(double X, double Y, double Z); - const std::vector<Vector>& GetSectionsList(); + std::vector<Vector> GetSectionsList(); - const Section* GetSection(Vector sectionPos); + const Section &GetSection(Vector sectionPos); - glm::vec3 Raycast(glm::vec3 position, glm::vec3 direction, float maxLength = 1000.0f, float minPrecision = 0.01f); + glm::vec3 Raycast(glm::vec3 position, glm::vec3 direction, float maxLength = 1000.0f, float minPrecision = 0.01f); void UpdatePhysics(float delta); @@ -59,4 +62,14 @@ public: void AddEntity(Entity entity); void DeleteEntity(unsigned int EntityId); + + BlockId GetBlockId(Vector pos); + + void SetBlockId(Vector pos, BlockId block); + + void SetBlockLight(Vector pos, unsigned char light); + + void SetBlockSkyLight(Vector pos, unsigned char light); + + Section *GetSectionPtr(Vector position); };
\ No newline at end of file |