diff --git a/CMakeLists.txt b/CMakeLists.txt index 29a37bc..bd2bd3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,8 @@ set(Boost_USE_STATIC_LIBS ON) set(BOOST_INCLUDE_LIBRARIES asio thread json) set(BOOST_ENABLE_CMAKE ON) +set(BOOST_IOSTREAMS_ENABLE_ZLIB ON) +set(BOOST_INCLUDE_LIBRARIES asio thread json iostreams) FetchContent_Declare( Boost URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-cmake.7z @@ -73,7 +75,7 @@ FetchContent_Declare( DOWNLOAD_NO_EXTRACT FALSE ) FetchContent_MakeAvailable(Boost) -target_link_libraries(luavox_common INTERFACE Boost::asio Boost::thread Boost::json) +target_link_libraries(luavox_common INTERFACE Boost::asio Boost::thread Boost::json Boost::iostreams) # glm # find_package(glm REQUIRED) @@ -116,7 +118,8 @@ target_link_libraries(luavox_common INTERFACE SQLite::SQLite3) # Static Assets file(GLOB_RECURSE ASSETS RELATIVE "${PROJECT_SOURCE_DIR}/assets" "assets/*.*") -add_custom_command(OUTPUT assets.o resources.cpp INPUT ${ASSETS} +file(GLOB_RECURSE ASSETS_A "${PROJECT_SOURCE_DIR}/assets" "assets/*.*") +add_custom_command(OUTPUT assets.o resources.cpp INPUT ${ASSETS_A} COMMAND cd ${CMAKE_CURRENT_BINARY_DIR} && ${CMAKE_CURRENT_SOURCE_DIR}/Src/assets.py ${ASSETS} COMMAND cd "${CMAKE_CURRENT_SOURCE_DIR}/assets" && ld -r -b binary -o '${CMAKE_CURRENT_BINARY_DIR}/assets.o' ${ASSETS} COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/assets.o ${CMAKE_CURRENT_BINARY_DIR}/assets.o) diff --git a/Src/Client/Abstract.hpp b/Src/Client/Abstract.hpp index 29c6bf1..97b9f22 100644 --- a/Src/Client/Abstract.hpp +++ b/Src/Client/Abstract.hpp @@ -39,7 +39,7 @@ struct Chunk { // Кубы вокселей в чанке std::vector Voxels; // Ноды - Node Nodes[16][16][16]; + std::array Nodes; // Ограничения прохождения света, идущего от солнца (от верха карты до верхней плоскости чанка) // LightPrism Lights[16][16]; }; @@ -79,7 +79,7 @@ public: }; struct Region { - Chunk Chunks[4][4][4]; + std::array Chunks; }; struct World { @@ -172,7 +172,7 @@ public: } CursorMode = EnumCursorMoveMode::Default; enum struct EnumCursorBtn { - Left, Middle, Right, One, Two + Left, Right, Middle, One, Two }; public: diff --git a/Src/Client/ServerSession.cpp b/Src/Client/ServerSession.cpp index a5ca791..9087e2a 100644 --- a/Src/Client/ServerSession.cpp +++ b/Src/Client/ServerSession.cpp @@ -32,7 +32,7 @@ struct PP_Content_ChunkVoxels : public ParsedPacket { struct PP_Content_ChunkNodes : public ParsedPacket { WorldId_t Id; Pos::GlobalChunk Pos; - Node Nodes[16][16][16]; + std::array Nodes; PP_Content_ChunkNodes(ToClient::L1 l1, uint8_t l2, WorldId_t id, Pos::GlobalChunk pos) : ParsedPacket(l1, l2), Id(id), Pos(pos) @@ -195,8 +195,8 @@ void ServerSession::onCursorMove(float xMove, float yMove) { static constexpr float PI = glm::pi(), PI2 = PI*2, PI_HALF = PI/2, PI_DEG = PI/180; - deltaPYR.x = std::clamp(PYR.x + yMove*PI_DEG, -PI_HALF+PI_DEG, PI_HALF-PI_DEG)-PYR.x; - deltaPYR.y = std::fmod(PYR.y + xMove*PI_DEG, PI2)-PYR.y; + deltaPYR.x = std::clamp(PYR.x - yMove*PI_DEG, -PI_HALF+PI_DEG, PI_HALF-PI_DEG)-PYR.x; + deltaPYR.y = std::fmod(PYR.y - xMove*PI_DEG, PI2)-PYR.y; deltaPYR.z = 0; double gTime = GTime; @@ -208,7 +208,26 @@ void ServerSession::onCursorMove(float xMove, float yMove) { } void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool state) { + if(!state) + return; + if(btn == EnumCursorBtn::Left) { + Net::Packet packet; + + packet << (uint8_t) ToServer::L1::System + << (uint8_t) ToServer::L2System::BlockChange + << uint8_t(0); + + Socket->pushPacket(std::move(packet)); + } else if(btn == EnumCursorBtn::Right) { + Net::Packet packet; + + packet << (uint8_t) ToServer::L1::System + << (uint8_t) ToServer::L2System::BlockChange + << uint8_t(1); + + Socket->pushPacket(std::move(packet)); + } } void ServerSession::onKeyboardBtn(int btn, int state) { @@ -255,9 +274,9 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) { if(Keys.CTRL) mltpl *= 16; - Speed += glm::vec3(rot*glm::vec4(0, 0, 1, 1)*float(Keys.W))*mltpl; + Speed += glm::vec3(rot*glm::vec4(0, 0, -1, 1)*float(Keys.W))*mltpl; Speed += glm::vec3(rot*glm::vec4(-1, 0, 0, 1)*float(Keys.A))*mltpl; - Speed += glm::vec3(rot*glm::vec4(0, 0, -1, 1)*float(Keys.S))*mltpl; + Speed += glm::vec3(rot*glm::vec4(0, 0, 1, 1)*float(Keys.S))*mltpl; Speed += glm::vec3(rot*glm::vec4(1, 0, 0, 1)*float(Keys.D))*mltpl; Speed += glm::vec3(0, -1, 0)*float(Keys.SHIFT)*mltpl; Speed += glm::vec3(0, 1, 0)*float(Keys.SPACE)*mltpl; @@ -275,7 +294,7 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) { Pos::GlobalRegion rPos = p.Pos >> 2; Pos::bvec4u cPos = p.Pos & 0x3; - Data.Worlds[p.Id].Regions[rPos].Chunks[cPos.x][cPos.y][cPos.z].Voxels = std::move(p.Cubes); + Data.Worlds[p.Id].Regions[rPos].Chunks[cPos.pack()].Voxels = std::move(p.Cubes); auto &pair = changeOrAddList_removeList[p.Id]; std::get<0>(pair).insert(p.Pos); @@ -284,8 +303,8 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) { Pos::GlobalRegion rPos = p.Pos >> 2; Pos::bvec4u cPos = p.Pos & 0x3; - Node *nodes = (Node*) Data.Worlds[p.Id].Regions[rPos].Chunks[cPos.x][cPos.y][cPos.z].Nodes; - std::copy((const Node*) p.Nodes, ((const Node*) p.Nodes)+16*16*16, nodes); + Node *nodes = (Node*) Data.Worlds[p.Id].Regions[rPos].Chunks[cPos.pack()].Nodes.data(); + std::copy(p.Nodes.begin(), p.Nodes.end(), nodes); auto &pair = changeOrAddList_removeList[p.Id]; std::get<0>(pair).insert(p.Pos); @@ -542,14 +561,14 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) { uint32_t compressedSize = co_await sock.read(); assert(compressedSize <= std::pow(2, 24)); std::u8string compressed(compressedSize, '\0'); - co_await sock.read((std::byte*) compressed.data(), compressedSize); + co_await sock.read((std::byte*) compressed.data(), compressedSize); PP_Content_ChunkVoxels *packet = new PP_Content_ChunkVoxels( ToClient::L1::Content, (uint8_t) ToClient::L2Content::ChunkVoxels, wcId, pos, - unCompressVoxels(compressed) + unCompressVoxels(compressed) // TODO: вынести в отдельный поток ); while(!NetInputPackets.push(packet)); @@ -566,7 +585,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) { uint32_t compressedSize = co_await sock.read(); assert(compressedSize <= std::pow(2, 24)); std::u8string compressed(compressedSize, '\0'); - co_await sock.read((std::byte*) compressed.data(), compressedSize); + co_await sock.read((std::byte*) compressed.data(), compressedSize); PP_Content_ChunkNodes *packet = new PP_Content_ChunkNodes( ToClient::L1::Content, @@ -575,7 +594,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) { pos ); - unCompressNodes(compressed, (Node*) packet->Nodes); + unCompressNodes(compressed, (Node*) packet->Nodes.data()); // TODO: вынести в отдельный поток while(!NetInputPackets.push(packet)); @@ -586,7 +605,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) { co_return; case ToClient::L2Content::RemoveRegion: { WorldId_t wcId = co_await sock.read(); - Pos::GlobalChunk pos; + Pos::GlobalRegion pos; pos.unpack(co_await sock.read()); PP_Content_RegionRemove *packet = new PP_Content_RegionRemove( diff --git a/Src/Client/Vulkan/Vulkan.cpp b/Src/Client/Vulkan/Vulkan.cpp index ffd93bb..b33e204 100644 --- a/Src/Client/Vulkan/Vulkan.cpp +++ b/Src/Client/Vulkan/Vulkan.cpp @@ -2081,7 +2081,7 @@ void Vulkan::gui_MainMenu() { ImGui::InputText("Username", ConnectionProgress.Username, sizeof(ConnectionProgress.Username)); ImGui::InputText("Password", ConnectionProgress.Password, sizeof(ConnectionProgress.Password), ImGuiInputTextFlags_Password); - static bool flag = false; + static bool flag = true; if(!flag) { flag = true; Game.Server = std::make_unique(IOC); @@ -2686,12 +2686,16 @@ Buffer::Buffer(Buffer &&obj) obj.Instance = nullptr; } -Buffer& Buffer::operator=(Buffer &&obj) -{ +Buffer& Buffer::operator=(Buffer &&obj) { + if(this == &obj) + return *this; + std::swap(Instance, obj.Instance); std::swap(Buff, obj.Buff); std::swap(Memory, obj.Memory); std::swap(Size, obj.Size); + obj.Instance = nullptr; + return *this; } diff --git a/Src/Client/Vulkan/VulkanRenderSession.cpp b/Src/Client/Vulkan/VulkanRenderSession.cpp index 4adb3ee..070b7b7 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.cpp +++ b/Src/Client/Vulkan/VulkanRenderSession.cpp @@ -251,6 +251,13 @@ void VulkanRenderSession::init(Vulkan *instance) { array[15] = {135, 135, 135-64, 0, 0, 0, 0, 0, 0}; array[16] = {135+16, 135, 135-64-16, 0, 0, 0, 0, 65535, 65535}; array[17] = {135, 135, 135-64-16, 0, 0, 0, 0, 0, 65535}; + + for(int iter = 0; iter < 18; iter++) { + array[18+iter] = array[iter]; + array[18+iter].FZ -= 32; + } + + VKCTX->TestQuad.unMapMemory(); } @@ -431,7 +438,7 @@ void VulkanRenderSession::init(Vulkan *instance) { .flags = 0, .depthClampEnable = false, .rasterizerDiscardEnable = false, - .polygonMode = VK_POLYGON_MODE_LINE, + .polygonMode = VK_POLYGON_MODE_FILL, .cullMode = VK_CULL_MODE_BACK_BIT, .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, .depthBiasEnable = false, @@ -636,6 +643,7 @@ void VulkanRenderSession::onContentDefinesLost(std::unordered_map& changeOrAddList, const std::unordered_set& remove) { auto &table = External.ChunkVoxelMesh[worldId]; @@ -645,7 +653,7 @@ void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered auto &buffers = table[pos]; - const auto &chunk = ServerSession->Data.Worlds[worldId].Regions[rPos].Chunks[cPos.x][cPos.y][cPos.z]; + const auto &chunk = ServerSession->Data.Worlds[worldId].Regions[rPos].Chunks[cPos.pack()]; if(chunk.Voxels.empty()) { VKCTX->VertexPool_Voxels.dropVertexs(std::get<0>(buffers)); @@ -655,11 +663,12 @@ void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered VKCTX->VertexPool_Voxels.relocate(voxels, std::move(vertexs)); } - std::vector vertexs2 = generateMeshForNodeChunks(chunk.Nodes); + std::vector vertexs2 = generateMeshForNodeChunks(chunk.Nodes.data()); if(vertexs2.empty()) { VKCTX->VertexPool_Nodes.dropVertexs(std::get<1>(buffers)); } else { + changed++; auto &nodes = std::get<1>(buffers); VKCTX->VertexPool_Nodes.relocate(nodes, std::move(vertexs2)); } @@ -669,6 +678,8 @@ void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered if(iter != table.end()) table.erase(iter); } + + TOS::Logger("Vul").debug() << "Обработано " << changed; } for(Pos::GlobalRegion pos : remove) { @@ -704,7 +715,12 @@ void VulkanRenderSession::beforeDraw() { } void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd) { - + { + X64Offset = Pos & ~((1 << Pos::Object_t::BS_Bit << 4 << 2)-1); + X64Offset_f = glm::vec3(X64Offset) / float(Pos::Object_t::BS); + X64Delta = glm::vec3(Pos-X64Offset) / float(Pos::Object_t::BS); + } + // Сместить в координаты игрока, повернуть относительно взгляда проецировать на экран // Изначально взгляд в z-1 // PCO.ProjView = glm::mat4(1); @@ -800,16 +816,27 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff static float Delta = 0; Delta += dTime; - glm::mat4 projView = glm::perspective(glm::radians(75.f), float(VkInst->Screen.Width)/float(VkInst->Screen.Height), 0.5, std::pow(2, 17)); - projView[1][1] *= -1; - glm::mat4 rotate = glm::mat4(1); - rotate = glm::translate(rotate, {0, 0, -4}); - rotate = glm::rotate(rotate, 45.f/360*(2*glm::pi()), {1, 0, 0}); - rotate = glm::rotate(rotate, Delta/16*(2*glm::pi()), {0, 1, 0}); - rotate = glm::translate(rotate, {0, 0, 4}); - - PCO.ProjView = projView*rotate; PCO.Model = glm::mat4(1); + PCO.Model = glm::translate(PCO.Model, -X64Offset_f); + + { + glm::mat4 proj = glm::perspective(glm::radians(75.f), float(VkInst->Screen.Width)/float(VkInst->Screen.Height), 0.5, std::pow(2, 17)); + proj[1][1] *= -1; + + // Получили область рендера от левого верхнего угла + // x -1 -> 1; y 1 -> -1; z 0 -> -1 + // Правило левой руки + // Перед полигонов определяется обходом против часовой стрелки + + glm::mat4 view = glm::mat4(1); + // Смещаем мир относительно позиции игрока, чтобы игрок в пространстве рендера оказался в нулевых координатах + view = glm::translate(view, -X64Delta); + // Поворачиваем мир обратно взгляду игрока, чтобы его взгляд стал по направлению оси -z + view = glm::mat4(-Quat)*view; + + // Сначала применяется матрица вида, потом проекции + PCO.ProjView = proj*view; + } vkCmdBindPipeline(drawCmd, VK_PIPELINE_BIND_POINT_GRAPHICS, NodeStaticOpaquePipeline); vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout, @@ -818,11 +845,36 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff MainAtlas_LightMap_PipelineLayout, 0, 2, (const VkDescriptorSet[]) {MainAtlasDescriptor, VoxelLightMapDescriptor}, 0, nullptr); + PCO.Model = glm::mat4(1); VkBuffer vkBuffer = VKCTX->TestQuad; - VkDeviceSize vkOffset = 0; + VkDeviceSize vkOffsets = 0; - vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffset); - vkCmdDraw(drawCmd, 6*3, 1, 0, 0); + vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffsets); + vkCmdDraw(drawCmd, 6*3*2, 1, 0, 0); + + { + Pos::GlobalChunk x64offset = X64Offset >> Pos::Object_t::BS_Bit >> 4; + + auto iterWorld = External.ChunkVoxelMesh.find(WorldId); + if(iterWorld != External.ChunkVoxelMesh.end()) { + glm::mat4 orig = PCO.Model; + + for(auto &pair : iterWorld->second) { + if(auto& nodes = std::get<1>(pair.second)) { + glm::vec3 cpos(pair.first-x64offset); + PCO.Model = glm::translate(orig, cpos*16.f); + auto [vkBuffer, offset] = VKCTX->VertexPool_Nodes.map(nodes); + + vkCmdPushConstants(drawCmd, MainAtlas_LightMap_PipelineLayout, + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, offsetof(WorldPCO, Model), sizeof(WorldPCO::Model), &PCO.Model); + vkCmdBindVertexBuffers(drawCmd, 0, 1, &vkBuffer, &vkOffsets); + vkCmdDraw(drawCmd, nodes.VertexCount, 1, offset, 0); + } + } + + PCO.Model = orig; + } + } } std::vector VulkanRenderSession::generateMeshForVoxelChunks(const std::vector cubes) { @@ -912,7 +964,7 @@ std::vector VulkanRenderSession::generateMeshForVoxelChunks(co return out; } -std::vector VulkanRenderSession::generateMeshForNodeChunks(const Node nodes[16][16][16]) { +std::vector VulkanRenderSession::generateMeshForNodeChunks(const Node* nodes) { std::vector out; NodeVertexStatic v; @@ -920,15 +972,16 @@ std::vector VulkanRenderSession::generateMeshForNodeChunks(con for(int y = 0; y < 16; y++) for(int x = 0; x < 16; x++) { - if(nodes[x][y][z].Data == 0) + size_t index = Pos::bvec16u(x, y, z).pack(); + if(nodes[index].Data == 0) continue; - v.Tex = nodes[x][y][z].NodeId; + v.Tex = nodes[index].NodeId; - if((y+1) >= 16 || nodes[x][y+1][z].NodeId == 0) { + if((y+1) >= 16 || nodes[Pos::bvec16u(x, y+1, z).pack()].NodeId == 0) { v.FX = 135+x*16; v.FY = 135+y*16+16; - v.FZ = 135+z*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); @@ -937,18 +990,18 @@ std::vector VulkanRenderSession::generateMeshForNodeChunks(con v.TU = 65535; out.push_back(v); - v.FZ += 16; + v.FZ -= 16; v.TV = 65535; out.push_back(v); v.FX = 135+x*16; - v.FZ = 135+z*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); v.FX += 16; - v.FZ += 16; + v.FZ -= 16; v.TV = 65535; v.TU = 65535; out.push_back(v); @@ -958,106 +1011,73 @@ std::vector VulkanRenderSession::generateMeshForNodeChunks(con out.push_back(v); } - if((y-1) < 0 || nodes[x][y-1][z].NodeId == 0) { + if((y-1) < 0 || nodes[Pos::bvec16u(x, y-1, z).pack()].NodeId == 0) { v.FX = 135+x*16; v.FY = 135+y*16; - v.FZ = 135+z*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); - v.FZ += 16; - v.TV = 65535; - out.push_back(v); - - v.FX += 16; - v.TU = 65535; - out.push_back(v); - - v.FX = 135+x*16; - v.FZ = 135+z*16; - v.TU = 0; - v.TV = 0; - out.push_back(v); - - v.FX += 16; - v.FZ += 16; - v.TV = 65535; - v.TU = 65535; - out.push_back(v); - v.FZ -= 16; + v.TV = 65535; + out.push_back(v); + + v.FX += 16; + v.TU = 65535; + out.push_back(v); + + v.FX = 135+x*16; + v.FZ = 135+z*16+16; + v.TU = 0; + v.TV = 0; + out.push_back(v); + + v.FX += 16; + v.FZ -= 16; + v.TV = 65535; + v.TU = 65535; + out.push_back(v); + + v.FZ += 16; v.TV = 0; out.push_back(v); } - if((x+1) >= 16 || nodes[x+1][y][z].NodeId == 0) { + if((x+1) >= 16 || nodes[Pos::bvec16u(x+1, y, z).pack()].NodeId == 0) { v.FX = 135+x*16+16; v.FY = 135+y*16; - v.FZ = 135+z*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); - v.FZ += 16; - v.TV = 65535; - out.push_back(v); - - v.FY += 16; - v.TU = 65535; - out.push_back(v); - - v.FY = 135+y*16; - v.FZ = 135+z*16; - v.TU = 0; - v.TV = 0; - out.push_back(v); - - v.FY += 16; - v.FZ += 16; - v.TV = 65535; - v.TU = 65535; - out.push_back(v); - v.FZ -= 16; - v.TV = 0; - out.push_back(v); - } - - if((x-1) < 0 || nodes[x-1][y][z].NodeId == 0) { - v.FX = 135+x*16; - v.FY = 135+y*16; - v.FZ = 135+z*16; - v.TU = 0; - v.TV = 0; + v.TV = 65535; out.push_back(v); v.FY += 16; v.TU = 65535; out.push_back(v); - v.FZ += 16; - v.TV = 65535; - out.push_back(v); - v.FY = 135+y*16; - v.FZ = 135+z*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); v.FY += 16; - v.FZ += 16; + v.FZ -= 16; v.TV = 65535; v.TU = 65535; out.push_back(v); - v.FY -= 16; - v.TU = 0; + v.FZ += 16; + v.TV = 0; out.push_back(v); } - if((z+1) >= 16 || nodes[x][y][z+1].NodeId == 0) { + if((x-1) < 0 || nodes[Pos::bvec16u(x-1, y, z).pack()].NodeId == 0) { v.FX = 135+x*16; v.FY = 135+y*16; v.FZ = 135+z*16+16; @@ -1069,18 +1089,18 @@ std::vector VulkanRenderSession::generateMeshForNodeChunks(con v.TU = 65535; out.push_back(v); - v.FX += 16; + v.FZ -= 16; v.TV = 65535; out.push_back(v); - v.FX = 135+x*16; v.FY = 135+y*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); - v.FX += 16; v.FY += 16; + v.FZ -= 16; v.TV = 65535; v.TU = 65535; out.push_back(v); @@ -1090,20 +1110,20 @@ std::vector VulkanRenderSession::generateMeshForNodeChunks(con out.push_back(v); } - if((z-1) < 0 || nodes[x][y][z-1].NodeId == 0) { + if((z+1) >= 16 || nodes[Pos::bvec16u(x, y, z+1).pack()].NodeId == 0) { v.FX = 135+x*16; v.FY = 135+y*16; - v.FZ = 135+z*16; + v.FZ = 135+z*16+16; v.TU = 0; v.TV = 0; out.push_back(v); v.FX += 16; - v.TV = 65535; + v.TU = 65535; out.push_back(v); v.FY += 16; - v.TU = 65535; + v.TV = 65535; out.push_back(v); v.FX = 135+x*16; @@ -1119,6 +1139,39 @@ std::vector VulkanRenderSession::generateMeshForNodeChunks(con out.push_back(v); v.FX -= 16; + v.TU = 0; + out.push_back(v); + } + + if((z-1) < 0 || nodes[Pos::bvec16u(x, y, z-1).pack()].NodeId == 0) { + v.FX = 135+x*16; + v.FY = 135+y*16; + v.FZ = 135+z*16; + v.TU = 0; + v.TV = 0; + out.push_back(v); + + v.FY += 16; + v.TV = 65535; + out.push_back(v); + + v.FX += 16; + v.TU = 65535; + out.push_back(v); + + v.FX = 135+x*16; + v.FY = 135+y*16; + v.TU = 0; + v.TV = 0; + out.push_back(v); + + v.FX += 16; + v.FY += 16; + v.TV = 65535; + v.TU = 65535; + out.push_back(v); + + v.FY -= 16; v.TV = 0; out.push_back(v); } diff --git a/Src/Client/Vulkan/VulkanRenderSession.hpp b/Src/Client/Vulkan/VulkanRenderSession.hpp index 231c0b7..c34088a 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.hpp +++ b/Src/Client/Vulkan/VulkanRenderSession.hpp @@ -48,6 +48,19 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent { // Положение камеры WorldId_t WorldId; Pos::Object Pos; + /* + Графический конвейер оперирует числами с плавающей запятой + Для сохранения точности матрица модели хранит смещения близкие к нулю (X64Delta) + глобальные смещения на уровне региона исключаются из смещения ещё при задании матрицы модели + + X64Offset = позиция игрока на уровне регионов + X64Delta = позиция игрока в рамках региона + + Внутри графического конвейера будут числа приблежённые к 0 + */ + // Смещение дочерних объекто на стороне хоста перед рендером + Pos::Object X64Offset; + glm::vec3 X64Offset_f, X64Delta; // Смещение мира относительно игрока в матрице вида (0 -> 64) glm::quat Quat; struct VulkanContext { @@ -61,7 +74,7 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent { VulkanContext(Vulkan *vkInst) : MainTest(vkInst), LightDummy(vkInst), - TestQuad(vkInst, sizeof(NodeVertexStatic)*6*3), + TestQuad(vkInst, sizeof(NodeVertexStatic)*6*3*2), VertexPool_Voxels(vkInst), VertexPool_Nodes(vkInst) {} @@ -143,7 +156,7 @@ public: void drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd); static std::vector generateMeshForVoxelChunks(const std::vector cubes); - static std::vector generateMeshForNodeChunks(const Node nodes[16][16][16]); + static std::vector generateMeshForNodeChunks(const Node* nodes); private: void updateDescriptor_MainAtlas(); diff --git a/Src/Common/Abstract.cpp b/Src/Common/Abstract.cpp index ae9a7ec..99b5c73 100644 --- a/Src/Common/Abstract.cpp +++ b/Src/Common/Abstract.cpp @@ -1,6 +1,10 @@ #include "Abstract.hpp" #include - +#include +#include +#include +#include +#include namespace LV { @@ -99,7 +103,7 @@ CompressedVoxels compressVoxels_byte(const std::vector& voxels) { } } - return {compressed, defines}; + return {compressLinear(compressed), defines}; } CompressedVoxels compressVoxels_bit(const std::vector& voxels) { @@ -245,7 +249,7 @@ CompressedVoxels compressVoxels_bit(const std::vector& voxels) { for(size_t iter = 0; iter < buff.size(); iter++) compressed[iter / 8] |= (buff[iter] << (iter % 8)); - return {compressed, profile}; + return {compressLinear(compressed), profile}; } CompressedVoxels compressVoxels(const std::vector& voxels, bool fast) { @@ -419,10 +423,11 @@ std::vector unCompressVoxels_bit(const std::u8string& compressed) { } std::vector unCompressVoxels(const std::u8string& compressed) { - if(compressed.front()) - return unCompressVoxels_byte(compressed); + const std::u8string& next = unCompressLinear(compressed); + if(next.front()) + return unCompressVoxels_byte(next); else - return unCompressVoxels_bit(compressed); + return unCompressVoxels_bit(next); } @@ -510,7 +515,7 @@ CompressedNodes compressNodes_byte(const Node* nodes) { profiles.shrink_to_fit(); - return {compressed, profiles}; + return {compressLinear(compressed), profiles}; } CompressedNodes compressNodes_bit(const Node* nodes) { @@ -628,15 +633,33 @@ CompressedNodes compressNodes_bit(const Node* nodes) { } } - return {compressed, profiles}; + return {compressLinear(compressed), profiles}; } CompressedNodes compressNodes(const Node* nodes, bool fast) { - if(fast) - return compressNodes_byte(nodes); - else - return compressNodes_bit(nodes); + std::u8string data(16*16*16*sizeof(Node), '\0'); + const char8_t *ptr = (const char8_t*) nodes; + std::copy(ptr, ptr+16*16*16*4, data.data()); + + std::vector node(16*16*16); + for(int iter = 0; iter < 16*16*16; iter++) { + node[iter] = nodes[iter].NodeId; + } + + { + std::sort(node.begin(), node.end()); + auto last = std::unique(node.begin(), node.end()); + node.erase(last, node.end()); + node.shrink_to_fit(); + } + + return {compressLinear(data), std::move(node)}; + + // if(fast) + // return compressNodes_byte(nodes); + // else + // return compressNodes_bit(nodes); } void unCompressNodes_byte(const std::u8string& compressed, Node* ptr) { @@ -761,10 +784,44 @@ void unCompressNodes_bit(const std::u8string& compressed, Node* ptr) { } void unCompressNodes(const std::u8string& compressed, Node* ptr) { - if(compressed.front()) - return unCompressNodes_byte(compressed, ptr); - else - return unCompressNodes_bit(compressed, ptr); + const std::u8string& next = unCompressLinear(compressed); + const Node *lPtr = (const Node*) next.data(); + std::copy(lPtr, lPtr+16*16*16, ptr); + + // if(next.front()) + // return unCompressNodes_byte(next, ptr); + // else + // return unCompressNodes_bit(next, ptr); +} + +std::u8string compressLinear(const std::u8string& data) { + std::stringstream in; + in.write((const char*) data.data(), data.size()); + + boost::iostreams::filtering_streambuf out; + out.push(boost::iostreams::zlib_compressor()); + out.push(in); + + std::stringstream compressed; + boost::iostreams::copy(out, compressed); + std::string outString = compressed.str(); + + return *(std::u8string*) &outString; +} + +std::u8string unCompressLinear(const std::u8string& data) { + std::stringstream in; + in.write((const char*) data.data(), data.size()); + + boost::iostreams::filtering_streambuf out; + out.push(boost::iostreams::zlib_decompressor()); + out.push(in); + + std::stringstream compressed; + boost::iostreams::copy(out, compressed); + std::string outString = compressed.str(); + + return *(std::u8string*) &outString; } } \ No newline at end of file diff --git a/Src/Common/Abstract.hpp b/Src/Common/Abstract.hpp index 6dd0017..ec53dcd 100644 --- a/Src/Common/Abstract.hpp +++ b/Src/Common/Abstract.hpp @@ -1,6 +1,7 @@ #pragma once #include "Common/Net.hpp" +#include "TOSLib.hpp" #include #include #include @@ -90,7 +91,7 @@ public: using U = std::make_unsigned_t; for(size_t iter = 0; iter < N; iter++) { - out |= Pack(U(get(iter))) << BitsPerComponent*iter; + out |= Pack(U(get(iter)) & U((Pack(1) << BitsPerComponent)-1)) << BitsPerComponent*iter; } return out; @@ -100,7 +101,7 @@ public: using U = std::make_unsigned_t; for(size_t iter = 0; iter < N; iter++) { - set(iter, U((pack >> BitsPerComponent*iter) & ((Pack(1) << BitsPerComponent)-1))); + set(iter, T(U((pack >> BitsPerComponent*iter) & U((Pack(1) << BitsPerComponent)-1)))); } } @@ -481,6 +482,9 @@ struct CompressedNodes { CompressedNodes compressNodes(const Node* nodes, bool fast = true); void unCompressNodes(const std::u8string& compressed, Node* ptr); +std::u8string compressLinear(const std::u8string& data); +std::u8string unCompressLinear(const std::u8string& data); + } diff --git a/Src/Common/Packets.hpp b/Src/Common/Packets.hpp index 8deb7bc..64d65b0 100644 --- a/Src/Common/Packets.hpp +++ b/Src/Common/Packets.hpp @@ -62,6 +62,7 @@ struct PacketQuat { 0 - 1 - 2 - Новая позиция камеры WorldId_c+ObjectPos+PacketQuat + 3 - Изменение блока */ @@ -74,7 +75,8 @@ enum struct L1 : uint8_t { enum struct L2System : uint8_t { InitEnd, Disconnect, - Test_CAM_PYR_POS + Test_CAM_PYR_POS, + BlockChange }; } diff --git a/Src/Server/ContentEventController.cpp b/Src/Server/ContentEventController.cpp index 5e17a2d..a0ab52a 100644 --- a/Src/Server/ContentEventController.cpp +++ b/Src/Server/ContentEventController.cpp @@ -107,6 +107,26 @@ void ContentEventController::onUpdate() { if(r1 != r2) { CrossedBorder = true; } + + if(!Remote->Actions.get_read().empty()) { + auto lock = Remote->Actions.lock(); + while(!lock->empty()) { + uint8_t action = lock->front(); + lock->pop(); + + Pos::GlobalNode pos = (Pos::GlobalNode) (glm::vec3) (glm::mat4(Remote->CameraQuat.toQuat())*glm::vec4(0, 0, -1, 1)); + pos = Pos.ObjectPos >> Pos::Object_t::BS_Bit; + + if(action == 0) { + // Break + Break.push(pos); + + } else if(action == 1) { + // Build + Build.push(pos); + } + } + } } } \ No newline at end of file diff --git a/Src/Server/ContentEventController.hpp b/Src/Server/ContentEventController.hpp index 139e55d..7b113d2 100644 --- a/Src/Server/ContentEventController.hpp +++ b/Src/Server/ContentEventController.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -57,10 +58,6 @@ struct ContentViewInfo { if(iterWorld == obj.Regions.end()) { out.WorldsNew.push_back(key); out.RegionsNew[key] = regions; - - for(const Pos::GlobalRegion& rp : regions) { - TOS::Logger("New").debug() << rp.x << ' ' << rp.y << ' ' << rp.z; - } } else { auto &vec = out.RegionsNew[key]; vec.reserve(8*8); @@ -69,10 +66,6 @@ struct ContentViewInfo { iterWorld->second.begin(), iterWorld->second.end(), std::back_inserter(vec) ); - - for(Pos::GlobalRegion& rp : vec) { - TOS::Logger("New").debug() << rp.x << ' ' << rp.y << ' ' << rp.z; - } } } @@ -83,10 +76,6 @@ struct ContentViewInfo { if(iterWorld == Regions.end()) { out.WorldsLost.push_back(key); out.RegionsLost[key] = regions; - - for(const Pos::GlobalRegion& rp : regions) { - TOS::Logger("Lost").debug() << rp.x << ' ' << rp.y << ' ' << rp.z; - } } else { auto &vec = out.RegionsLost[key]; vec.reserve(8*8); @@ -95,10 +84,6 @@ struct ContentViewInfo { iterWorld->second.begin(), iterWorld->second.end(), std::back_inserter(vec) ); - - for(Pos::GlobalRegion& rp : vec) { - TOS::Logger("Lost").debug() << rp.x << ' ' << rp.y << ' ' << rp.z; - } } } @@ -153,6 +138,7 @@ public: bool CrossedBorder = true; ServerObjectPos Pos, LastPos; + std::queue Build, Break; public: ContentEventController(std::unique_ptr&& remote); diff --git a/Src/Server/GameServer.cpp b/Src/Server/GameServer.cpp index 75fd472..fecf24b 100644 --- a/Src/Server/GameServer.cpp +++ b/Src/Server/GameServer.cpp @@ -29,18 +29,18 @@ GameServer::GameServer(asio::io_context &ioc, fs::path worldPath) { init(worldPath); - BackingChunkPressure.Threads.resize(1); + BackingChunkPressure.Threads.resize(4); BackingChunkPressure.Worlds = &Expanse.Worlds; for(size_t iter = 0; iter < BackingChunkPressure.Threads.size(); iter++) { BackingChunkPressure.Threads[iter] = std::thread(&BackingChunkPressure_t::run, &BackingChunkPressure, iter); } - BackingNoiseGenerator.Threads.resize(1); + BackingNoiseGenerator.Threads.resize(4); for(size_t iter = 0; iter < BackingNoiseGenerator.Threads.size(); iter++) { BackingNoiseGenerator.Threads[iter] = std::thread(&BackingNoiseGenerator_t::run, &BackingNoiseGenerator, iter); } - BackingAsyncLua.Threads.resize(2); + BackingAsyncLua.Threads.resize(4); for(size_t iter = 0; iter < BackingAsyncLua.Threads.size(); iter++) { BackingAsyncLua.Threads[iter] = std::thread(&BackingAsyncLua_t::run, &BackingAsyncLua, iter); } @@ -65,17 +65,23 @@ GameServer::~GameServer() { } void GameServer::BackingChunkPressure_t::run(int id) { + // static thread_local int local_counter = -1; + int iteration = 0; LOG.debug() << "Старт потока " << id; try { while(true) { + // local_counter++; + // LOG.debug() << "Ожидаю начала " << id << ' ' << local_counter; { std::unique_lock lock(Mutex); - Symaphore.wait(lock, [&](){ return RunCollect != 0 || NeedShutdown; }); + Symaphore.wait(lock, [&](){ return iteration != Iteration || NeedShutdown; }); if(NeedShutdown) { LOG.debug() << "Завершение выполнения потока " << id; break; } + + iteration = Iteration; } // Сбор данных @@ -97,20 +103,19 @@ void GameServer::BackingChunkPressure_t::run(int id) { for(const auto& [regionPos, region] : worldObj.Regions) { auto& regionObj = *region; - if(counter++ % pullSize != 0) { - counter %= pullSize; + if(counter++ % pullSize != id) { continue; } Dump dumpRegion; + dumpRegion.CECs = regionObj.CECs; dumpRegion.IsChunkChanged_Voxels = regionObj.IsChunkChanged_Voxels; regionObj.IsChunkChanged_Voxels = 0; dumpRegion.IsChunkChanged_Nodes = regionObj.IsChunkChanged_Nodes; regionObj.IsChunkChanged_Nodes = 0; if(!regionObj.NewCECs.empty()) { - dumpRegion.CECs = regionObj.CECs; dumpRegion.NewCECs = std::move(regionObj.NewCECs); dumpRegion.Voxels = regionObj.Voxels; @@ -123,9 +128,9 @@ void GameServer::BackingChunkPressure_t::run(int id) { std::copy(fromPtr, fromPtr+16*16*16, toPtr.data()); } } else { - if(regionObj.IsChunkChanged_Voxels) { + if(dumpRegion.IsChunkChanged_Voxels) { for(int index = 0; index < 64; index++) { - if((regionObj.IsChunkChanged_Voxels >> index) & 0x1) + if(((dumpRegion.IsChunkChanged_Voxels >> index) & 0x1) == 0) continue; Pos::bvec4u chunkPos; @@ -140,9 +145,9 @@ void GameServer::BackingChunkPressure_t::run(int id) { } } - if(regionObj.IsChunkChanged_Nodes) { + if(dumpRegion.IsChunkChanged_Nodes) { for(int index = 0; index < 64; index++) { - if((regionObj.IsChunkChanged_Nodes >> index) & 0x1) + if(((dumpRegion.IsChunkChanged_Nodes >> index) & 0x1) == 0) continue; Pos::bvec4u chunkPos; @@ -166,9 +171,10 @@ void GameServer::BackingChunkPressure_t::run(int id) { } // Синхронизация + // LOG.debug() << "Синхронизирую " << id << ' ' << local_counter; { std::unique_lock lock(Mutex); - RunCollect--; + RunCollect -= 1; Symaphore.notify_all(); } @@ -207,7 +213,7 @@ void GameServer::BackingChunkPressure_t::run(int id) { if((region.IsChunkChanged_Voxels >> chunkPos.pack()) & 0x1) { for(auto& ptr : region.CECs) { bool skip = false; - for(auto& ptr2 : region.CECs) { + for(auto& ptr2 : region.NewCECs) { if(ptr == ptr2) { skip = true; break; @@ -246,7 +252,7 @@ void GameServer::BackingChunkPressure_t::run(int id) { if((region.IsChunkChanged_Nodes >> chunkPos.pack()) & 0x1) { for(auto& ptr : region.CECs) { bool skip = false; - for(auto& ptr2 : region.CECs) { + for(auto& ptr2 : region.NewCECs) { if(ptr == ptr2) { skip = true; break; @@ -315,9 +321,10 @@ void GameServer::BackingChunkPressure_t::run(int id) { } // Синхронизация + // LOG.debug() << "Конец " << id << ' ' << local_counter; { std::unique_lock lock(Mutex); - RunCompress--; + RunCompress -= 1; Symaphore.notify_all(); } } @@ -364,7 +371,9 @@ void GameServer::BackingNoiseGenerator_t::run(int id) { for(int z = 0; z < 64; z++) for(int y = 0; y < 64; y++) for(int x = 0; x < 64; x++, ptr++) { - *ptr = TOS::genRand(); //glm::perlin(glm::vec3(posNode.x+x, posNode.y+y, posNode.z+z)); + // *ptr = TOS::genRand(); + *ptr = glm::perlin(glm::vec3(posNode.x+x, posNode.y+y, posNode.z+z) / 16.13f); + //*ptr = std::pow(*ptr, 0.75f)*1.5f; } Output.lock()->push_back({key, std::move(data)}); @@ -403,15 +412,17 @@ void GameServer::BackingAsyncLua_t::run(int id) { lock->pop(); } + //if(key.RegionPos == Pos::GlobalRegion(0, 0, 0)) { + float *ptr = noise.data(); for(int z = 0; z < 64; z++) for(int y = 0; y < 64; y++) - for(int x = 0; x < 64; x++) { - // DefVoxelId_t id = *ptr > 0.9 ? 1 : 0; + for(int x = 0; x < 64; x++, ptr++) { + DefVoxelId_t id = std::clamp(*ptr, 0.f, 1.f) * 3; //> 0.9 ? 1 : 0; Pos::bvec64u nodePos(x, y, z); auto &node = out.Nodes[Pos::bvec4u(nodePos >> 4).pack()][Pos::bvec16u(nodePos & 0xf).pack()]; - // node.NodeId = id; - // node.Meta = 0; + node.NodeId = id; + node.Meta = 0; if(x == 0 && z == 0) node.NodeId = 1; @@ -419,12 +430,21 @@ void GameServer::BackingAsyncLua_t::run(int id) { node.NodeId = 2; else if(x == 0 && y == 0) node.NodeId = 3; - else + + if(y == 1 && z == 0) + node.NodeId = 0; + else if(x == 0 && y == 1) node.NodeId = 0; - node.Meta = 0; + // node.Meta = 0; } - } + } + // else { + // Node *ptr = (Node*) &out.Nodes[0][0]; + // Node node; + // node.Data = 0; + // std::fill(ptr, ptr+64*64*64, node); + // } RegionOut.lock()->push_back({key, out}); } @@ -799,7 +819,7 @@ void GameServer::stepConnections() { } void GameServer::stepModInitializations() { - + BackingChunkPressure.endWithResults(); } IWorldSaveBackend::TickSyncInfo_Out GameServer::stepDatabaseSync() { @@ -1422,6 +1442,32 @@ void GameServer::stepGlobalStep() { void GameServer::stepSyncContent() { for(std::shared_ptr& cec : Game.CECs) { cec->onUpdate(); + + while(!cec->Build.empty()) { + Pos::GlobalNode node = cec->Build.front(); + cec->Build.pop(); + + Pos::GlobalRegion rPos = node >> 6; + Pos::bvec4u cPos = (node >> 4) & 0x3; + Pos::bvec16u nPos = node & 0xf; + + auto ®ion = Expanse.Worlds[0]->Regions[rPos]; + region->Nodes[cPos.pack()][nPos.pack()].NodeId = 4; + region->IsChunkChanged_Nodes |= 1ull << cPos.pack(); + } + + while(!cec->Break.empty()) { + Pos::GlobalNode node = cec->Break.front(); + cec->Break.pop(); + + Pos::GlobalRegion rPos = node >> 6; + Pos::bvec4u cPos = (node >> 4) & 0x3; + Pos::bvec16u nPos = node & 0xf; + + auto ®ion = Expanse.Worlds[0]->Regions[rPos]; + region->Nodes[cPos.pack()][nPos.pack()].NodeId = 0; + region->IsChunkChanged_Nodes |= 1ull << cPos.pack(); + } } // Оповещения о ресурсах и профилях diff --git a/Src/Server/GameServer.hpp b/Src/Server/GameServer.hpp index 608e2a2..301cc22 100644 --- a/Src/Server/GameServer.hpp +++ b/Src/Server/GameServer.hpp @@ -145,16 +145,18 @@ class GameServer : public AsyncObject { */ struct BackingChunkPressure_t { TOS::Logger LOG = "BackingChunkPressure"; - bool NeedShutdown = false; + volatile bool NeedShutdown = false; std::vector Threads; std::mutex Mutex; - int RunCollect = 0, RunCompress = 0; + volatile int RunCollect = 0, RunCompress = 0, Iteration = 0; std::condition_variable Symaphore; std::unordered_map> *Worlds; void startCollectChanges() { std::lock_guard lock(Mutex); - RunCompress = RunCollect = Threads.size(); + RunCollect = Threads.size(); + RunCompress = Threads.size(); + Iteration += 1; Symaphore.notify_all(); } diff --git a/Src/Server/RemoteClient.cpp b/Src/Server/RemoteClient.cpp index 452d706..c514b1e 100644 --- a/Src/Server/RemoteClient.cpp +++ b/Src/Server/RemoteClient.cpp @@ -105,7 +105,7 @@ bool RemoteClient::maybe_prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::Globa if(iterWorld != ResUses.RefChunk.end()) // Исключим зависимости предыдущей версии чанка { - auto iterRegion = iterWorld->second.find(chunkPos); + auto iterRegion = iterWorld->second.find(regionPos); if(iterRegion != iterWorld->second.end()) { // Уменьшим счётчик зависимостей for(const DefVoxelId_t& id : iterRegion->second[localChunk.pack()].Voxel) { @@ -128,6 +128,8 @@ bool RemoteClient::maybe_prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::Globa if(!newTypes.empty()) { // Добавляем новые типы в запрос NextRequest.Voxel.insert(NextRequest.Voxel.end(), newTypes.begin(), newTypes.end()); + for(DefVoxelId_t voxel : newTypes) + ResUses.RefDefVoxel[voxel] = {}; } if(!lostTypes.empty()) { @@ -181,7 +183,7 @@ bool RemoteClient::maybe_prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::Global if(iterWorld != ResUses.RefChunk.end()) // Исключим зависимости предыдущей версии чанка { - auto iterRegion = iterWorld->second.find(chunkPos); + auto iterRegion = iterWorld->second.find(regionPos); if(iterRegion != iterWorld->second.end()) { // Уменьшим счётчик зависимостей for(const DefNodeId_t& id : iterRegion->second[localChunk.pack()].Node) { @@ -204,6 +206,8 @@ bool RemoteClient::maybe_prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::Global if(!newTypes.empty()) { // Добавляем новые типы в запрос NextRequest.Node.insert(NextRequest.Node.end(), newTypes.begin(), newTypes.end()); + for(DefNodeId_t node : newTypes) + ResUses.RefDefNode[node] = {}; } if(!lostTypes.empty()) { @@ -259,6 +263,8 @@ void RemoteClient::prepareRegionRemove(WorldId_t worldId, Pos::GlobalRegion regi } } } + + iterWorld->second.erase(iterRegion); } } @@ -675,6 +681,12 @@ coro<> RemoteClient::rP_System(Net::AsyncSocket &sock) { co_return; } + case ToServer::L2System::BlockChange: + { + uint8_t action = co_await sock.read(); + Actions.lock()->push(action); + co_return; + } default: protocolError(); } diff --git a/Src/Server/RemoteClient.hpp b/Src/Server/RemoteClient.hpp index 1716c12..cf45b95 100644 --- a/Src/Server/RemoteClient.hpp +++ b/Src/Server/RemoteClient.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -296,6 +297,7 @@ public: const std::string Username; Pos::Object CameraPos = {0, 0, 0}; ToServer::PacketQuat CameraQuat = {0}; + TOS::SpinlockObject> Actions; public: RemoteClient(asio::io_context &ioc, tcp::socket socket, const std::string username, std::vector &&client_cache) diff --git a/Src/TOSLib.hpp b/Src/TOSLib.hpp index 0bb3dff..598a055 100644 --- a/Src/TOSLib.hpp +++ b/Src/TOSLib.hpp @@ -13,6 +13,7 @@ #define _USE_MATH_DEFINES #include #include +#include namespace TOS { diff --git a/Src/main.cpp b/Src/main.cpp index 1b9714d..657bba3 100644 --- a/Src/main.cpp +++ b/Src/main.cpp @@ -1,3 +1,4 @@ +#include "Common/Abstract.hpp" #include #include #include @@ -20,9 +21,10 @@ int main() { // LuaVox asio::io_context ioc; + Logger LOG = "main"; LV::Client::VK::Vulkan vkInst(ioc); - + ioc.run(); return 0; diff --git a/assets/textures/0.png b/assets/textures/0.png new file mode 100644 index 0000000..4b48a99 Binary files /dev/null and b/assets/textures/0.png differ diff --git a/assets/textures/8.png b/assets/textures/8.png deleted file mode 100644 index 6a989b8..0000000 Binary files a/assets/textures/8.png and /dev/null differ diff --git a/assets/textures/grass.png b/assets/textures/grass.png index 4b48a99..3ec069c 100644 Binary files a/assets/textures/grass.png and b/assets/textures/grass.png differ diff --git a/assets/textures/xnether_purple_wood.png b/assets/textures/xnether_purple_wood.png index 3ec069c..6a989b8 100644 Binary files a/assets/textures/xnether_purple_wood.png and b/assets/textures/xnether_purple_wood.png differ