*
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -39,7 +39,7 @@ struct Chunk {
|
||||
// Кубы вокселей в чанке
|
||||
std::vector<VoxelCube> Voxels;
|
||||
// Ноды
|
||||
Node Nodes[16][16][16];
|
||||
std::array<Node, 16*16*16> Nodes;
|
||||
// Ограничения прохождения света, идущего от солнца (от верха карты до верхней плоскости чанка)
|
||||
// LightPrism Lights[16][16];
|
||||
};
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
};
|
||||
|
||||
struct Region {
|
||||
Chunk Chunks[4][4][4];
|
||||
std::array<Chunk, 4*4*4> 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:
|
||||
|
||||
@@ -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<Node, 16*16*16> 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<float>(), 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<uint32_t>();
|
||||
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<uint32_t>();
|
||||
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<WorldId_t>();
|
||||
Pos::GlobalChunk pos;
|
||||
Pos::GlobalRegion pos;
|
||||
pos.unpack(co_await sock.read<Pos::GlobalRegion::Pack>());
|
||||
|
||||
PP_Content_RegionRemove *packet = new PP_Content_RegionRemove(
|
||||
|
||||
@@ -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<ServerObj>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<EnumDefContent
|
||||
|
||||
}
|
||||
|
||||
int changed = 0;
|
||||
void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk>& changeOrAddList, const std::unordered_set<Pos::GlobalRegion>& 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<NodeVertexStatic> vertexs2 = generateMeshForNodeChunks(chunk.Nodes);
|
||||
std::vector<NodeVertexStatic> 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<float>(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<float>()), {1, 0, 0});
|
||||
rotate = glm::rotate(rotate, Delta/16*(2*glm::pi<float>()), {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<float>(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<VoxelVertexPoint> VulkanRenderSession::generateMeshForVoxelChunks(const std::vector<VoxelCube> cubes) {
|
||||
@@ -912,7 +964,7 @@ std::vector<VoxelVertexPoint> VulkanRenderSession::generateMeshForVoxelChunks(co
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<NodeVertexStatic> VulkanRenderSession::generateMeshForNodeChunks(const Node nodes[16][16][16]) {
|
||||
std::vector<NodeVertexStatic> VulkanRenderSession::generateMeshForNodeChunks(const Node* nodes) {
|
||||
std::vector<NodeVertexStatic> out;
|
||||
NodeVertexStatic v;
|
||||
|
||||
@@ -920,15 +972,16 @@ std::vector<NodeVertexStatic> 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<NodeVertexStatic> 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<NodeVertexStatic> 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<NodeVertexStatic> 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<NodeVertexStatic> 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<NodeVertexStatic> 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);
|
||||
}
|
||||
|
||||
@@ -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<VoxelVertexPoint> generateMeshForVoxelChunks(const std::vector<VoxelCube> cubes);
|
||||
static std::vector<NodeVertexStatic> generateMeshForNodeChunks(const Node nodes[16][16][16]);
|
||||
static std::vector<NodeVertexStatic> generateMeshForNodeChunks(const Node* nodes);
|
||||
|
||||
private:
|
||||
void updateDescriptor_MainAtlas();
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "Abstract.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/iostreams/filtering_streambuf.hpp>
|
||||
#include <boost/iostreams/copy.hpp>
|
||||
#include <boost/iostreams/filter/zlib.hpp>
|
||||
#include <cstddef>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace LV {
|
||||
@@ -99,7 +103,7 @@ CompressedVoxels compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
}
|
||||
}
|
||||
|
||||
return {compressed, defines};
|
||||
return {compressLinear(compressed), defines};
|
||||
}
|
||||
|
||||
CompressedVoxels compressVoxels_bit(const std::vector<VoxelCube>& voxels) {
|
||||
@@ -245,7 +249,7 @@ CompressedVoxels compressVoxels_bit(const std::vector<VoxelCube>& 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<VoxelCube>& voxels, bool fast) {
|
||||
@@ -419,10 +423,11 @@ std::vector<VoxelCube> unCompressVoxels_bit(const std::u8string& compressed) {
|
||||
}
|
||||
|
||||
std::vector<VoxelCube> 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<DefNodeId_t> 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<boost::iostreams::input> 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<boost::iostreams::input> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/Net.hpp"
|
||||
#include "TOSLib.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <glm/ext.hpp>
|
||||
@@ -90,7 +91,7 @@ public:
|
||||
using U = std::make_unsigned_t<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<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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@@ -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<Pos::GlobalNode> Build, Break;
|
||||
|
||||
public:
|
||||
ContentEventController(std::unique_ptr<RemoteClient>&& remote);
|
||||
|
||||
@@ -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<std::mutex> 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<std::mutex> 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<std::mutex> 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<ContentEventController>& 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();
|
||||
}
|
||||
}
|
||||
|
||||
// Оповещения о ресурсах и профилях
|
||||
|
||||
@@ -145,16 +145,18 @@ class GameServer : public AsyncObject {
|
||||
*/
|
||||
struct BackingChunkPressure_t {
|
||||
TOS::Logger LOG = "BackingChunkPressure";
|
||||
bool NeedShutdown = false;
|
||||
volatile bool NeedShutdown = false;
|
||||
std::vector<std::thread> Threads;
|
||||
std::mutex Mutex;
|
||||
int RunCollect = 0, RunCompress = 0;
|
||||
volatile int RunCollect = 0, RunCompress = 0, Iteration = 0;
|
||||
std::condition_variable Symaphore;
|
||||
std::unordered_map<WorldId_t, std::unique_ptr<World>> *Worlds;
|
||||
|
||||
void startCollectChanges() {
|
||||
std::lock_guard<std::mutex> lock(Mutex);
|
||||
RunCompress = RunCollect = Threads.size();
|
||||
RunCollect = Threads.size();
|
||||
RunCompress = Threads.size();
|
||||
Iteration += 1;
|
||||
Symaphore.notify_all();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<uint8_t>();
|
||||
Actions.lock()->push(action);
|
||||
co_return;
|
||||
}
|
||||
default:
|
||||
protocolError();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <initializer_list>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
@@ -296,6 +297,7 @@ public:
|
||||
const std::string Username;
|
||||
Pos::Object CameraPos = {0, 0, 0};
|
||||
ToServer::PacketQuat CameraQuat = {0};
|
||||
TOS::SpinlockObject<std::queue<uint8_t>> Actions;
|
||||
|
||||
public:
|
||||
RemoteClient(asio::io_context &ioc, tcp::socket socket, const std::string username, std::vector<HASH> &&client_cache)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
namespace TOS {
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "Common/Abstract.hpp"
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <boost/asio.hpp>
|
||||
@@ -20,9 +21,10 @@ int main() {
|
||||
|
||||
// LuaVox
|
||||
asio::io_context ioc;
|
||||
Logger LOG = "main";
|
||||
|
||||
LV::Client::VK::Vulkan vkInst(ioc);
|
||||
|
||||
|
||||
ioc.run();
|
||||
|
||||
return 0;
|
||||
|
||||
BIN
assets/textures/0.png
Normal file
BIN
assets/textures/0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.8 KiB |
Reference in New Issue
Block a user