*
@@ -17,9 +17,14 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # -rdy
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
|
||||
|
||||
# sanitizer
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment")
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fsanitize=address -fno-omit-frame-pointer")
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -fsanitize=address")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
|
||||
|
||||
project(LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
||||
|
||||
|
||||
BIN
Cache/db.sqlite3
Normal file
@@ -286,6 +286,7 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||
|
||||
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);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<0>(pair).insert(p.Pos);
|
||||
} else if(l2 == ToClient::L2Content::RemoveRegion) {
|
||||
@@ -293,11 +294,12 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||
|
||||
auto ®ions = Data.Worlds[p.Id].Regions;
|
||||
auto obj = regions.find(p.Pos);
|
||||
assert(obj != regions.end());
|
||||
regions.erase(obj);
|
||||
if(obj != regions.end()) {
|
||||
regions.erase(obj);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<1>(pair).insert(p.Pos);
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<1>(pair).insert(p.Pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +585,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
|
||||
co_return;
|
||||
case ToClient::L2Content::RemoveRegion: {
|
||||
WorldId_t wcId = co_await sock.read<uint8_t>();
|
||||
WorldId_t wcId = co_await sock.read<WorldId_t>();
|
||||
Pos::GlobalChunk pos;
|
||||
pos.unpack(co_await sock.read<Pos::GlobalRegion::Pack>());
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace LV::Client::VK {
|
||||
|
||||
Получаемые вершины сначала пишутся в общий буфер, потом передаются на устройство
|
||||
*/
|
||||
// Нужна реализация индексного буфера
|
||||
template<typename Vertex, uint16_t PerBlock = 1 << 10, uint16_t PerPool = 1 << 12>
|
||||
class VertexPool {
|
||||
static constexpr size_t HC_Buffer_Size = size_t(PerBlock)*size_t(PerPool);
|
||||
@@ -63,8 +64,9 @@ private:
|
||||
// Пишем в общий буфер, TasksWait
|
||||
Vertex *ptr = HCPtr+WritePos;
|
||||
std::copy(data.begin(), data.end(), ptr);
|
||||
size_t count = data.size();
|
||||
TasksWait.push({std::move(data), WritePos, poolId, blockId});
|
||||
WritePos += data.size();
|
||||
WritePos += count;
|
||||
} else {
|
||||
// Отложим запись на следующий такт
|
||||
TasksPostponed.push(Task(std::move(data), -1, poolId, blockId));
|
||||
@@ -219,7 +221,9 @@ public:
|
||||
void update(VkCommandPool commandPool) {
|
||||
if(TasksWait.empty())
|
||||
return;
|
||||
|
||||
|
||||
assert(WritePos);
|
||||
|
||||
VkCommandBufferAllocateInfo allocInfo {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
nullptr,
|
||||
@@ -240,6 +244,28 @@ public:
|
||||
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
|
||||
VkBufferMemoryBarrier barrier = {
|
||||
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
nullptr,
|
||||
VK_ACCESS_HOST_WRITE_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
HostCoherent.getBuffer(),
|
||||
0,
|
||||
WritePos*sizeof(Vertex)
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
commandBuffer,
|
||||
VK_PIPELINE_STAGE_HOST_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
1, &barrier,
|
||||
0, nullptr
|
||||
);
|
||||
|
||||
while(!TasksWait.empty()) {
|
||||
Task& task = TasksWait.front();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Client/ServerSession.hpp"
|
||||
#include "Common/Async.hpp"
|
||||
#include "Common/Net.hpp"
|
||||
#include "TOSLib.hpp"
|
||||
#include "assets.hpp"
|
||||
#include "imgui.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
@@ -216,6 +217,7 @@ void Vulkan::run()
|
||||
} else if (err == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
LOGGER.debug() << "VK_SUBOPTIMAL_KHR Pre";
|
||||
continue;
|
||||
} else if(err == VK_SUCCESS) {
|
||||
|
||||
Screen.State = DrawState::Drawing;
|
||||
@@ -2079,6 +2081,17 @@ 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;
|
||||
if(!flag) {
|
||||
flag = true;
|
||||
Game.Server = std::make_unique<ServerObj>(IOC);
|
||||
ConnectionProgress.Progress = "Сервер запущен на порту " + std::to_string(Game.Server->LS.getPort());
|
||||
ConnectionProgress.InProgress = true;
|
||||
ConnectionProgress.Cancel = false;
|
||||
ConnectionProgress.Progress.clear();
|
||||
co_spawn(ConnectionProgress.connect(IOC));
|
||||
}
|
||||
|
||||
if(!ConnectionProgress.InProgress && !ConnectionProgress.Socket) {
|
||||
if(ImGui::Button("Подключиться")) {
|
||||
ConnectionProgress.InProgress = true;
|
||||
@@ -3510,6 +3523,8 @@ void DynamicImage::changeData(int32_t x, int32_t y, uint16_t width, uint16_t hei
|
||||
// Выполняем все команды
|
||||
buffer.execute();
|
||||
|
||||
Time::sleep3(50);
|
||||
|
||||
// Удаляем не нужную картинку
|
||||
vkDestroyImage(Instance->Graphics.Device, tempImage, nullptr);
|
||||
vkFreeMemory(Instance->Graphics.Device, tempMemory, nullptr);
|
||||
|
||||
@@ -197,12 +197,18 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
||||
return true;
|
||||
});
|
||||
|
||||
{
|
||||
uint16_t texId = VKCTX->MainTest.atlasAddTexture(2, 2);
|
||||
uint32_t colors[4] = {0xfffffffful, 0x00fffffful, 0xffffff00ul, 0xff00fffful};
|
||||
VKCTX->MainTest.atlasChangeTextureData(texId, (const uint32_t*) colors);
|
||||
}
|
||||
|
||||
int width, height;
|
||||
bool hasAlpha;
|
||||
for(const char *path : {
|
||||
"grass.png",
|
||||
"tropical_rainforest_wood.png",
|
||||
"willow_wood.png",
|
||||
"tropical_rainforest_wood.png",
|
||||
"xnether_blue_wood.png",
|
||||
"xnether_purple_wood.png"
|
||||
}) {
|
||||
@@ -617,12 +623,6 @@ void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered
|
||||
auto &table = External.ChunkVoxelMesh[worldId];
|
||||
|
||||
for(Pos::GlobalChunk pos : changeOrAddList) {
|
||||
if(pos.y < 0) {
|
||||
int g = 0;
|
||||
g++;
|
||||
}
|
||||
|
||||
|
||||
Pos::GlobalRegion rPos = pos >> 2;
|
||||
Pos::bvec4u cPos = pos & 0x3;
|
||||
|
||||
@@ -639,6 +639,7 @@ void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered
|
||||
}
|
||||
|
||||
std::vector<NodeVertexStatic> vertexs2 = generateMeshForNodeChunks(chunk.Nodes);
|
||||
|
||||
if(vertexs2.empty()) {
|
||||
VKCTX->VertexPool_Nodes.dropVertexs(std::get<1>(buffers));
|
||||
} else {
|
||||
@@ -697,7 +698,7 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff
|
||||
// Сместить в координаты игрока, повернуть относительно взгляда проецировать на экран
|
||||
// Изначально взгляд в z-1
|
||||
PCO.ProjView = glm::mat4(1);
|
||||
PCO.ProjView = glm::translate(PCO.ProjView, -glm::vec3(Pos)/float(Pos::Object_t::BS));
|
||||
PCO.ProjView = glm::translate(PCO.ProjView, -glm::vec3(Pos.z, Pos.y, Pos.x)/float(Pos::Object_t::BS));
|
||||
PCO.ProjView = proj*glm::mat4(Quat)*PCO.ProjView;
|
||||
PCO.Model = glm::mat4(1);
|
||||
|
||||
@@ -771,7 +772,7 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff
|
||||
|
||||
for(auto &pair : iterWorld->second) {
|
||||
if(auto& nodes = std::get<1>(pair.second)) {
|
||||
glm::vec3 cpos(pair.first.x, pair.first.y, pair.first.z);
|
||||
glm::vec3 cpos(pair.first.z, pair.first.y, pair.first.x);
|
||||
PCO.Model = glm::translate(orig, cpos*16.f);
|
||||
auto [vkBuffer, offset] = VKCTX->VertexPool_Nodes.map(nodes);
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ struct Object_t {
|
||||
static glm::vec3 asFloatVec(const Object &obj) { return glm::vec3(float(obj[0])/float(BS), float(obj[1])/float(BS), float(obj[2])/float(BS)); }
|
||||
static GlobalNode asNodePos(const Object &obj) { return (GlobalNode) (obj >> BS_Bit); }
|
||||
static GlobalChunk asChunkPos(const Object &obj) { return (GlobalChunk) (obj >> BS_Bit >> 4); }
|
||||
static GlobalRegion asRegionsPos(const Object &obj) { return (GlobalRegion) (obj >> BS_Bit >> 8); }
|
||||
static GlobalRegion asRegionsPos(const Object &obj) { return (GlobalRegion) (obj >> BS_Bit >> 6); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,22 +24,28 @@ struct PacketQuat {
|
||||
z = (quat.z+1)/2*0x3ff,
|
||||
w = (quat.w+1)/2*0x3ff;
|
||||
|
||||
for(uint8_t &val : Data)
|
||||
val = 0;
|
||||
uint64_t value = 0;
|
||||
|
||||
*(uint16_t*) Data |= x;
|
||||
*(uint16_t*) (Data+1) |= y << 2;
|
||||
*(uint16_t*) (Data+2) |= z << 4;
|
||||
*(uint16_t*) (Data+3) |= w << 6;
|
||||
value |= x & 0x3ff;
|
||||
value |= uint64_t(y & 0x3ff) << 10;
|
||||
value |= uint64_t(z & 0x3ff) << 20;
|
||||
value |= uint64_t(w & 0x3ff) << 30;
|
||||
|
||||
for(int iter = 0; iter < 5; iter++)
|
||||
Data[iter] = (value >> (iter * 8)) & 0xff;
|
||||
}
|
||||
|
||||
glm::quat toQuat() const {
|
||||
const uint64_t &data = (const uint64_t&) *Data;
|
||||
uint64_t value = 0;
|
||||
|
||||
for(int iter = 0; iter < 5; iter++)
|
||||
value |= (Data[iter] >> (iter*10)) & 0x3ff;
|
||||
|
||||
uint16_t
|
||||
x = data & 0x3ff,
|
||||
y = (data >> 10) & 0x3ff,
|
||||
z = (data >> 20) & 0x3ff,
|
||||
w = (data >> 30) & 0x3ff;
|
||||
x = value & 0x3ff,
|
||||
y = (value >> 10) & 0x3ff,
|
||||
z = (value >> 20) & 0x3ff,
|
||||
w = (value >> 30) & 0x3ff;
|
||||
|
||||
float fx = (float(x)/0x3ff)*2-1;
|
||||
float fy = (float(y)/0x3ff)*2-1;
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace LV::Server {
|
||||
ContentEventController::ContentEventController(std::unique_ptr<RemoteClient> &&remote)
|
||||
: Remote(std::move(remote))
|
||||
{
|
||||
LastPos = Pos = {0, Remote->CameraPos};
|
||||
}
|
||||
|
||||
uint16_t ContentEventController::getViewRangeBackground() const {
|
||||
@@ -18,11 +19,11 @@ uint16_t ContentEventController::getViewRangeBackground() const {
|
||||
}
|
||||
|
||||
ServerObjectPos ContentEventController::getLastPos() const {
|
||||
return {0, Remote->CameraPos};
|
||||
return LastPos;
|
||||
}
|
||||
|
||||
ServerObjectPos ContentEventController::getPos() const {
|
||||
return {0, Remote->CameraPos};
|
||||
return Pos;
|
||||
}
|
||||
|
||||
void ContentEventController::removeUnobservable(const ContentViewInfo_Diff& diff) {
|
||||
@@ -97,4 +98,15 @@ void ContentEventController::onPortalUpdates(const std::vector<void*> &portals)
|
||||
|
||||
}
|
||||
|
||||
void ContentEventController::onUpdate() {
|
||||
LastPos = Pos;
|
||||
Pos.ObjectPos = Remote->CameraPos;
|
||||
|
||||
Pos::GlobalRegion r1 = LastPos.ObjectPos >> 12 >> 4 >> 2;
|
||||
Pos::GlobalRegion r2 = Pos.ObjectPos >> 12 >> 4 >> 2;
|
||||
if(r1 != r2) {
|
||||
CrossedBorder = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Common/Abstract.hpp>
|
||||
#include "Abstract.hpp"
|
||||
#include "TOSLib.hpp"
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
@@ -56,6 +57,10 @@ 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);
|
||||
@@ -64,6 +69,10 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +83,10 @@ 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);
|
||||
@@ -82,6 +95,10 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +152,8 @@ public:
|
||||
// Если игрок пересекал границы чанка (для перерасчёта ContentViewState)
|
||||
bool CrossedBorder = true;
|
||||
|
||||
ServerObjectPos Pos, LastPos;
|
||||
|
||||
public:
|
||||
ContentEventController(std::unique_ptr<RemoteClient>&& remote);
|
||||
|
||||
@@ -160,6 +179,8 @@ public:
|
||||
|
||||
inline const SubscribedObj& getSubscribed() { return Subscribed; };
|
||||
|
||||
void onUpdate();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ GameServer::GameServer(asio::io_context &ioc, fs::path worldPath)
|
||||
for(size_t iter = 0; iter < BackingNoiseGenerator.Threads.size(); iter++) {
|
||||
BackingNoiseGenerator.Threads[iter] = std::thread(&BackingNoiseGenerator_t::run, &BackingNoiseGenerator, iter);
|
||||
}
|
||||
|
||||
BackingAsyncLua.Threads.resize(2);
|
||||
for(size_t iter = 0; iter < BackingAsyncLua.Threads.size(); iter++) {
|
||||
BackingAsyncLua.Threads[iter] = std::thread(&BackingAsyncLua_t::run, &BackingAsyncLua, iter);
|
||||
}
|
||||
}
|
||||
|
||||
GameServer::~GameServer() {
|
||||
@@ -46,6 +51,7 @@ GameServer::~GameServer() {
|
||||
BackingChunkPressure.NeedShutdown = true;
|
||||
BackingChunkPressure.Symaphore.notify_all();
|
||||
BackingNoiseGenerator.NeedShutdown = true;
|
||||
BackingAsyncLua.NeedShutdown = true;
|
||||
|
||||
RunThread.join();
|
||||
WorkDeadline.cancel();
|
||||
@@ -53,6 +59,7 @@ GameServer::~GameServer() {
|
||||
|
||||
BackingChunkPressure.stop();
|
||||
BackingNoiseGenerator.stop();
|
||||
BackingAsyncLua.stop();
|
||||
|
||||
LOG.info() << "Сервер уничтожен";
|
||||
}
|
||||
@@ -227,7 +234,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
for(auto& [chunkPos, chunk] : region.Nodes) {
|
||||
CompressedNodes cmp = compressNodes(chunk.data());
|
||||
Pos::GlobalChunk chunkPosR = (Pos::GlobalChunk(regionPos) << 2) + chunkPos;
|
||||
|
||||
|
||||
for(auto& ptr : region.NewCECs) {
|
||||
bool accepted = ptr->Remote->maybe_prepareChunkUpdate_Nodes(worldId,
|
||||
chunkPosR, cmp.Compressed, cmp.Defines);
|
||||
@@ -369,6 +376,64 @@ void GameServer::BackingNoiseGenerator_t::run(int id) {
|
||||
|
||||
}
|
||||
|
||||
void GameServer::BackingAsyncLua_t::run(int id) {
|
||||
LOG.debug() << "Старт потока " << id;
|
||||
|
||||
BackingNoiseGenerator_t::NoiseKey key;
|
||||
std::array<float, 64*64*64> noise;
|
||||
World::RegionIn out;
|
||||
|
||||
try {
|
||||
while(true) {
|
||||
if(NeedShutdown) {
|
||||
LOG.debug() << "Завершение выполнения потока " << id;
|
||||
break;
|
||||
}
|
||||
|
||||
if(NoiseIn.get_read().empty())
|
||||
TOS::Time::sleep3(50);
|
||||
|
||||
{
|
||||
auto lock = NoiseIn.lock();
|
||||
if(lock->empty())
|
||||
continue;
|
||||
|
||||
key = lock->front().first;
|
||||
noise = lock->front().second;
|
||||
lock->pop();
|
||||
}
|
||||
|
||||
{
|
||||
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;
|
||||
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;
|
||||
|
||||
if(x == 0 && z == 0)
|
||||
node.NodeId = 1;
|
||||
else if(y == 0 && z == 0)
|
||||
node.NodeId = 2;
|
||||
else if(x == 0 && y == 0)
|
||||
node.NodeId = 3;
|
||||
else
|
||||
node.NodeId = 0;
|
||||
|
||||
node.Meta = 0;
|
||||
}
|
||||
}
|
||||
|
||||
RegionOut.lock()->push_back({key, out});
|
||||
}
|
||||
} catch(const std::exception& exc) {
|
||||
NeedShutdown = true;
|
||||
LOG.error() << "Ошибка выполнения потока " << id << ":\n" << exc.what();
|
||||
}
|
||||
}
|
||||
|
||||
static thread_local std::vector<ContentViewCircle> TL_Circles;
|
||||
|
||||
std::vector<ContentViewCircle> GameServer::Expanse_t::accumulateContentViewCircles(ContentViewCircle circle, int depth)
|
||||
@@ -462,7 +527,7 @@ ContentViewInfo GameServer::Expanse_t::makeContentViewInfo(const std::vector<Con
|
||||
for(int32_t z = -regionRange; z <= regionRange; z++)
|
||||
for(int32_t y = -regionRange; y <= regionRange; y++)
|
||||
for(int32_t x = -regionRange; x <= regionRange; x++)
|
||||
cvw.push_back(Pos::GlobalRegion(x, y, z));
|
||||
cvw.push_back(Pos::GlobalRegion(x, y, z)+circle.Pos);
|
||||
}
|
||||
|
||||
for(auto& [worldId, regions] : cvi.Regions) {
|
||||
@@ -751,7 +816,7 @@ IWorldSaveBackend::TickSyncInfo_Out GameServer::stepDatabaseSync() {
|
||||
|
||||
ContentViewCircle cvc;
|
||||
cvc.WorldId = oPos.WorldId;
|
||||
cvc.Pos = Pos::Object_t::asChunkPos(oPos.ObjectPos);
|
||||
cvc.Pos = Pos::Object_t::asRegionsPos(oPos.ObjectPos);
|
||||
cvc.Range = 2;
|
||||
|
||||
std::vector<ContentViewCircle> newCVCs = Expanse.accumulateContentViewCircles(cvc);
|
||||
@@ -831,46 +896,32 @@ void GameServer::stepGeneratorAndLuaAsync(IWorldSaveBackend::TickSyncInfo_Out db
|
||||
|
||||
|
||||
// Синхронизация с генератором шума
|
||||
std::vector<std::pair<BackingNoiseGenerator_t::NoiseKey, std::array<float, 64*64*64>>> calculatedNoise = BackingNoiseGenerator.tickSync(std::move(db.NotExisten));
|
||||
|
||||
|
||||
std::unordered_map<WorldId_t, std::vector<std::pair<Pos::GlobalRegion, World::RegionIn>>> toLoadRegions;
|
||||
|
||||
// Синхронизация с контроллером асинхронных обработчиков луа
|
||||
// 2.2 и 3.1
|
||||
// Обработка шума на стороне луа
|
||||
for(auto& [key, region] : calculatedNoise) {
|
||||
auto &obj = toLoadRegions[key.WId].emplace_back(key.RegionPos, World::RegionIn()).second;
|
||||
float *ptr = ®ion[0];
|
||||
{
|
||||
std::vector<std::pair<BackingNoiseGenerator_t::NoiseKey, std::array<float, 64*64*64>>> calculatedNoise = BackingNoiseGenerator.tickSync(std::move(db.NotExisten));
|
||||
if(!calculatedNoise.empty()) {
|
||||
auto lock = BackingAsyncLua.NoiseIn.lock();
|
||||
|
||||
{
|
||||
Node node;
|
||||
node.Data = 0;
|
||||
std::fill((Node*) obj.Nodes.data(), ((Node*) obj.Nodes.data())+64*64*64, node);
|
||||
for(auto& pair : calculatedNoise)
|
||||
lock->push(pair);
|
||||
}
|
||||
|
||||
if((key.RegionPos.x == 0 || key.RegionPos.x == 0) && key.RegionPos.y == 0 && key.RegionPos.z == 0) {
|
||||
for(int z = 0; z < 64; z++)
|
||||
for(int y = 0; y < 64; y++)
|
||||
for(int x = 0; x < 64; x++, ptr++) {
|
||||
// DefVoxelId_t id = *ptr > 0.9 ? 1 : 0;
|
||||
Pos::bvec64u nodePos(x, y, z);
|
||||
auto &node = obj.Nodes[Pos::bvec4u(nodePos >> 4).pack()][Pos::bvec16u(nodePos & 0xf).pack()];
|
||||
// node.NodeId = id;
|
||||
// node.Meta = 0;
|
||||
calculatedNoise.clear();
|
||||
|
||||
if(
|
||||
(y == 0 && z == 0)
|
||||
// || (x == 0 && z == 0)
|
||||
// || (x == 0 && y == 0)
|
||||
) {
|
||||
if(x+y+z <= 18)
|
||||
node.NodeId = (((x+y+z)/3)%3)+1;
|
||||
}
|
||||
|
||||
node.Meta = 0;
|
||||
if(!BackingAsyncLua.RegionOut.get_read().empty()) {
|
||||
std::vector<
|
||||
std::pair<BackingNoiseGenerator_t::NoiseKey, World::RegionIn>
|
||||
> toLoad = std::move(*BackingAsyncLua.RegionOut.lock());
|
||||
|
||||
for(auto& [key, region] : toLoad) {
|
||||
toLoadRegions[key.WId].push_back({key.RegionPos, region});
|
||||
}
|
||||
}
|
||||
// obj.Nodes[0][0].NodeId = 1;
|
||||
}
|
||||
|
||||
// Обработка идентификаторов на стороне луа
|
||||
@@ -1369,6 +1420,10 @@ void GameServer::stepGlobalStep() {
|
||||
}
|
||||
|
||||
void GameServer::stepSyncContent() {
|
||||
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
|
||||
cec->onUpdate();
|
||||
}
|
||||
|
||||
// Оповещения о ресурсах и профилях
|
||||
Content.Texture.update(CurrentTickDuration);
|
||||
if(Content.Texture.hasPreparedInformation()) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "RemoteClient.hpp"
|
||||
#include "Server/Abstract.hpp"
|
||||
#include <TOSLib.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
@@ -122,9 +123,6 @@ class GameServer : public AsyncObject {
|
||||
/*
|
||||
Обязательно между тактами
|
||||
|
||||
Генерация шума
|
||||
OpenCL или пул
|
||||
|
||||
Конвертация ресурсов игры, их хранение в кеше и загрузка в память для отправки клиентам
|
||||
io_uring или последовательное чтение
|
||||
|
||||
@@ -184,6 +182,9 @@ class GameServer : public AsyncObject {
|
||||
void run(int id);
|
||||
} BackingChunkPressure;
|
||||
|
||||
/*
|
||||
Генератор шума
|
||||
*/
|
||||
struct BackingNoiseGenerator_t {
|
||||
struct NoiseKey {
|
||||
WorldId_t WId;
|
||||
@@ -225,6 +226,26 @@ class GameServer : public AsyncObject {
|
||||
}
|
||||
} BackingNoiseGenerator;
|
||||
|
||||
/*
|
||||
Обработчик асинронного луа
|
||||
*/
|
||||
struct BackingAsyncLua_t {
|
||||
TOS::Logger LOG = "BackingAsyncLua";
|
||||
bool NeedShutdown = false;
|
||||
std::vector<std::thread> Threads;
|
||||
TOS::SpinlockObject<std::queue<std::pair<BackingNoiseGenerator_t::NoiseKey, std::array<float, 64*64*64>>>> NoiseIn;
|
||||
TOS::SpinlockObject<std::vector<std::pair<BackingNoiseGenerator_t::NoiseKey, World::RegionIn>>> RegionOut;
|
||||
|
||||
void stop() {
|
||||
NeedShutdown = true;
|
||||
|
||||
for(std::thread& thread : Threads)
|
||||
thread.join();
|
||||
}
|
||||
|
||||
void run(int id);
|
||||
} BackingAsyncLua;
|
||||
|
||||
public:
|
||||
GameServer(asio::io_context &ioc, fs::path worldPath);
|
||||
virtual ~GameServer();
|
||||
|
||||
@@ -237,26 +237,26 @@ void RemoteClient::prepareRegionRemove(WorldId_t worldId, Pos::GlobalRegion regi
|
||||
assert(iterWorld != ResUses.RefChunk.end());
|
||||
|
||||
auto iterRegion = iterWorld->second.find(regionPos);
|
||||
assert(iterRegion != iterWorld->second.end());
|
||||
|
||||
for(const auto &iterChunk : iterRegion->second) {
|
||||
for(const DefVoxelId_t& id : iterChunk.Voxel) {
|
||||
auto iter = ResUses.DefVoxel.find(id);
|
||||
assert(iter != ResUses.DefVoxel.end()); // Воксель должен быть в зависимостях
|
||||
if(--iter->second == 0) {
|
||||
// Вокселя больше нет в зависимостях
|
||||
lostTypesV.push_back(id);
|
||||
ResUses.DefVoxel.erase(iter);
|
||||
if(iterRegion != iterWorld->second.end()) {
|
||||
for(const auto &iterChunk : iterRegion->second) {
|
||||
for(const DefVoxelId_t& id : iterChunk.Voxel) {
|
||||
auto iter = ResUses.DefVoxel.find(id);
|
||||
assert(iter != ResUses.DefVoxel.end()); // Воксель должен быть в зависимостях
|
||||
if(--iter->second == 0) {
|
||||
// Вокселя больше нет в зависимостях
|
||||
lostTypesV.push_back(id);
|
||||
ResUses.DefVoxel.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const DefNodeId_t& id : iterChunk.Node) {
|
||||
auto iter = ResUses.DefNode.find(id);
|
||||
assert(iter != ResUses.DefNode.end()); // Нода должна быть в зависимостях
|
||||
if(--iter->second == 0) {
|
||||
// Ноды больше нет в зависимостях
|
||||
lostTypesN.push_back(id);
|
||||
ResUses.DefNode.erase(iter);
|
||||
for(const DefNodeId_t& id : iterChunk.Node) {
|
||||
auto iter = ResUses.DefNode.find(id);
|
||||
assert(iter != ResUses.DefNode.end()); // Нода должна быть в зависимостях
|
||||
if(--iter->second == 0) {
|
||||
// Ноды больше нет в зависимостях
|
||||
lostTypesN.push_back(id);
|
||||
ResUses.DefNode.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -663,9 +663,12 @@ coro<> RemoteClient::rP_System(Net::AsyncSocket &sock) {
|
||||
}
|
||||
case ToServer::L2System::Test_CAM_PYR_POS:
|
||||
{
|
||||
CameraPos.x = co_await sock.read<decltype(CameraPos.x)>();
|
||||
CameraPos.y = co_await sock.read<decltype(CameraPos.x)>();
|
||||
CameraPos.z = co_await sock.read<decltype(CameraPos.x)>();
|
||||
Pos::Object newPos;
|
||||
newPos.x = co_await sock.read<decltype(CameraPos.x)>();
|
||||
newPos.y = co_await sock.read<decltype(CameraPos.y)>();
|
||||
newPos.z = co_await sock.read<decltype(CameraPos.z)>();
|
||||
|
||||
CameraPos = newPos;
|
||||
|
||||
for(int iter = 0; iter < 5; iter++)
|
||||
CameraQuat.Data[iter] = co_await sock.read<uint8_t>();
|
||||
|
||||
BIN
assets/textures/8.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 14 KiB |
BIN
assets/textures/grass.png~
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 10 KiB |