This commit is contained in:
2025-07-12 03:27:20 +06:00
parent dbe2e2c33c
commit 9c64b893cf
21 changed files with 408 additions and 182 deletions

View File

@@ -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);
}
}
}
}
}

View File

@@ -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);

View File

@@ -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 &region = 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 &region = Expanse.Worlds[0]->Regions[rPos];
region->Nodes[cPos.pack()][nPos.pack()].NodeId = 0;
region->IsChunkChanged_Nodes |= 1ull << cPos.pack();
}
}
// Оповещения о ресурсах и профилях

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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)