Сейчас оно компилируется, пересмотр расчёта зон наблюдения
This commit is contained in:
@@ -34,7 +34,12 @@ struct GlobalTime {
|
||||
};
|
||||
|
||||
struct VoxelCube {
|
||||
DefVoxelId_t VoxelId;
|
||||
union {
|
||||
struct {
|
||||
DefVoxelId_t VoxelId : 24, Meta : 8;
|
||||
};
|
||||
DefVoxelId_t Data;
|
||||
};
|
||||
Pos::bvec256u Left, Size;
|
||||
};
|
||||
|
||||
@@ -77,39 +82,32 @@ public:
|
||||
virtual void onBinaryResourceAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, BinaryResource>>) = 0;
|
||||
virtual void onBinaryResourceLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) = 0;
|
||||
|
||||
// Профили использования двоичных ресурсов
|
||||
// В этом месте нужно зарание распарсить
|
||||
virtual void onBinaryProfileAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, std::u8string>>) = 0;
|
||||
virtual void onBinaryProfileLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) = 0;
|
||||
|
||||
virtual void onContentDefines(std::unordered_map<EnumDefContent, std::unordered_map<>>);
|
||||
EnumDefContent
|
||||
|
||||
virtual void onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) = 0;
|
||||
virtual void onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) = 0;
|
||||
virtual void onDefNodeUpdates(const std::vector<DefNodeId_c> &updates) = 0;
|
||||
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) = 0;
|
||||
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) = 0;
|
||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::unordered_map<ResourceId_t, std::u8string>>) = 0;
|
||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) = 0;
|
||||
|
||||
// Сообщаем об изменившихся чанках
|
||||
virtual void onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) = 0;
|
||||
virtual void onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) = 0;
|
||||
// Установить позицию для камеры
|
||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) = 0;
|
||||
virtual void setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) = 0;
|
||||
|
||||
virtual ~IRenderSession();
|
||||
};
|
||||
|
||||
|
||||
struct Region {
|
||||
std::unordered_map<Pos::Local16_u, Chunk> Chunks;
|
||||
std::unordered_map<Pos::bvec16u, Chunk> Chunks;
|
||||
};
|
||||
|
||||
|
||||
struct World {
|
||||
std::vector<EntityId_c> Entitys;
|
||||
std::unordered_map<Pos::GlobalRegion::Key, Region> Regions;
|
||||
|
||||
};
|
||||
|
||||
struct DefVoxelInfo {
|
||||
|
||||
};
|
||||
|
||||
struct DefNodeInfo {
|
||||
|
||||
};
|
||||
|
||||
struct DefWorldInfo {
|
||||
|
||||
@@ -123,10 +121,16 @@ struct DefEntityInfo {
|
||||
|
||||
};
|
||||
|
||||
struct WorldInfo {
|
||||
struct DefFuncEntityInfo {
|
||||
|
||||
};
|
||||
|
||||
struct WorldInfo {
|
||||
std::vector<EntityId_t> Entitys;
|
||||
std::vector<FuncEntityId_t> FuncEntitys;
|
||||
std::unordered_map<Pos::GlobalRegion, Region> Regions;
|
||||
};
|
||||
|
||||
struct VoxelInfo {
|
||||
|
||||
};
|
||||
@@ -143,24 +147,33 @@ struct EntityInfo {
|
||||
|
||||
};
|
||||
|
||||
struct FuncEntityInfo {
|
||||
|
||||
};
|
||||
|
||||
struct DefItemInfo {
|
||||
|
||||
};
|
||||
|
||||
/* Интерфейс обработчика сессии с сервером */
|
||||
class IServerSession {
|
||||
public:
|
||||
struct {
|
||||
std::unordered_map<DefWorldId_c, DefWorldInfo> DefWorlds;
|
||||
std::unordered_map<DefVoxelId_c, VoxelInfo> DefVoxels;
|
||||
std::unordered_map<DefNodeId_c, NodeInfo> DefNodes;
|
||||
std::unordered_map<DefPortalId_c, DefPortalInfo> DefPortals;
|
||||
std::unordered_map<DefEntityId_c, DefEntityInfo> DefEntityes;
|
||||
|
||||
std::unordered_map<WorldId_c, WorldInfo> Worlds;
|
||||
std::unordered_map<PortalId_c, PortalInfo> Portals;
|
||||
std::unordered_map<EntityId_c, EntityInfo> Entityes;
|
||||
std::unordered_map<DefVoxelId_t, DefVoxelInfo> DefVoxel;
|
||||
std::unordered_map<DefNodeId_t, DefNodeInfo> DefNode;
|
||||
std::unordered_map<DefWorldId_t, DefWorldInfo> DefWorld;
|
||||
std::unordered_map<DefPortalId_t, DefPortalInfo> DefPortal;
|
||||
std::unordered_map<DefEntityId_t, DefEntityInfo> DefEntity;
|
||||
std::unordered_map<DefFuncEntityId_t, DefFuncEntityInfo> DefFuncEntity;
|
||||
std::unordered_map<DefItemId_t, DefItemInfo> DefItem;
|
||||
} Registry;
|
||||
|
||||
struct {
|
||||
std::unordered_map<WorldId_c, World> Worlds;
|
||||
} External;
|
||||
std::unordered_map<WorldId_t, WorldInfo> Worlds;
|
||||
std::unordered_map<PortalId_t, PortalInfo> Portals;
|
||||
std::unordered_map<EntityId_t, EntityInfo> Entityes;
|
||||
std::unordered_map<FuncEntityId_t, FuncEntityInfo> FuncEntityes;
|
||||
} Data;
|
||||
|
||||
virtual ~IServerSession();
|
||||
|
||||
|
||||
@@ -20,20 +20,20 @@ namespace LV::Client {
|
||||
ParsedPacket::~ParsedPacket() = default;
|
||||
|
||||
struct PP_Content_ChunkVoxels : public ParsedPacket {
|
||||
WorldId_c Id;
|
||||
WorldId_t Id;
|
||||
Pos::GlobalChunk Pos;
|
||||
std::vector<VoxelCube> Cubes;
|
||||
|
||||
PP_Content_ChunkVoxels(ToClient::L1 l1, uint8_t l2, WorldId_c id, Pos::GlobalChunk pos, std::vector<VoxelCube> &&cubes)
|
||||
PP_Content_ChunkVoxels(ToClient::L1 l1, uint8_t l2, WorldId_t id, Pos::GlobalChunk pos, std::vector<VoxelCube> &&cubes)
|
||||
: ParsedPacket(l1, l2), Id(id), Pos(pos), Cubes(std::move(cubes))
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Content_ChunkRemove : public ParsedPacket {
|
||||
WorldId_c Id;
|
||||
WorldId_t Id;
|
||||
Pos::GlobalChunk Pos;
|
||||
|
||||
PP_Content_ChunkRemove(ToClient::L1 l1, uint8_t l2, WorldId_c id, Pos::GlobalChunk pos)
|
||||
PP_Content_ChunkRemove(ToClient::L1 l1, uint8_t l2, WorldId_t id, Pos::GlobalChunk pos)
|
||||
: ParsedPacket(l1, l2), Id(id), Pos(pos)
|
||||
{}
|
||||
};
|
||||
@@ -252,7 +252,7 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||
Speed += glm::vec3(0, 1, 0)*float(Keys.SPACE)*mltpl;
|
||||
|
||||
{
|
||||
std::unordered_map<WorldId_c, std::tuple<std::unordered_set<Pos::GlobalChunk>, std::unordered_set<Pos::GlobalChunk>>> changeOrAddList_removeList;
|
||||
std::unordered_map<WorldId_t, std::tuple<std::unordered_set<Pos::GlobalChunk>, std::unordered_set<Pos::GlobalChunk>>> changeOrAddList_removeList;
|
||||
|
||||
// Пакеты
|
||||
ParsedPacket *pack;
|
||||
@@ -261,19 +261,19 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||
ToClient::L2Content l2 = ToClient::L2Content(pack->Level2);
|
||||
if(l2 == ToClient::L2Content::ChunkVoxels) {
|
||||
PP_Content_ChunkVoxels &p = *dynamic_cast<PP_Content_ChunkVoxels*>(pack);
|
||||
Pos::GlobalRegion rPos(p.Pos.X >> 4, p.Pos.Y >> 4, p.Pos.Z >> 4);
|
||||
Pos::Local16_u cPos(p.Pos.X & 0xf, p.Pos.Y & 0xf, p.Pos.Z & 0xf);
|
||||
Pos::GlobalRegion rPos = p.Pos >> 2;
|
||||
Pos::bvec4u cPos = p.Pos & 0x3;
|
||||
|
||||
External.Worlds[p.Id].Regions[rPos].Chunks[cPos].Voxels = std::move(p.Cubes);
|
||||
Data.Worlds[p.Id].Regions[rPos].Chunks[cPos].Voxels = std::move(p.Cubes);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<0>(pair).insert(p.Pos);
|
||||
} else if(l2 == ToClient::L2Content::RemoveChunk) {
|
||||
PP_Content_ChunkRemove &p = *dynamic_cast<PP_Content_ChunkRemove*>(pack);
|
||||
|
||||
Pos::GlobalRegion rPos(p.Pos.X >> 4, p.Pos.Y >> 4, p.Pos.Z >> 4);
|
||||
Pos::Local16_u cPos(p.Pos.X & 0xf, p.Pos.Y & 0xf, p.Pos.Z & 0xf);
|
||||
auto &obj = External.Worlds[p.Id].Regions[rPos].Chunks;
|
||||
Pos::GlobalRegion rPos = p.Pos >> 2;
|
||||
Pos::bvec4u cPos = p.Pos & 0x3;
|
||||
auto &obj = Data.Worlds[p.Id].Regions[rPos].Chunks;
|
||||
auto iter = obj.find(cPos);
|
||||
if(iter != obj.end())
|
||||
obj.erase(iter);
|
||||
@@ -443,22 +443,22 @@ coro<> ServerSession::rP_Definition(Net::AsyncSocket &sock) {
|
||||
|
||||
switch((ToClient::L2Definition) second) {
|
||||
case ToClient::L2Definition::World: {
|
||||
DefWorldId_c cdId = co_await sock.read<DefWorldId_c>();
|
||||
DefWorldId_t cdId = co_await sock.read<DefWorldId_t>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::FreeWorld: {
|
||||
DefWorldId_c cdId = co_await sock.read<DefWorldId_c>();
|
||||
DefWorldId_t cdId = co_await sock.read<DefWorldId_t>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::Voxel: {
|
||||
DefVoxelId_c cdId = co_await sock.read<DefVoxelId_c>();
|
||||
DefVoxelId_t cdId = co_await sock.read<DefVoxelId_t>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::FreeVoxel: {
|
||||
DefVoxelId_c cdId = co_await sock.read<DefVoxelId_c>();
|
||||
DefVoxelId_t cdId = co_await sock.read<DefVoxelId_t>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -509,9 +509,9 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
co_return;
|
||||
case ToClient::L2Content::ChunkVoxels:
|
||||
{
|
||||
WorldId_c wcId = co_await sock.read<WorldId_c>();
|
||||
Pos::GlobalChunk::Key posKey = co_await sock.read<Pos::GlobalChunk::Key>();
|
||||
Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey;
|
||||
WorldId_t wcId = co_await sock.read<WorldId_t>();
|
||||
Pos::GlobalChunk pos;
|
||||
pos.unpack(co_await sock.read<Pos::GlobalChunk::Pack>());
|
||||
|
||||
std::vector<VoxelCube> cubes(co_await sock.read<uint16_t>());
|
||||
uint16_t debugCubesCount = cubes.size();
|
||||
@@ -522,13 +522,13 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
|
||||
for(size_t iter = 0; iter < cubes.size(); iter++) {
|
||||
VoxelCube &cube = cubes[iter];
|
||||
cube.VoxelId = co_await sock.read<uint16_t>();
|
||||
cube.Left.X = co_await sock.read<uint8_t>();
|
||||
cube.Left.Y = co_await sock.read<uint8_t>();
|
||||
cube.Left.Z = co_await sock.read<uint8_t>();
|
||||
cube.Size.X = co_await sock.read<uint8_t>();
|
||||
cube.Size.Y = co_await sock.read<uint8_t>();
|
||||
cube.Size.Z = co_await sock.read<uint8_t>();
|
||||
cube.Data = co_await sock.read<DefVoxelId_t>();
|
||||
cube.Left.x = co_await sock.read<uint8_t>();
|
||||
cube.Left.y = co_await sock.read<uint8_t>();
|
||||
cube.Left.z = co_await sock.read<uint8_t>();
|
||||
cube.Size.x = co_await sock.read<uint8_t>();
|
||||
cube.Size.y = co_await sock.read<uint8_t>();
|
||||
cube.Size.z = co_await sock.read<uint8_t>();
|
||||
}
|
||||
|
||||
PP_Content_ChunkVoxels *packet = new PP_Content_ChunkVoxels(
|
||||
@@ -551,9 +551,9 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
|
||||
co_return;
|
||||
case ToClient::L2Content::RemoveChunk: {
|
||||
WorldId_c wcId = co_await sock.read<uint8_t>();
|
||||
Pos::GlobalChunk::Key posKey = co_await sock.read<Pos::GlobalChunk::Key>();
|
||||
Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey;
|
||||
WorldId_t wcId = co_await sock.read<uint8_t>();
|
||||
Pos::GlobalChunk pos;
|
||||
pos.unpack(co_await sock.read<Pos::GlobalChunk::Pack>());
|
||||
|
||||
PP_Content_ChunkRemove *packet = new PP_Content_ChunkRemove(
|
||||
ToClient::L1::Content,
|
||||
|
||||
@@ -232,16 +232,16 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
||||
{
|
||||
std::vector<VoxelCube> cubes;
|
||||
|
||||
cubes.emplace_back(0, Pos::Local256_u{0, 0, 0}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(1, Pos::Local256_u{255, 0, 0}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(1, Pos::Local256_u{0, 255, 0}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(1, Pos::Local256_u{0, 0, 255}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(2, Pos::Local256_u{255, 255, 0}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(2, Pos::Local256_u{0, 255, 255}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(2, Pos::Local256_u{255, 0, 255}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.emplace_back(3, Pos::Local256_u{255, 255, 255}, Pos::Local256_u{0, 0, 0});
|
||||
cubes.push_back({0, 0, Pos::bvec256u{0, 0, 0}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({1, 0, Pos::bvec256u{255, 0, 0}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({1, 0, Pos::bvec256u{0, 255, 0}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({1, 0, Pos::bvec256u{0, 0, 255}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({2, 0, Pos::bvec256u{255, 255, 0}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({2, 0, Pos::bvec256u{0, 255, 255}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({2, 0, Pos::bvec256u{255, 0, 255}, Pos::bvec256u{0, 0, 0}});
|
||||
cubes.push_back({3, 0, Pos::bvec256u{255, 255, 255}, Pos::bvec256u{0, 0, 0}});
|
||||
|
||||
cubes.emplace_back(4, Pos::Local256_u{64, 64, 64}, Pos::Local256_u{127, 127, 127});
|
||||
cubes.push_back({4, 0, Pos::bvec256u{64, 64, 64}, Pos::bvec256u{127, 127, 127}});
|
||||
|
||||
std::vector<VoxelVertexPoint> vertexs = generateMeshForVoxelChunks(cubes);
|
||||
|
||||
@@ -595,50 +595,30 @@ void VulkanRenderSession::init(Vulkan *instance) {
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefTexture(TextureId_c id, std::vector<std::byte> &&info) {
|
||||
void VulkanRenderSession::onBinaryResourceAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, BinaryResource>>) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefTextureLost(const std::vector<TextureId_c> &&lost) {
|
||||
void VulkanRenderSession::onBinaryResourceLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefModel(ModelId_c id, std::vector<std::byte> &&info) {
|
||||
void VulkanRenderSession::onContentDefinesAdd(std::unordered_map<EnumDefContent, std::unordered_map<ResourceId_t, std::u8string>>) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefModelLost(const std::vector<ModelId_c> &&lost) {
|
||||
void VulkanRenderSession::onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefNodeUpdates(const std::vector<DefNodeId_c> &updates) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) {
|
||||
auto &table = External.ChunkVoxelMesh[worldId];
|
||||
void VulkanRenderSession::onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) {
|
||||
auto &table = External.ChunkVoxelMesh[worldId];
|
||||
|
||||
for(Pos::GlobalChunk pos : changeOrAddList) {
|
||||
Pos::GlobalRegion rPos(pos.X >> 4, pos.Y >> 4, pos.Z >> 4);
|
||||
Pos::Local16_u cPos(pos.X & 0xf, pos.Y & 0xf, pos.Z & 0xf);
|
||||
Pos::GlobalRegion rPos = pos >> 4;
|
||||
Pos::bvec16u cPos = pos & 0xf;
|
||||
|
||||
const auto &voxels = ServerSession->External.Worlds[worldId].Regions[rPos].Chunks[cPos].Voxels;
|
||||
const auto &voxels = ServerSession->Data.Worlds[worldId].Regions[rPos].Chunks[cPos].Voxels;
|
||||
|
||||
if(voxels.empty()) {
|
||||
auto iter = table.find(pos);
|
||||
@@ -669,7 +649,7 @@ void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::unordered
|
||||
External.ChunkVoxelMesh.erase( External.ChunkVoxelMesh.find(worldId));
|
||||
}
|
||||
|
||||
void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) {
|
||||
void VulkanRenderSession::setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) {
|
||||
WorldId = worldId;
|
||||
Pos = pos;
|
||||
Quat = quat;
|
||||
@@ -738,7 +718,7 @@ void VulkanRenderSession::drawWorld(GlobalTime gTime, float dTime, VkCommandBuff
|
||||
glm::mat4 orig = PCO.Model;
|
||||
|
||||
for(auto &pair : iterWorld->second) {
|
||||
glm::vec3 cpos(pair.first.X, pair.first.Y, pair.first.Z);
|
||||
glm::vec3 cpos(pair.first.x, pair.first.y, pair.first.z);
|
||||
PCO.Model = glm::translate(orig, cpos*16.f);
|
||||
vkBuffer = *pair.second;
|
||||
|
||||
@@ -759,78 +739,78 @@ std::vector<VoxelVertexPoint> VulkanRenderSession::generateMeshForVoxelChunks(co
|
||||
|
||||
for(const VoxelCube &cube : cubes) {
|
||||
out.emplace_back(
|
||||
cube.Left.X,
|
||||
cube.Left.Y,
|
||||
cube.Left.Z,
|
||||
cube.Left.x,
|
||||
cube.Left.y,
|
||||
cube.Left.z,
|
||||
0,
|
||||
0, 0,
|
||||
cube.Size.X,
|
||||
cube.Size.Z,
|
||||
cube.Size.x,
|
||||
cube.Size.z,
|
||||
cube.VoxelId,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
|
||||
out.emplace_back(
|
||||
cube.Left.X,
|
||||
cube.Left.Y,
|
||||
cube.Left.Z,
|
||||
cube.Left.x,
|
||||
cube.Left.y,
|
||||
cube.Left.z,
|
||||
1,
|
||||
0, 0,
|
||||
cube.Size.X,
|
||||
cube.Size.Y,
|
||||
cube.Size.x,
|
||||
cube.Size.y,
|
||||
cube.VoxelId,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
|
||||
out.emplace_back(
|
||||
cube.Left.X,
|
||||
cube.Left.Y,
|
||||
cube.Left.Z,
|
||||
cube.Left.x,
|
||||
cube.Left.y,
|
||||
cube.Left.z,
|
||||
2,
|
||||
0, 0,
|
||||
cube.Size.Z,
|
||||
cube.Size.Y,
|
||||
cube.Size.z,
|
||||
cube.Size.y,
|
||||
cube.VoxelId,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
|
||||
out.emplace_back(
|
||||
cube.Left.X,
|
||||
cube.Left.Y+cube.Size.Y+1,
|
||||
cube.Left.Z,
|
||||
cube.Left.x,
|
||||
cube.Left.y+cube.Size.y+1,
|
||||
cube.Left.z,
|
||||
3,
|
||||
0, 0,
|
||||
cube.Size.X,
|
||||
cube.Size.Z,
|
||||
cube.Size.x,
|
||||
cube.Size.z,
|
||||
cube.VoxelId,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
|
||||
out.emplace_back(
|
||||
cube.Left.X,
|
||||
cube.Left.Y,
|
||||
cube.Left.Z+cube.Size.Z+1,
|
||||
cube.Left.x,
|
||||
cube.Left.y,
|
||||
cube.Left.z+cube.Size.z+1,
|
||||
4,
|
||||
0, 0,
|
||||
cube.Size.X,
|
||||
cube.Size.Y,
|
||||
cube.Size.x,
|
||||
cube.Size.y,
|
||||
cube.VoxelId,
|
||||
0, 0,
|
||||
0
|
||||
);
|
||||
|
||||
out.emplace_back(
|
||||
cube.Left.X+cube.Size.X+1,
|
||||
cube.Left.Y,
|
||||
cube.Left.Z,
|
||||
cube.Left.x+cube.Size.x+1,
|
||||
cube.Left.y,
|
||||
cube.Left.z,
|
||||
5,
|
||||
0, 0,
|
||||
cube.Size.Z,
|
||||
cube.Size.Y,
|
||||
cube.Size.z,
|
||||
cube.Size.y,
|
||||
cube.VoxelId,
|
||||
0, 0,
|
||||
0
|
||||
|
||||
@@ -78,7 +78,7 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
IServerSession *ServerSession = nullptr;
|
||||
|
||||
// Положение камеры
|
||||
WorldId_c WorldId;
|
||||
WorldId_t WorldId;
|
||||
Pos::Object Pos;
|
||||
glm::quat Quat;
|
||||
|
||||
@@ -130,10 +130,10 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
NodeStaticTransparentPipeline = VK_NULL_HANDLE;
|
||||
|
||||
|
||||
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
||||
std::map<BinTextureId_t, uint16_t> ServerToAtlas;
|
||||
|
||||
struct {
|
||||
std::unordered_map<WorldId_c, std::unordered_map<Pos::GlobalChunk, std::unique_ptr<Buffer>>> ChunkVoxelMesh;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::unique_ptr<Buffer>>> ChunkVoxelMesh;
|
||||
} External;
|
||||
|
||||
virtual void free(Vulkan *instance) override;
|
||||
@@ -151,19 +151,12 @@ public:
|
||||
assert(serverSession);
|
||||
}
|
||||
|
||||
virtual void onDefTexture(TextureId_c id, std::vector<std::byte> &&info) override;
|
||||
virtual void onDefTextureLost(const std::vector<TextureId_c> &&lost) override;
|
||||
virtual void onDefModel(ModelId_c id, std::vector<std::byte> &&info) override;
|
||||
virtual void onDefModelLost(const std::vector<ModelId_c> &&lost) override;
|
||||
|
||||
virtual void onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) override;
|
||||
virtual void onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) override;
|
||||
virtual void onDefNodeUpdates(const std::vector<DefNodeId_c> &updates) override;
|
||||
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) override;
|
||||
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) override;
|
||||
|
||||
virtual void onChunksChange(WorldId_c worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) override;
|
||||
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) override;
|
||||
virtual void onBinaryResourceAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, BinaryResource>>) override;
|
||||
virtual void onBinaryResourceLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) override;
|
||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::unordered_map<ResourceId_t, std::u8string>>) override;
|
||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) override;
|
||||
virtual void onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalChunk> &remove) override;
|
||||
virtual void setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) override;
|
||||
|
||||
glm::mat4 calcViewMatrix(glm::quat quat, glm::vec3 camOffset = glm::vec3(0)) {
|
||||
return glm::translate(glm::mat4(quat), camOffset);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <glm/ext.hpp>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace LV {
|
||||
@@ -42,10 +41,13 @@ public:
|
||||
BitVec3() = default;
|
||||
BitVec3(T value)
|
||||
: x(value), y(value), z(value)
|
||||
{
|
||||
}
|
||||
{}
|
||||
BitVec3(const T x, const T y, const T z)
|
||||
: x(x), y(y), z(z)
|
||||
{}
|
||||
template<typename vT, glm::qualifier vQ>
|
||||
BitVec3(const glm::vec<3, vT, vQ> vec)
|
||||
: x(vec.x), y(vec.y), z(vec.z)
|
||||
{}
|
||||
BitVec3(const BitVec3&) = default;
|
||||
BitVec3(BitVec3&&) = default;
|
||||
@@ -94,7 +96,7 @@ public:
|
||||
using U = std::make_unsigned_t<T>;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++) {
|
||||
get(iter) = U((pack >> BitsPerComponent*iter) & ((Pack(1) << BitsPerComponent)-1));
|
||||
set(iter, U((pack >> BitsPerComponent*iter) & ((Pack(1) << BitsPerComponent)-1)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +104,7 @@ public:
|
||||
|
||||
template<typename T2, size_t BitsPerComponent2>
|
||||
operator BitVec3<T2, BitsPerComponent2>() const {
|
||||
BitVec3<T, BitsPerComponent2> out;
|
||||
BitVec3<T2, BitsPerComponent2> out;
|
||||
for(size_t iter = 0; iter < N; iter++) {
|
||||
out.set(iter, T2(std::make_unsigned_t<T2>(std::make_unsigned_t<T>(get(iter)))));
|
||||
}
|
||||
@@ -110,18 +112,24 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template<typename vT, glm::qualifier vQ>
|
||||
operator glm::vec<3, vT, vQ>() const {
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
BitVec3 operator+(const BitVec3 &other) const {
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) + other[iter];
|
||||
out.set(iter, get(iter) + other[iter]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator+=(const BitVec3 &other) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) += other[iter];
|
||||
set(iter, get(iter) + other[iter]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -130,14 +138,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) + value;
|
||||
out.set(iter, get(iter) + value);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator+=(const T value) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) += value;
|
||||
set(iter, get(iter) + value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -146,14 +154,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) - other[iter];
|
||||
out.set(iter, get(iter) - other[iter]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator-=(const BitVec3 &other) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) -= other[iter];
|
||||
set(iter, get(iter) - other[iter]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -162,14 +170,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) - value;
|
||||
out.set(iter, get(iter) - value);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator-=(const T value) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) -= value;
|
||||
set(iter, get(iter) - value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -178,14 +186,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) * other[iter];
|
||||
out.set(iter, get(iter) * other[iter]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator*=(const BitVec3 &other) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) *= other[iter];
|
||||
set(iter, get(iter) * other[iter]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -194,14 +202,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) * value;
|
||||
out.set(iter, get(iter) * value);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator*=(const T value) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) *= value;
|
||||
set(iter, get(iter) * value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -210,14 +218,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) / other[iter];
|
||||
out.set(iter, get(iter) / other[iter]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator/=(const BitVec3 &other) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) /= other[iter];
|
||||
set(iter, get(iter) / other[iter]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -226,14 +234,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) / value;
|
||||
out.set(iter, get(iter) / value);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator/=(const T value) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) /= value;
|
||||
set(iter, get(iter) / value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -249,7 +257,7 @@ public:
|
||||
|
||||
BitVec3& operator>>=(const auto offset) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) >>= offset;
|
||||
set(iter, get(iter) >> offset);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -258,14 +266,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) << offset;
|
||||
out.set(iter, get(iter) << offset);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator<<=(const auto offset) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) <<= offset;
|
||||
set(iter, get(iter) << offset);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -274,14 +282,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) | other[iter];
|
||||
out.set(iter, get(iter) | other[iter]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator|=(const BitVec3 other) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) |= other[iter];
|
||||
set(iter, get(iter) | other[iter]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -290,14 +298,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) | value;
|
||||
out.set(iter, get(iter) | value);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator|=(const T value) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) |= value;
|
||||
set(iter, get(iter) | value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -306,14 +314,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) & other[iter];
|
||||
out.set(iter, get(iter) & other[iter]);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator&=(const BitVec3 other) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) &= other[iter];
|
||||
set(iter, get(iter) & other[iter]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -322,14 +330,14 @@ public:
|
||||
BitVec3 out;
|
||||
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
out[iter] = get(iter) & value;
|
||||
out.set(iter, get(iter) & value);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
BitVec3& operator&=(const T value) {
|
||||
for(size_t iter = 0; iter < N; iter++)
|
||||
get(iter) &= value;
|
||||
set(iter, get(iter) & value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -343,7 +351,9 @@ using bvec16i = BitVec3<int8_t, 4>;
|
||||
using bvec16u = BitVec3<uint8_t, 4>;
|
||||
using bvec256i = BitVec3<int8_t, 8>;
|
||||
using bvec256u = BitVec3<uint8_t, 8>;
|
||||
using bvec4096i = BitVec3<int8_t, 12>;
|
||||
using bvec1024i = BitVec3<int16_t, 10>;
|
||||
using bvec1024u = BitVec3<uint16_t, 10>;
|
||||
using bvec4096i = BitVec3<int16_t, 12>;
|
||||
using bvec4096u = BitVec3<uint16_t, 12>;
|
||||
|
||||
using GlobalVoxel = BitVec3<int32_t, 24>;
|
||||
@@ -385,25 +395,23 @@ using BinSoundId_t = ResourceId_t;
|
||||
using BinFontId_t = ResourceId_t;
|
||||
|
||||
// Шаблоны использования бинарных ресурсов
|
||||
using TextureId_t = ResourceId_t;
|
||||
using AnimationId_t = ResourceId_t;
|
||||
using ModelId_t = ResourceId_t;
|
||||
using SoundId_t = ResourceId_t;
|
||||
using FontId_t = ResourceId_t;
|
||||
// using DefTextureId_t = ResourceId_t;
|
||||
// using DefModelId_t = ResourceId_t;
|
||||
// using DefSoundId_t = ResourceId_t;
|
||||
// using DefFontId_t = ResourceId_t;
|
||||
|
||||
enum class EnumDefContent {
|
||||
Voxel, Node, Generator, World, Portal, Entity, FuncEntitry
|
||||
};
|
||||
|
||||
// Игровые определения
|
||||
using DefVoxelId_t = ResourceId_t;
|
||||
using DefNodeId_t = ResourceId_t;
|
||||
using DefGeneratorId_t = ResourceId_t;
|
||||
using DefWorldId_t = ResourceId_t;
|
||||
using DefPortalId_t = ResourceId_t;
|
||||
using DefEntityId_t = ResourceId_t;
|
||||
using DefVoxelId_t = ResourceId_t;
|
||||
using DefNodeId_t = ResourceId_t;
|
||||
using DefWorldId_t = ResourceId_t;
|
||||
using DefPortalId_t = ResourceId_t;
|
||||
using DefEntityId_t = ResourceId_t;
|
||||
using DefFuncEntityId_t = ResourceId_t;
|
||||
|
||||
using DefItemId_t = ResourceId_t;
|
||||
|
||||
// Контент, основанный на игровых определениях
|
||||
using WorldId_t = ResourceId_t;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Common/Abstract.hpp"
|
||||
#include <iostream>
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace LV {
|
||||
|
||||
|
||||
@@ -138,10 +138,14 @@ enum struct L2System : uint8_t {
|
||||
enum struct L2Resource : uint8_t {
|
||||
Texture,
|
||||
FreeTexture,
|
||||
Animation,
|
||||
FreeAnimation,
|
||||
Sound,
|
||||
FreeSound,
|
||||
Model,
|
||||
FreeModel,
|
||||
Font,
|
||||
FreeFont,
|
||||
InitResSend = 253,
|
||||
ChunkSend,
|
||||
SendCanceled
|
||||
@@ -157,7 +161,11 @@ enum struct L2Definition : uint8_t {
|
||||
Portal,
|
||||
FreePortal,
|
||||
Entity,
|
||||
FreeEntity
|
||||
FreeEntity,
|
||||
FuncEntity,
|
||||
FreeFuncEntity,
|
||||
Item,
|
||||
FreeItem
|
||||
};
|
||||
|
||||
enum struct L2Content : uint8_t {
|
||||
|
||||
@@ -4,19 +4,31 @@
|
||||
#include <Common/Abstract.hpp>
|
||||
#include <Common/Collide.hpp>
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
struct TexturePipeline {
|
||||
std::vector<BinTextureId_t> BinTextures;
|
||||
std::u8string Pipeline;
|
||||
};
|
||||
|
||||
|
||||
// В одном регионе может быть максимум 2^16 сущностей. Клиенту адресуются сущности в формате <мир>+<позиция региона>+<uint16_t>
|
||||
// И если сущность перешла из одного региона в другой, идентификатор сущности на стороне клиента сохраняется
|
||||
using EntityId_t = uint16_t;
|
||||
using FuncEntityId_t = uint16_t;
|
||||
using ClientEntityId_t = std::tuple<WorldId_t, Pos::GlobalRegion, EntityId_t>;
|
||||
using RegionEntityId_t = uint16_t;
|
||||
using ClientEntityId_t = RegionEntityId_t;
|
||||
using ServerEntityId_t = std::tuple<WorldId_t, Pos::GlobalRegion, RegionEntityId_t>;
|
||||
using RegionFuncEntityId_t = uint16_t;
|
||||
using ClientFuncEntityId_t = RegionFuncEntityId_t;
|
||||
using ServerFuncEntityId_t = std::tuple<WorldId_t, Pos::GlobalRegion, RegionFuncEntityId_t>;
|
||||
|
||||
using MediaStreamId_t = uint16_t;
|
||||
using ContentBridgeId_t = ResourceId_t;
|
||||
using PlayerId_t = ResourceId_t;
|
||||
using DefGeneratorId_t = ResourceId_t;
|
||||
|
||||
|
||||
/*
|
||||
@@ -44,25 +56,66 @@ struct ServerTime {
|
||||
};
|
||||
|
||||
struct VoxelCube {
|
||||
DefVoxelId_t VoxelId;
|
||||
Pos::bvec256u Left, Right;
|
||||
union {
|
||||
struct {
|
||||
DefVoxelId_t VoxelId : 24, Meta : 8;
|
||||
};
|
||||
|
||||
auto operator<=>(const VoxelCube&) const = default;
|
||||
DefVoxelId_t Data = 0;
|
||||
};
|
||||
|
||||
Pos::bvec256u Left, Right; // TODO: заменить на позицию и размер
|
||||
|
||||
auto operator<=>(const VoxelCube& other) const {
|
||||
if (auto cmp = Left <=> other.Left; cmp != 0)
|
||||
return cmp;
|
||||
|
||||
if (auto cmp = Right <=> other.Right; cmp != 0)
|
||||
return cmp;
|
||||
|
||||
return Data <=> other.Data;
|
||||
}
|
||||
|
||||
bool operator==(const VoxelCube& other) const {
|
||||
return Left == other.Left && Right == other.Right && Data == other.Data;
|
||||
}
|
||||
};
|
||||
|
||||
struct VoxelCube_Region {
|
||||
Pos::bvec4096u Left, Right;
|
||||
DefVoxelId_t VoxelId;
|
||||
union {
|
||||
struct {
|
||||
DefVoxelId_t VoxelId : 24, Meta : 8;
|
||||
};
|
||||
|
||||
auto operator<=>(const VoxelCube_Region&) const = default;
|
||||
DefVoxelId_t Data = 0;
|
||||
};
|
||||
|
||||
Pos::bvec1024u Left, Right; // TODO: заменить на позицию и размер
|
||||
|
||||
auto operator<=>(const VoxelCube_Region& other) const {
|
||||
if (auto cmp = Left <=> other.Left; cmp != 0)
|
||||
return cmp;
|
||||
|
||||
if (auto cmp = Right <=> other.Right; cmp != 0)
|
||||
return cmp;
|
||||
|
||||
return Data <=> other.Data;
|
||||
}
|
||||
|
||||
bool operator==(const VoxelCube_Region& other) const {
|
||||
return Left == other.Left && Right == other.Right && Data == other.Data;
|
||||
}
|
||||
};
|
||||
|
||||
struct Node {
|
||||
DefNodeId_t NodeId;
|
||||
uint8_t Rotate : 6;
|
||||
union {
|
||||
struct {
|
||||
DefNodeId_t NodeId : 24, Meta : 8;
|
||||
};
|
||||
DefNodeId_t Data;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct AABB {
|
||||
Pos::Object VecMin, VecMax;
|
||||
|
||||
@@ -96,26 +149,26 @@ struct LocalAABB {
|
||||
|
||||
struct CollisionAABB : public AABB {
|
||||
enum struct EnumType {
|
||||
Voxel, Node, Entity, Barrier, Portal, Another
|
||||
Voxel, Node, Entity, FuncEntity, Barrier, Portal, Another
|
||||
} Type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
EntityId_t Index;
|
||||
RegionEntityId_t Index;
|
||||
} Entity;
|
||||
|
||||
struct {
|
||||
FuncEntityId_t Index;
|
||||
RegionFuncEntityId_t Index;
|
||||
} FuncEntity;
|
||||
|
||||
struct {
|
||||
Pos::bvec4u Chunk;
|
||||
Pos::bvec16u Pos;
|
||||
} Node;
|
||||
|
||||
struct {
|
||||
Pos::bvec16u Chunk;
|
||||
Pos::bvec4u Chunk;
|
||||
uint32_t Index;
|
||||
DefVoxelId_t Id;
|
||||
} Voxel;
|
||||
|
||||
struct {
|
||||
@@ -171,6 +224,15 @@ public:
|
||||
DefEntityId_t getDefId() const { return DefId; }
|
||||
};
|
||||
|
||||
class FuncEntity {
|
||||
DefFuncEntityId_t DefId;
|
||||
|
||||
public:
|
||||
FuncEntity(DefFuncEntityId_t defId);
|
||||
|
||||
DefFuncEntityId_t getDefId() const { return DefId; }
|
||||
};
|
||||
|
||||
|
||||
template<typename Vec>
|
||||
struct VoxelCuboidsFuncs {
|
||||
@@ -292,7 +354,7 @@ struct VoxelCuboidsFuncs {
|
||||
}
|
||||
};
|
||||
|
||||
inline void convertRegionVoxelsToChunks(const std::vector<VoxelCube_Region>& regions, std::vector<VoxelCube> *chunks) {
|
||||
inline void convertRegionVoxelsToChunks(const std::vector<VoxelCube_Region>& regions, std::unordered_map<Pos::bvec4u, std::vector<VoxelCube>> &chunks) {
|
||||
for (const auto& region : regions) {
|
||||
int minX = region.Left.x >> 8;
|
||||
int minY = region.Left.y >> 8;
|
||||
@@ -315,30 +377,24 @@ inline void convertRegionVoxelsToChunks(const std::vector<VoxelCube_Region>& reg
|
||||
static_cast<uint8_t>(std::min<uint16_t>(((z+1) << 8)-1, region.Right.z) - (z << 8))
|
||||
};
|
||||
|
||||
int chunkIndex = z * 16 * 16 + y * 16 + x;
|
||||
chunks[chunkIndex].emplace_back(region.VoxelId, left, right);
|
||||
chunks[Pos::bvec4u(x, y, z)].push_back({
|
||||
region.VoxelId, region.Meta, left, right
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void convertChunkVoxelsToRegion(const std::vector<VoxelCube> *chunks, std::vector<VoxelCube_Region> ®ions) {
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
for (int y = 0; y < 16; ++y) {
|
||||
for (int z = 0; z < 16; ++z) {
|
||||
int chunkIndex = z * 16 * 16 + y * 16 + x;
|
||||
|
||||
Pos::bvec4096u left(x << 8, y << 8, z << 8);
|
||||
|
||||
for (const auto& cube : chunks[chunkIndex]) {
|
||||
regions.emplace_back(
|
||||
Pos::bvec4096u(left.x+cube.Left.x, left.y+cube.Left.y, left.z+cube.Left.z),
|
||||
Pos::bvec4096u(left.x+cube.Right.x, left.y+cube.Right.y, left.z+cube.Right.z),
|
||||
cube.VoxelId
|
||||
);
|
||||
}
|
||||
}
|
||||
inline void convertChunkVoxelsToRegion(const std::unordered_map<Pos::bvec4u, std::vector<VoxelCube>> &chunks, std::vector<VoxelCube_Region> ®ions) {
|
||||
for(const auto& [pos, voxels] : chunks) {
|
||||
Pos::bvec1024u left = pos << 8;
|
||||
for (const auto& cube : voxels) {
|
||||
regions.push_back({
|
||||
cube.VoxelId, cube.Meta,
|
||||
Pos::bvec1024u(left.x+cube.Left.x, left.y+cube.Left.y, left.z+cube.Left.z),
|
||||
Pos::bvec1024u(left.x+cube.Right.x, left.y+cube.Right.y, left.z+cube.Right.z)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ContentEventController::ContentEventController(std::unique_ptr<RemoteClient> &&r
|
||||
}
|
||||
|
||||
uint16_t ContentEventController::getViewRangeActive() const {
|
||||
return 16;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16_t ContentEventController::getViewRangeBackground() const {
|
||||
@@ -34,9 +34,9 @@ void ContentEventController::checkContentViewChanges() {
|
||||
for(const auto &[regionPos, chunks] : regions) {
|
||||
size_t bitPos = chunks._Find_first();
|
||||
while(bitPos != chunks.size()) {
|
||||
Pos::Local16_u chunkPosLocal;
|
||||
chunkPosLocal = bitPos;
|
||||
Pos::GlobalChunk chunkPos = regionPos.toChunk(chunkPosLocal);
|
||||
Pos::bvec4u chunkPosLocal;
|
||||
chunkPosLocal.unpack(bitPos);
|
||||
Pos::GlobalChunk chunkPos = (Pos::GlobalChunk(regionPos) << 2) + chunkPosLocal;
|
||||
Remote->prepareChunkRemove(worldId, chunkPos);
|
||||
bitPos = chunks._Find_next(bitPos);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ void ContentEventController::onWorldUpdate(WorldId_t worldId, World *worldObj)
|
||||
}
|
||||
|
||||
void ContentEventController::onChunksUpdate_Voxels(WorldId_t worldId, Pos::GlobalRegion regionPos,
|
||||
const std::unordered_map<Pos::Local16_u, const std::vector<VoxelCube>*> &chunks)
|
||||
const std::unordered_map<Pos::bvec4u, const std::vector<VoxelCube>*>& chunks)
|
||||
{
|
||||
auto pWorld = ContentViewState.find(worldId);
|
||||
if(pWorld == ContentViewState.end())
|
||||
@@ -69,19 +69,19 @@ void ContentEventController::onChunksUpdate_Voxels(WorldId_t worldId, Pos::Globa
|
||||
if(pRegion == pWorld->second.end())
|
||||
return;
|
||||
|
||||
const std::bitset<4096> &chunkBitset = pRegion->second;
|
||||
const std::bitset<64> &chunkBitset = pRegion->second;
|
||||
|
||||
for(auto pChunk : chunks) {
|
||||
if(!chunkBitset.test(pChunk.first))
|
||||
if(!chunkBitset.test(pChunk.first.pack()))
|
||||
continue;
|
||||
|
||||
Pos::GlobalChunk chunkPos = regionPos.toChunk(pChunk.first);
|
||||
Remote->prepareChunkUpdate_Voxels(worldId, chunkPos, *pChunk.second);
|
||||
Pos::GlobalChunk chunkPos = (Pos::GlobalChunk(regionPos) << 2) + pChunk.first;
|
||||
Remote->prepareChunkUpdate_Voxels(worldId, chunkPos, pChunk.second);
|
||||
}
|
||||
}
|
||||
|
||||
void ContentEventController::onChunksUpdate_Nodes(WorldId_t worldId, Pos::GlobalRegion regionPos,
|
||||
const std::unordered_map<Pos::Local16_u, const std::unordered_map<Pos::Local16_u, Node>*> &chunks)
|
||||
const std::unordered_map<Pos::bvec4u, const Node*> &chunks)
|
||||
{
|
||||
auto pWorld = ContentViewState.find(worldId);
|
||||
if(pWorld == ContentViewState.end())
|
||||
@@ -91,41 +91,41 @@ void ContentEventController::onChunksUpdate_Nodes(WorldId_t worldId, Pos::Global
|
||||
if(pRegion == pWorld->second.end())
|
||||
return;
|
||||
|
||||
const std::bitset<4096> &chunkBitset = pRegion->second;
|
||||
const std::bitset<64> &chunkBitset = pRegion->second;
|
||||
|
||||
for(auto pChunk : chunks) {
|
||||
if(!chunkBitset.test(pChunk.first))
|
||||
if(!chunkBitset.test(pChunk.first.pack()))
|
||||
continue;
|
||||
|
||||
Pos::GlobalChunk chunkPos = regionPos.toChunk(pChunk.first);
|
||||
Remote->prepareChunkUpdate_Nodes(worldId, chunkPos, *pChunk.second);
|
||||
Pos::GlobalChunk chunkPos = (Pos::GlobalChunk(regionPos) << 2) + Pos::GlobalChunk(pChunk.first);
|
||||
Remote->prepareChunkUpdate_Nodes(worldId, chunkPos, pChunk.second);
|
||||
}
|
||||
}
|
||||
|
||||
void ContentEventController::onChunksUpdate_LightPrism(WorldId_t worldId, Pos::GlobalRegion regionPos,
|
||||
const std::unordered_map<Pos::Local16_u, const LightPrism*> &chunks)
|
||||
{
|
||||
auto pWorld = ContentViewState.find(worldId);
|
||||
if(pWorld == ContentViewState.end())
|
||||
return;
|
||||
// void ContentEventController::onChunksUpdate_LightPrism(WorldId_t worldId, Pos::GlobalRegion regionPos,
|
||||
// const std::unordered_map<Pos::bvec4u, const LightPrism*> &chunks)
|
||||
// {
|
||||
// auto pWorld = ContentViewState.find(worldId);
|
||||
// if(pWorld == ContentViewState.end())
|
||||
// return;
|
||||
|
||||
auto pRegion = pWorld->second.find(regionPos);
|
||||
if(pRegion == pWorld->second.end())
|
||||
return;
|
||||
// auto pRegion = pWorld->second.find(regionPos);
|
||||
// if(pRegion == pWorld->second.end())
|
||||
// return;
|
||||
|
||||
const std::bitset<4096> &chunkBitset = pRegion->second;
|
||||
// const std::bitset<4096> &chunkBitset = pRegion->second;
|
||||
|
||||
for(auto pChunk : chunks) {
|
||||
if(!chunkBitset.test(pChunk.first))
|
||||
continue;
|
||||
// for(auto pChunk : chunks) {
|
||||
// if(!chunkBitset.test(pChunk.first))
|
||||
// continue;
|
||||
|
||||
Pos::GlobalChunk chunkPos = regionPos.toChunk(pChunk.first);
|
||||
Remote->prepareChunkUpdate_LightPrism(worldId, chunkPos, pChunk.second);
|
||||
}
|
||||
}
|
||||
// Pos::GlobalChunk chunkPos = regionPos.toChunk(pChunk.first);
|
||||
// Remote->prepareChunkUpdate_LightPrism(worldId, chunkPos, pChunk.second);
|
||||
// }
|
||||
// }
|
||||
|
||||
void ContentEventController::onEntityEnterLost(WorldId_t worldId, Pos::GlobalRegion regionPos,
|
||||
const std::unordered_set<LocalEntityId_t> &enter, const std::unordered_set<LocalEntityId_t> &lost)
|
||||
const std::unordered_set<RegionEntityId_t> &enter, const std::unordered_set<RegionEntityId_t> &lost)
|
||||
{
|
||||
auto pWorld = Subscribed.Entities.find(worldId);
|
||||
if(pWorld == Subscribed.Entities.end()) {
|
||||
@@ -141,9 +141,9 @@ void ContentEventController::onEntityEnterLost(WorldId_t worldId, Pos::GlobalReg
|
||||
pRegion = pWorld->second.find(regionPos);
|
||||
}
|
||||
|
||||
std::unordered_set<LocalEntityId_t> &entityesId = pRegion->second;
|
||||
std::unordered_set<RegionEntityId_t> &entityesId = pRegion->second;
|
||||
|
||||
for(LocalEntityId_t eId : lost) {
|
||||
for(RegionEntityId_t eId : lost) {
|
||||
entityesId.erase(eId);
|
||||
}
|
||||
|
||||
@@ -157,13 +157,13 @@ void ContentEventController::onEntityEnterLost(WorldId_t worldId, Pos::GlobalReg
|
||||
}
|
||||
|
||||
// Сообщить Remote
|
||||
for(LocalEntityId_t eId : lost) {
|
||||
for(RegionEntityId_t eId : lost) {
|
||||
Remote->prepareEntityRemove({worldId, regionPos, eId});
|
||||
}
|
||||
}
|
||||
|
||||
void ContentEventController::onEntitySwap(WorldId_t lastWorldId, Pos::GlobalRegion lastRegionPos,
|
||||
LocalEntityId_t lastId, WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, LocalEntityId_t newId)
|
||||
RegionEntityId_t lastId, WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, RegionEntityId_t newId)
|
||||
{
|
||||
// Проверим отслеживается ли эта сущность нами
|
||||
auto lpWorld = Subscribed.Entities.find(lastWorldId);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@@ -35,22 +34,22 @@ struct ContentViewCircle {
|
||||
int32_t Range;
|
||||
|
||||
inline int32_t sqrDistance(Pos::GlobalRegion regionPos) const {
|
||||
glm::i32vec3 vec = {Pos.x-((regionPos.X << 4) | 0b1000), Pos.y-((regionPos.Y << 4) | 0b1000), Pos.z-((regionPos.Z << 4) | 0b1000)};
|
||||
glm::i32vec3 vec = Pos-(glm::i16vec3) ((Pos::GlobalChunk(regionPos) << 2) | 0b10);
|
||||
return vec.x*vec.x+vec.y*vec.y+vec.z*vec.z;
|
||||
};
|
||||
|
||||
inline int32_t sqrDistance(Pos::GlobalChunk chunkPos) const {
|
||||
glm::i32vec3 vec = {Pos.x-chunkPos.X, Pos.y-chunkPos.Y, Pos.z-chunkPos.Z};
|
||||
glm::i32vec3 vec = Pos-(glm::i16vec3) chunkPos;
|
||||
return vec.x*vec.x+vec.y*vec.y+vec.z*vec.z;
|
||||
};
|
||||
|
||||
inline int64_t sqrDistance(Pos::Object objectPos) const {
|
||||
glm::i32vec3 vec = {Pos.x-(objectPos.x >> 20), Pos.y-(objectPos.y >> 20), Pos.z-(objectPos.z >> 20)};
|
||||
glm::i32vec3 vec = Pos-(glm::i16vec3) (objectPos >> 12 >> 4);
|
||||
return vec.x*vec.x+vec.y*vec.y+vec.z*vec.z;
|
||||
};
|
||||
|
||||
bool isIn(Pos::GlobalRegion regionPos) const {
|
||||
return sqrDistance(regionPos) < Range+192; // (8×sqrt(3))^2
|
||||
return sqrDistance(regionPos) < Range+12; // (2×sqrt(3))^2
|
||||
}
|
||||
|
||||
bool isIn(Pos::GlobalChunk chunkPos) const {
|
||||
@@ -62,8 +61,8 @@ struct ContentViewCircle {
|
||||
}
|
||||
};
|
||||
|
||||
// Регион -> чанки попавшие под обозрение Pos::Local16_u
|
||||
using ContentViewWorld = std::map<Pos::GlobalRegion, std::bitset<4096>>; // 1 - чанк виден, 0 - не виден
|
||||
// Регион -> чанки попавшие под обозрение Pos::bvec4u
|
||||
using ContentViewWorld = std::map<Pos::GlobalRegion, std::bitset<64>>; // 1 - чанк виден, 0 - не виден
|
||||
|
||||
struct ContentViewGlobal_DiffInfo;
|
||||
|
||||
@@ -99,9 +98,9 @@ inline ContentViewGlobal_DiffInfo ContentViewGlobal::calcDiffWith(const ContentV
|
||||
for(const auto &[regionPos, _] : newWorldView)
|
||||
newRegions.push_back(regionPos);
|
||||
} else {
|
||||
const std::map<Pos::GlobalRegion, std::bitset<4096>> &newRegions = newWorldView;
|
||||
const std::map<Pos::GlobalRegion, std::bitset<4096>> &oldRegions = oldWorldIter->second;
|
||||
std::map<Pos::GlobalRegion, std::bitset<4096>> *diffRegions = nullptr;
|
||||
const std::map<Pos::GlobalRegion, std::bitset<64>> &newRegions = newWorldView;
|
||||
const std::map<Pos::GlobalRegion, std::bitset<64>> &oldRegions = oldWorldIter->second;
|
||||
std::map<Pos::GlobalRegion, std::bitset<64>> *diffRegions = nullptr;
|
||||
|
||||
// Рассматриваем разницу меж регионами
|
||||
for(const auto &[newRegionPos, newRegionBitField] : newRegions) {
|
||||
@@ -113,8 +112,8 @@ inline ContentViewGlobal_DiffInfo ContentViewGlobal::calcDiffWith(const ContentV
|
||||
(*diffRegions)[newRegionPos] = newRegionBitField;
|
||||
newView.Regions[newWorldId].push_back(newRegionPos);
|
||||
} else {
|
||||
const std::bitset<4096> &oldChunks = oldRegionIter->second;
|
||||
std::bitset<4096> chunks = (~oldChunks) & newRegionBitField; // Останется поле с новыми чанками
|
||||
const std::bitset<64> &oldChunks = oldRegionIter->second;
|
||||
std::bitset<64> chunks = (~oldChunks) & newRegionBitField; // Останется поле с новыми чанками
|
||||
if(chunks._Find_first() != chunks.size()) {
|
||||
// Есть новые чанки
|
||||
if(!diffRegions)
|
||||
@@ -157,7 +156,8 @@ private:
|
||||
struct SubscribedObj {
|
||||
// Используется регионами
|
||||
std::vector<PortalId_t> Portals;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalRegion, std::unordered_set<LocalEntityId_t>>> Entities;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalRegion, std::unordered_set<RegionEntityId_t>>> Entities;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalRegion, std::unordered_set<RegionEntityId_t>>> FuncEntities;
|
||||
} Subscribed;
|
||||
|
||||
public:
|
||||
@@ -168,6 +168,8 @@ public:
|
||||
// Объявленная в чанках территория точно отслеживается (активная зона)
|
||||
ContentViewGlobal ContentViewState;
|
||||
ContentViewGlobal_DiffInfo ContentView_NewView, ContentView_LostView;
|
||||
// Миры добавленные в наблюдение в текущем такте
|
||||
std::vector<WorldId_t> NewWorlds;
|
||||
|
||||
// size_t CVCHash = 0; // Хэш для std::vector<ContentViewCircle>
|
||||
// std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> SubscribedRegions;
|
||||
@@ -190,14 +192,18 @@ public:
|
||||
void onWorldUpdate(WorldId_t worldId, World *worldObj);
|
||||
|
||||
// Нужно фильтровать неотслеживаемые чанки
|
||||
void onChunksUpdate_Voxels(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_map<Pos::Local16_u, const std::vector<VoxelCube>*> &chunks);
|
||||
void onChunksUpdate_Nodes(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_map<Pos::Local16_u, const std::unordered_map<Pos::Local16_u, Node>*> &chunks);
|
||||
void onChunksUpdate_LightPrism(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_map<Pos::Local16_u, const LightPrism*> &chunks);
|
||||
void onChunksUpdate_Voxels(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_map<Pos::bvec4u, const std::vector<VoxelCube>*> &chunks);
|
||||
void onChunksUpdate_Nodes(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_map<Pos::bvec4u, const Node*> &chunks);
|
||||
//void onChunksUpdate_LightPrism(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_map<Pos::bvec4u, const LightPrism*> &chunks);
|
||||
|
||||
void onEntityEnterLost(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_set<LocalEntityId_t> &enter, const std::unordered_set<LocalEntityId_t> &lost);
|
||||
void onEntitySwap(WorldId_t lastWorldId, Pos::GlobalRegion lastRegionPos, LocalEntityId_t lastId, WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, LocalEntityId_t newId);
|
||||
void onEntityEnterLost(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_set<RegionEntityId_t> &enter, const std::unordered_set<RegionEntityId_t> &lost);
|
||||
void onEntitySwap(WorldId_t lastWorldId, Pos::GlobalRegion lastRegionPos, RegionEntityId_t lastId, WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, RegionEntityId_t newId);
|
||||
void onEntityUpdates(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::vector<Entity> &entities);
|
||||
|
||||
void onFuncEntityEnterLost(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::unordered_set<RegionEntityId_t> &enter, const std::unordered_set<RegionEntityId_t> &lost);
|
||||
void onFuncEntitySwap(WorldId_t lastWorldId, Pos::GlobalRegion lastRegionPos, RegionEntityId_t lastId, WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, RegionEntityId_t newId);
|
||||
void onFuncEntityUpdates(WorldId_t worldId, Pos::GlobalRegion regionPos, const std::vector<Entity> &entities);
|
||||
|
||||
void onPortalEnterLost(const std::vector<void*> &enter, const std::vector<void*> &lost);
|
||||
void onPortalUpdates(const std::vector<void*> &portals);
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ void GameServer::Expanse_t::_accumulateContentViewCircles(ContentViewCircle circ
|
||||
ContentViewGlobal GameServer::Expanse_t::makeContentViewGlobal(const std::vector<ContentViewCircle> &views) {
|
||||
ContentViewGlobal cvg;
|
||||
Pos::GlobalRegion posRegion, lastPosRegion;
|
||||
std::bitset<4096> *cache = nullptr;
|
||||
std::bitset<64> *cache = nullptr;
|
||||
|
||||
for(const ContentViewCircle &circle : views) {
|
||||
ContentViewWorld &cvw = cvg[circle.WorldId];
|
||||
@@ -123,14 +123,14 @@ ContentViewGlobal GameServer::Expanse_t::makeContentViewGlobal(const std::vector
|
||||
continue;
|
||||
|
||||
Pos::GlobalChunk posChunk(x+circle.Pos.x, y+circle.Pos.y, z+circle.Pos.z);
|
||||
posRegion.fromChunk(posChunk);
|
||||
posRegion = posChunk >> 2;
|
||||
|
||||
if(!cache || lastPosRegion != posRegion) {
|
||||
lastPosRegion = posRegion;
|
||||
cache = &cvw[posRegion];
|
||||
}
|
||||
|
||||
cache->_Unchecked_set(posChunk.toLocal());
|
||||
cache->_Unchecked_set(Pos::bvec4u(posChunk).pack());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,17 +279,19 @@ Region* GameServer::forceGetRegion(WorldId_t worldId, Pos::GlobalRegion pos) {
|
||||
region->IsLoaded = true;
|
||||
region->load(&data);
|
||||
} else {
|
||||
|
||||
region->IsLoaded = true;
|
||||
if(pos.Y == 0) {
|
||||
for(int z = 0; z < 16; z++)
|
||||
for(int x = 0; x < 16; x++) {
|
||||
region->Voxels[x][0][z].push_back({0, {0, 0, 0}, {255, 255, 255},});
|
||||
}
|
||||
if(pos.y == 0) {
|
||||
for(int z = 0; z < 4; z++)
|
||||
for(int y = 0; y < 4; y++)
|
||||
for(int x = 0; x < 4; x++) {
|
||||
Node *nodes = (Node*) ®ion->Nodes[0][0][0][z][y][x];
|
||||
for(int index = 0; index < 16*16*16; index++)
|
||||
nodes[index] = {static_cast<DefNodeId_t>(y == 0 ? 1 : 0), 0};
|
||||
region->IsChunkChanged_Nodes |= (y == 0 ? 1 : 0) << (z*4*4+y*4+x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::fill(region->IsChunkChanged_Voxels, region->IsChunkChanged_Voxels+64, ~0);
|
||||
return region.get();
|
||||
} else {
|
||||
return iterRegion->second.get();
|
||||
@@ -403,27 +405,43 @@ void GameServer::run() {
|
||||
}
|
||||
|
||||
void GameServer::stepContent() {
|
||||
Content.TextureM.update(CurrentTickDuration);
|
||||
if(Content.TextureM.hasPreparedInformation()) {
|
||||
auto table = Content.TextureM.takePreparedInformation();
|
||||
Content.Texture.update(CurrentTickDuration);
|
||||
if(Content.Texture.hasPreparedInformation()) {
|
||||
auto table = Content.Texture.takePreparedInformation();
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
cec->Remote->informateDefTexture(table);
|
||||
cec->Remote->informateBinTexture(table);
|
||||
}
|
||||
}
|
||||
|
||||
Content.ModelM.update(CurrentTickDuration);
|
||||
if(Content.ModelM.hasPreparedInformation()) {
|
||||
auto table = Content.ModelM.takePreparedInformation();
|
||||
Content.Animation.update(CurrentTickDuration);
|
||||
if(Content.Animation.hasPreparedInformation()) {
|
||||
auto table = Content.Animation.takePreparedInformation();
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
cec->Remote->informateDefTexture(table);
|
||||
cec->Remote->informateBinAnimation(table);
|
||||
}
|
||||
}
|
||||
|
||||
Content.SoundM.update(CurrentTickDuration);
|
||||
if(Content.SoundM.hasPreparedInformation()) {
|
||||
auto table = Content.SoundM.takePreparedInformation();
|
||||
Content.Model.update(CurrentTickDuration);
|
||||
if(Content.Model.hasPreparedInformation()) {
|
||||
auto table = Content.Model.takePreparedInformation();
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
cec->Remote->informateDefTexture(table);
|
||||
cec->Remote->informateBinModel(table);
|
||||
}
|
||||
}
|
||||
|
||||
Content.Sound.update(CurrentTickDuration);
|
||||
if(Content.Sound.hasPreparedInformation()) {
|
||||
auto table = Content.Sound.takePreparedInformation();
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
cec->Remote->informateBinSound(table);
|
||||
}
|
||||
}
|
||||
|
||||
Content.Font.update(CurrentTickDuration);
|
||||
if(Content.Font.hasPreparedInformation()) {
|
||||
auto table = Content.Font.takePreparedInformation();
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
cec->Remote->informateBinFont(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,6 +520,17 @@ void GameServer::stepWorlds() {
|
||||
for(auto &pair : Expanse.Worlds)
|
||||
pair.second->onUpdate(this, CurrentTickDuration);
|
||||
|
||||
// Оповещаем о новых мирах
|
||||
for(const std::unique_ptr<ContentEventController>& cec : Game.CECs) {
|
||||
for(WorldId_t id : cec->NewWorlds) {
|
||||
auto iter = Expanse.Worlds.find(id);
|
||||
assert(iter != Expanse.Worlds.end());
|
||||
cec->onWorldUpdate(id, iter->second.get());
|
||||
}
|
||||
|
||||
cec->NewWorlds.clear();
|
||||
}
|
||||
|
||||
for(auto &pWorld : Expanse.Worlds) {
|
||||
World &wobj = *pWorld.second;
|
||||
|
||||
@@ -675,10 +704,10 @@ void GameServer::stepWorlds() {
|
||||
if(rPos != pRegion.first || pWorld.first != entity.WorldId) {
|
||||
|
||||
Region *toRegion = forceGetRegion(entity.WorldId, rPos);
|
||||
LocalEntityId_t newId = toRegion->pushEntity(entity);
|
||||
RegionEntityId_t newId = toRegion->pushEntity(entity);
|
||||
// toRegion->Entityes[newId].WorldId = Если мир изменился
|
||||
|
||||
if(newId == LocalEntityId_t(-1)) {
|
||||
if(newId == RegionEntityId_t(-1)) {
|
||||
// В другом регионе нет места
|
||||
} else {
|
||||
entity.IsRemoved = true;
|
||||
@@ -692,45 +721,42 @@ void GameServer::stepWorlds() {
|
||||
}
|
||||
|
||||
// Проверить необходимость перерасчёта вертикальной проходимости света
|
||||
std::unordered_map<Pos::Local16_u, const LightPrism*> ChangedLightPrism;
|
||||
{
|
||||
for(int big = 0; big < 64; big++) {
|
||||
uint64_t bits = region.IsChunkChanged_Voxels[big] | region.IsChunkChanged_Nodes[big];
|
||||
// std::unordered_map<Pos::bvec4u, const LightPrism*> ChangedLightPrism;
|
||||
// {
|
||||
// for(int big = 0; big < 64; big++) {
|
||||
// uint64_t bits = region.IsChunkChanged_Voxels[big] | region.IsChunkChanged_Nodes[big];
|
||||
|
||||
if(!bits)
|
||||
continue;
|
||||
// if(!bits)
|
||||
// continue;
|
||||
|
||||
for(int little = 0; little < 64; little++) {
|
||||
if(((bits >> little) & 1) == 0)
|
||||
continue;
|
||||
// for(int little = 0; little < 64; little++) {
|
||||
// if(((bits >> little) & 1) == 0)
|
||||
// continue;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Сбор данных об изменившихся чанках
|
||||
std::unordered_map<Pos::Local16_u, const std::vector<VoxelCube>*> ChangedVoxels;
|
||||
std::unordered_map<Pos::Local16_u, const std::unordered_map<Pos::Local16_u, Node>*> ChangedNodes;
|
||||
std::unordered_map<Pos::bvec4u, const std::vector<VoxelCube>*> ChangedVoxels;
|
||||
std::unordered_map<Pos::bvec4u, const Node*> ChangedNodes;
|
||||
{
|
||||
if(!region.IsChunkChanged_Voxels && !region.IsChunkChanged_Nodes)
|
||||
continue;
|
||||
|
||||
for(int big = 0; big < 64; big++) {
|
||||
uint64_t bits_voxels = region.IsChunkChanged_Voxels[big];
|
||||
uint64_t bits_nodes = region.IsChunkChanged_Nodes[big];
|
||||
for(int index = 0; index < 64; index++) {
|
||||
Pos::bvec4u pos;
|
||||
pos.unpack(index);
|
||||
|
||||
if(!bits_voxels && !bits_nodes)
|
||||
continue;
|
||||
if(((region.IsChunkChanged_Voxels >> index) & 1) == 1) {
|
||||
auto iter = region.Voxels.find(pos);
|
||||
assert(iter != region.Voxels.end());
|
||||
ChangedVoxels[pos] = &iter->second;
|
||||
}
|
||||
|
||||
for(int little = 0; little < 64; little++) {
|
||||
Pos::Local16_u pos(little & 0xf, ((big & 0x3) << 2) | (little >> 4), big >> 2);
|
||||
|
||||
if(((bits_voxels >> little) & 1) == 1) {
|
||||
ChangedVoxels[pos] = ®ion.Voxels[pos.X][pos.Y][pos.Z];
|
||||
}
|
||||
|
||||
if(((bits_nodes >> little) & 1) == 1) {
|
||||
ChangedNodes[pos] = ®ion.Nodes[pos.X][pos.Y][pos.Z];
|
||||
}
|
||||
if(((region.IsChunkChanged_Nodes >> index) & 1) == 1) {
|
||||
ChangedNodes[pos] = (Node*) ®ion.Nodes[0][0][0][pos.x][pos.y][pos.z];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -762,11 +788,11 @@ void GameServer::stepWorlds() {
|
||||
continue;
|
||||
|
||||
// Наблюдаемые чанки
|
||||
const std::bitset<4096> &chunkBitset = chunkBitsetIter->second;
|
||||
const std::bitset<64> &chunkBitset = chunkBitsetIter->second;
|
||||
|
||||
// Пересылка изменений в регионе
|
||||
if(!ChangedLightPrism.empty())
|
||||
cec->onChunksUpdate_LightPrism(pWorld.first, pRegion.first, ChangedLightPrism);
|
||||
// if(!ChangedLightPrism.empty())
|
||||
// cec->onChunksUpdate_LightPrism(pWorld.first, pRegion.first, ChangedLightPrism);
|
||||
|
||||
if(!ChangedVoxels.empty())
|
||||
cec->onChunksUpdate_Voxels(pWorld.first, pRegion.first, ChangedVoxels);
|
||||
@@ -776,31 +802,31 @@ void GameServer::stepWorlds() {
|
||||
|
||||
// Отправка полной информации о новых наблюдаемых чанках
|
||||
{
|
||||
const std::bitset<4096> *new_chunkBitset = nullptr;
|
||||
const std::bitset<64> *new_chunkBitset = nullptr;
|
||||
try { new_chunkBitset = &cec->ContentView_NewView.View.at(pWorld.first).at(pRegion.first); } catch(...) {}
|
||||
|
||||
if(new_chunkBitset) {
|
||||
std::unordered_map<Pos::Local16_u, const LightPrism*> newLightPrism;
|
||||
std::unordered_map<Pos::Local16_u, const std::vector<VoxelCube>*> newVoxels;
|
||||
std::unordered_map<Pos::Local16_u, const std::unordered_map<Pos::Local16_u, Node>*> newNodes;
|
||||
//std::unordered_map<Pos::bvec4u, const LightPrism*> newLightPrism;
|
||||
std::unordered_map<Pos::bvec4u, const std::vector<VoxelCube>*> newVoxels;
|
||||
std::unordered_map<Pos::bvec4u, const Node*> newNodes;
|
||||
|
||||
newLightPrism.reserve(new_chunkBitset->count());
|
||||
//newLightPrism.reserve(new_chunkBitset->count());
|
||||
newVoxels.reserve(new_chunkBitset->count());
|
||||
newNodes.reserve(new_chunkBitset->count());
|
||||
|
||||
size_t bitPos = new_chunkBitset->_Find_first();
|
||||
while(bitPos != new_chunkBitset->size()) {
|
||||
Pos::Local16_u chunkPos;
|
||||
Pos::bvec4u chunkPos;
|
||||
chunkPos = bitPos;
|
||||
|
||||
newLightPrism.insert({chunkPos, ®ion.Lights[0][0][chunkPos.X][chunkPos.Y][chunkPos.Z]});
|
||||
newVoxels.insert({chunkPos, ®ion.Voxels[chunkPos.X][chunkPos.Y][chunkPos.Z]});
|
||||
newNodes.insert({chunkPos, ®ion.Nodes[chunkPos.X][chunkPos.Y][chunkPos.Z]});
|
||||
//newLightPrism.insert({chunkPos, ®ion.Lights[0][0][chunkPos.X][chunkPos.Y][chunkPos.Z]});
|
||||
newVoxels.insert({chunkPos, ®ion.Voxels[chunkPos]});
|
||||
newNodes.insert({chunkPos, ®ion.Nodes[0][0][0][chunkPos.x][chunkPos.y][chunkPos.z]});
|
||||
|
||||
bitPos = new_chunkBitset->_Find_next(bitPos);
|
||||
}
|
||||
|
||||
cec->onChunksUpdate_LightPrism(pWorld.first, pRegion.first, newLightPrism);
|
||||
//cec->onChunksUpdate_LightPrism(pWorld.first, pRegion.first, newLightPrism);
|
||||
cec->onChunksUpdate_Voxels(pWorld.first, pRegion.first, newVoxels);
|
||||
cec->onChunksUpdate_Nodes(pWorld.first, pRegion.first, newNodes);
|
||||
}
|
||||
@@ -894,7 +920,7 @@ void GameServer::stepWorlds() {
|
||||
region.IsChanged = false;
|
||||
|
||||
SB_Region data;
|
||||
convertChunkVoxelsToRegion((const std::vector<VoxelCube>*) region.Voxels, data.Voxels);
|
||||
convertChunkVoxelsToRegion(region.Voxels, data.Voxels);
|
||||
SaveBackend.World->save(worldStringId, pRegion.first, &data);
|
||||
}
|
||||
|
||||
@@ -904,9 +930,8 @@ void GameServer::stepWorlds() {
|
||||
}
|
||||
|
||||
// Сброс информации об изменившихся данных
|
||||
|
||||
std::fill(region.IsChunkChanged_Voxels, region.IsChunkChanged_Voxels+64, 0);
|
||||
std::fill(region.IsChunkChanged_Nodes, region.IsChunkChanged_Nodes+64, 0);
|
||||
region.IsChunkChanged_Voxels = 0;
|
||||
region.IsChunkChanged_Nodes = 0;
|
||||
}
|
||||
|
||||
for(Pos::GlobalRegion regionPos : regionsToRemove) {
|
||||
@@ -931,7 +956,7 @@ void GameServer::stepWorlds() {
|
||||
|
||||
// TODO: Передефайнить идентификаторы нод
|
||||
|
||||
convertRegionVoxelsToChunks(data.Voxels, (std::vector<VoxelCube>*) robj.Voxels);
|
||||
convertRegionVoxelsToChunks(data.Voxels, robj.Voxels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,6 +1005,22 @@ void GameServer::stepViewContent() {
|
||||
ContentViewGlobal_DiffInfo lostView = cec.ContentViewState.calcDiffWith(newCbg);
|
||||
if(!newView.empty() || !lostView.empty()) {
|
||||
lost_CVG.insert({&cec, {newView}});
|
||||
|
||||
std::vector<WorldId_t> newWorlds, lostWorlds;
|
||||
|
||||
// Поиск потерянных миров
|
||||
for(const auto& [key, _] : cec.ContentViewState) {
|
||||
if(!newCbg.contains(key))
|
||||
lostWorlds.push_back(key);
|
||||
}
|
||||
|
||||
// Поиск новых увиденных миров
|
||||
for(const auto& [key, _] : newCbg) {
|
||||
if(!cec.ContentViewState.contains(key))
|
||||
newWorlds.push_back(key);
|
||||
}
|
||||
|
||||
cec.NewWorlds = std::move(newWorlds);
|
||||
cec.ContentViewState = std::move(newCbg);
|
||||
cec.ContentView_NewView = std::move(newView);
|
||||
cec.ContentView_LostView = std::move(lostView);
|
||||
@@ -1011,15 +1052,20 @@ void GameServer::stepSendPlayersPackets() {
|
||||
|
||||
full.uniq();
|
||||
|
||||
if(!full.NewTextures.empty())
|
||||
Content.TextureM.needResourceResponse(full.NewTextures);
|
||||
if(!full.BinTexture.empty())
|
||||
Content.Texture.needResourceResponse(full.BinTexture);
|
||||
|
||||
if(!full.NewModels.empty())
|
||||
Content.ModelM.needResourceResponse(full.NewModels);
|
||||
if(!full.BinAnimation.empty())
|
||||
Content.Animation.needResourceResponse(full.BinAnimation);
|
||||
|
||||
if(!full.NewSounds.empty())
|
||||
Content.SoundM.needResourceResponse(full.NewSounds);
|
||||
if(!full.BinModel.empty())
|
||||
Content.Model.needResourceResponse(full.BinModel);
|
||||
|
||||
if(!full.BinSound.empty())
|
||||
Content.Sound.needResourceResponse(full.BinSound);
|
||||
|
||||
if(!full.BinFont.empty())
|
||||
Content.Font.needResourceResponse(full.BinFont);
|
||||
}
|
||||
|
||||
void GameServer::stepLoadRegions() {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "World.hpp"
|
||||
|
||||
#include "SaveBackend.hpp"
|
||||
#include "boost/asio/ip/address.hpp"
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
@@ -51,20 +50,24 @@ class GameServer : public AsyncObject {
|
||||
// WorldDefManager WorldDM;
|
||||
// VoxelDefManager VoxelDM;
|
||||
// NodeDefManager NodeDM;
|
||||
BinaryResourceManager TextureM;
|
||||
BinaryResourceManager ModelM;
|
||||
BinaryResourceManager SoundM;
|
||||
BinaryResourceManager Texture;
|
||||
BinaryResourceManager Animation;
|
||||
BinaryResourceManager Model;
|
||||
BinaryResourceManager Sound;
|
||||
BinaryResourceManager Font;
|
||||
|
||||
ContentObj(asio::io_context &ioc,
|
||||
std::shared_ptr<ResourceFile> zeroTexture,
|
||||
std::shared_ptr<ResourceFile> zeroAnimation,
|
||||
std::shared_ptr<ResourceFile> zeroModel,
|
||||
std::shared_ptr<ResourceFile> zeroSound)
|
||||
: TextureM(ioc, zeroTexture),
|
||||
ModelM(ioc, zeroModel),
|
||||
SoundM(ioc, zeroSound)
|
||||
{
|
||||
|
||||
}
|
||||
std::shared_ptr<ResourceFile> zeroSound,
|
||||
std::shared_ptr<ResourceFile> zeroFont)
|
||||
: Texture(ioc, zeroTexture),
|
||||
Animation(ioc, zeroAnimation),
|
||||
Model(ioc, zeroModel),
|
||||
Sound(ioc, zeroSound),
|
||||
Font(ioc, zeroFont)
|
||||
{}
|
||||
|
||||
} Content;
|
||||
|
||||
@@ -114,7 +117,7 @@ class GameServer : public AsyncObject {
|
||||
public:
|
||||
GameServer(asio::io_context &ioc, fs::path worldPath)
|
||||
: AsyncObject(ioc),
|
||||
Content(ioc, nullptr, nullptr, nullptr)
|
||||
Content(ioc, nullptr, nullptr, nullptr, nullptr, nullptr)
|
||||
{
|
||||
init(worldPath);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -102,7 +102,7 @@ public:
|
||||
// Соотнести идентификатор на стороне клиента с идентификатором на стороне сервера
|
||||
ServerKey toServer(ClientKey ckey) {
|
||||
return CSmapper.toServer(ckey);
|
||||
}
|
||||
}
|
||||
|
||||
// Удаляет серверный идентификатор, освобождая идентификатор клиента
|
||||
ClientKey erase(ServerKey skey) {
|
||||
@@ -138,30 +138,43 @@ public:
|
||||
этих ресурсов и переотправлять их клиенту
|
||||
*/
|
||||
struct ResourceRequest {
|
||||
std::vector<BinTextureId_t> NewTextures;
|
||||
std::vector<BinModelId_t> NewModels;
|
||||
std::vector<BinSoundId_t> NewSounds;
|
||||
std::vector<BinTextureId_t> BinTexture;
|
||||
std::vector<BinAnimationId_t> BinAnimation;
|
||||
std::vector<BinModelId_t> BinModel;
|
||||
std::vector<BinSoundId_t> BinSound;
|
||||
std::vector<BinFontId_t> BinFont;
|
||||
|
||||
std::vector<DefWorldId_t> NewWorlds;
|
||||
std::vector<DefVoxelId_t> NewVoxels;
|
||||
std::vector<DefNodeId_t> NewNodes;
|
||||
std::vector<DefPortalId_t> NewPortals;
|
||||
std::vector<DefEntityId_t> NewEntityes;
|
||||
std::vector<DefVoxelId_t> Voxel;
|
||||
std::vector<DefNodeId_t> Node;
|
||||
std::vector<DefWorldId_t> World;
|
||||
std::vector<DefPortalId_t> Portal;
|
||||
std::vector<DefEntityId_t> Entity;
|
||||
std::vector<DefFuncEntityId_t> FuncEntity;
|
||||
std::vector<DefItemId_t> Item;
|
||||
|
||||
void insert(const ResourceRequest &obj) {
|
||||
NewTextures.insert(NewTextures.end(), obj.NewTextures.begin(), obj.NewTextures.end());
|
||||
NewModels.insert(NewModels.end(), obj.NewModels.begin(), obj.NewModels.end());
|
||||
NewSounds.insert(NewSounds.end(), obj.NewSounds.begin(), obj.NewSounds.end());
|
||||
BinTexture.insert(BinTexture.end(), obj.BinTexture.begin(), obj.BinTexture.end());
|
||||
BinAnimation.insert(BinAnimation.end(), obj.BinAnimation.begin(), obj.BinAnimation.end());
|
||||
BinModel.insert(BinModel.end(), obj.BinModel.begin(), obj.BinModel.end());
|
||||
BinSound.insert(BinSound.end(), obj.BinSound.begin(), obj.BinSound.end());
|
||||
BinFont.insert(BinFont.end(), obj.BinFont.begin(), obj.BinFont.end());
|
||||
|
||||
NewWorlds.insert(NewWorlds.end(), obj.NewWorlds.begin(), obj.NewWorlds.end());
|
||||
NewVoxels.insert(NewVoxels.end(), obj.NewVoxels.begin(), obj.NewVoxels.end());
|
||||
NewNodes.insert(NewNodes.end(), obj.NewNodes.begin(), obj.NewNodes.end());
|
||||
NewPortals.insert(NewPortals.end(), obj.NewPortals.begin(), obj.NewPortals.end());
|
||||
NewEntityes.insert(NewEntityes.end(), obj.NewEntityes.begin(), obj.NewEntityes.end());
|
||||
Voxel.insert(Voxel.end(), obj.Voxel.begin(), obj.Voxel.end());
|
||||
Node.insert(Node.end(), obj.Node.begin(), obj.Node.end());
|
||||
World.insert(World.end(), obj.World.begin(), obj.World.end());
|
||||
Portal.insert(Portal.end(), obj.Portal.begin(), obj.Portal.end());
|
||||
Entity.insert(Entity.end(), obj.Entity.begin(), obj.Entity.end());
|
||||
FuncEntity.insert(FuncEntity.end(), obj.FuncEntity.begin(), obj.FuncEntity.end());
|
||||
Item.insert(Item.end(), obj.Item.begin(), obj.Item.end());
|
||||
}
|
||||
|
||||
void uniq() {
|
||||
for(std::vector<ResourceId_t> *vec : {&NewTextures, &NewModels, &NewSounds, &NewWorlds, &NewVoxels, &NewNodes, &NewPortals, &NewEntityes}) {
|
||||
for(std::vector<ResourceId_t> *vec : {
|
||||
&BinTexture, &BinAnimation, &BinModel, &BinSound,
|
||||
&BinFont, &Voxel, &Node, &World,
|
||||
&Portal, &Entity, &FuncEntity, &Item
|
||||
})
|
||||
{
|
||||
std::sort(vec->begin(), vec->end());
|
||||
auto last = std::unique(vec->begin(), vec->end());
|
||||
vec->erase(last, vec->end());
|
||||
@@ -169,7 +182,7 @@ struct ResourceRequest {
|
||||
}
|
||||
};
|
||||
|
||||
using EntityKey = std::tuple<WorldId_c, Pos::GlobalRegion>;
|
||||
// using EntityKey = std::tuple<WorldId_c, Pos::GlobalRegion>;
|
||||
|
||||
|
||||
|
||||
@@ -186,85 +199,109 @@ class RemoteClient {
|
||||
DestroyLock UseLock;
|
||||
Net::AsyncSocket Socket;
|
||||
bool IsConnected = true, IsGoingShutdown = false;
|
||||
std::vector<HASH> ClientCache;
|
||||
std::vector<HASH> ClientBinaryCache;
|
||||
|
||||
/*
|
||||
При обнаружении нового контента составляется запрос (ResourceRequest)
|
||||
на полное описание ресурса. Это описание отправляется клиенту и используется
|
||||
чтобы выстроить зависимость какие базовые ресурсы использует контент.
|
||||
Если базовые ресурсы не известны, то они также запрашиваются.
|
||||
*/
|
||||
|
||||
struct ResUsesObj {
|
||||
// Счётчики использования базовых ресурсов высшими объектами
|
||||
std::map<BinTextureId_t, uint32_t> BinTexture;
|
||||
std::map<BinSoundId_t, uint32_t> BinSound;
|
||||
// Счётчики использования двоичных кэшируемых ресурсов
|
||||
std::map<BinTextureId_t, uint32_t> BinTexture;
|
||||
std::map<BinAnimationId_t, uint32_t> BinAnimation;
|
||||
std::map<BinModelId_t, uint32_t> BinModel;
|
||||
std::map<BinSoundId_t, uint32_t> BinSound;
|
||||
std::map<BinFontId_t, uint32_t> BinFont;
|
||||
|
||||
// Может использовать текстуры
|
||||
std::map<BinModelId_t, uint32_t> BinModel;
|
||||
// Счётчики использование профилей контента
|
||||
std::map<DefVoxelId_t, uint32_t> DefVoxel; // Один чанк, одно использование
|
||||
std::map<DefNodeId_t, uint32_t> DefNode;
|
||||
std::map<DefWorldId_t, uint32_t> DefWorld;
|
||||
std::map<DefPortalId_t, uint32_t> DefPortal;
|
||||
std::map<DefEntityId_t, uint32_t> DefEntity;
|
||||
std::map<DefFuncEntityId_t, uint32_t> DefFuncEntity;
|
||||
std::map<DefItemId_t, uint32_t> DefItem; // При передаче инвентарей?
|
||||
|
||||
// Будут использовать в своих определениях текстуры, звуки, модели
|
||||
std::map<DefWorldId_t, uint32_t> DefWorld;
|
||||
std::map<DefVoxelId_t, uint32_t> DefVoxel;
|
||||
std::map<DefNodeId_t, uint32_t> DefNode;
|
||||
std::map<DefPortalId_t, uint32_t> DefPortal;
|
||||
std::map<DefEntityId_t, uint32_t> DefEntity;
|
||||
|
||||
|
||||
// Переписываемый контент
|
||||
|
||||
// Сущности используют текстуры, звуки, модели
|
||||
struct EntityResourceUse {
|
||||
DefEntityId_t DefId;
|
||||
|
||||
std::unordered_set<BinTextureId_t> Textures;
|
||||
std::unordered_set<BinSoundId_t> Sounds;
|
||||
std::unordered_set<BinModelId_t> Models;
|
||||
// Зависимость профилей контента от профилей ресурсов
|
||||
// Нужно чтобы пересчитать зависимости к профилям ресурсов
|
||||
struct RefDefVoxel_t {
|
||||
std::vector<BinTextureId_t> Texture;
|
||||
std::vector<BinSoundId_t> Sound;
|
||||
};
|
||||
|
||||
std::map<GlobalEntityId_t, EntityResourceUse> Entity;
|
||||
|
||||
// Чанки используют воксели, ноды
|
||||
std::map<std::tuple<WorldId_t, Pos::GlobalChunk>, std::unordered_set<DefVoxelId_t>> ChunkVoxels;
|
||||
std::map<std::tuple<WorldId_t, Pos::GlobalChunk>, std::unordered_set<DefNodeId_t>> ChunkNodes;
|
||||
|
||||
// Миры
|
||||
struct WorldResourceUse {
|
||||
DefWorldId_t DefId;
|
||||
|
||||
std::unordered_set<BinTextureId_t> Textures;
|
||||
std::unordered_set<BinSoundId_t> Sounds;
|
||||
std::unordered_set<BinModelId_t> Models;
|
||||
std::map<DefVoxelId_t, RefDefVoxel_t> RefDefVoxel;
|
||||
struct RefDefNode_t {
|
||||
std::vector<BinModelId_t> Model;
|
||||
std::vector<BinSoundId_t> Sound;
|
||||
};
|
||||
|
||||
std::map<WorldId_t, WorldResourceUse> Worlds;
|
||||
|
||||
|
||||
// Порталы
|
||||
struct PortalResourceUse {
|
||||
DefPortalId_t DefId;
|
||||
|
||||
std::unordered_set<BinTextureId_t> Textures;
|
||||
std::unordered_set<BinSoundId_t> Sounds;
|
||||
std::unordered_set<BinModelId_t> Models;
|
||||
std::map<DefNodeId_t, RefDefNode_t> RefDefNode;
|
||||
struct RefDefWorld_t {
|
||||
std::vector<BinTextureId_t> Texture;
|
||||
std::vector<BinModelId_t> Model;
|
||||
};
|
||||
std::map<WorldId_t, RefDefWorld_t> RefDefWorld;
|
||||
struct RefDefPortal_t {
|
||||
std::vector<BinTextureId_t> Texture;
|
||||
std::vector<BinAnimationId_t> Animation;
|
||||
std::vector<BinModelId_t> Model;
|
||||
};
|
||||
std::map<DefPortalId_t, RefDefPortal_t> RefDefPortal;
|
||||
struct RefDefEntity_t {
|
||||
std::vector<BinTextureId_t> Texture;
|
||||
std::vector<BinAnimationId_t> Animation;
|
||||
std::vector<BinModelId_t> Model;
|
||||
};
|
||||
std::map<DefEntityId_t, RefDefEntity_t> RefDefEntity;
|
||||
struct RefDefFuncEntity_t {
|
||||
std::vector<BinTextureId_t> Texture;
|
||||
std::vector<BinAnimationId_t> Animation;
|
||||
std::vector<BinModelId_t> Model;
|
||||
};
|
||||
std::map<DefFuncEntityId_t, RefDefFuncEntity_t> RefDefFuncEntity;
|
||||
struct RefDefItem_t {
|
||||
std::vector<BinTextureId_t> Texture;
|
||||
std::vector<BinAnimationId_t> Animation;
|
||||
std::vector<BinModelId_t> Model;
|
||||
};
|
||||
std::map<DefItemId_t, RefDefItem_t> RefDefItem;
|
||||
|
||||
// Модификационные зависимости экземпляров профилей контента
|
||||
struct ChunkRef {
|
||||
// Отсортированные списки уникальных вокселей
|
||||
std::vector<DefVoxelId_t> Voxel;
|
||||
std::vector<DefNodeId_t> Node;
|
||||
};
|
||||
std::map<WorldId_t, std::map<Pos::GlobalChunk, ChunkRef>> RefChunk;
|
||||
struct RefWorld_t {
|
||||
DefWorldId_t Profile;
|
||||
};
|
||||
std::map<WorldId_t, RefWorld_t> RefWorld;
|
||||
struct RefPortal_t {
|
||||
DefPortalId_t Profile;
|
||||
};
|
||||
std::map<PortalId_t, RefPortal_t> RefPortal;
|
||||
struct RefEntity_t {
|
||||
DefEntityId_t Profile;
|
||||
};
|
||||
std::map<ServerEntityId_t, RefEntity_t> RefEntity;
|
||||
struct RefFuncEntity_t {
|
||||
DefFuncEntityId_t Profile;
|
||||
};
|
||||
std::map<ServerFuncEntityId_t, RefFuncEntity_t> RefFuncEntity;
|
||||
|
||||
std::map<PortalId_t, PortalResourceUse> Portals;
|
||||
|
||||
} ResUses;
|
||||
|
||||
// Смена идентификаторов сервера на клиентские
|
||||
struct {
|
||||
SCSKeyRemapper<BinTextureId_t, TextureId_c> BinTextures;
|
||||
SCSKeyRemapper<BinSoundId_t, SoundId_c> BinSounds;
|
||||
SCSKeyRemapper<BinModelId_t, ModelId_c> BinModels;
|
||||
|
||||
SCSKeyRemapper<DefWorldId_t, DefWorldId_c> DefWorlds;
|
||||
SCSKeyRemapper<DefVoxelId_t, DefVoxelId_c> DefVoxels;
|
||||
SCSKeyRemapper<DefNodeId_t, DefNodeId_c> DefNodes;
|
||||
SCSKeyRemapper<DefPortalId_t, DefPortalId_c> DefPortals;
|
||||
SCSKeyRemapper<DefEntityId_t, DefEntityId_c> DefEntityes;
|
||||
|
||||
SCSKeyRemapper<WorldId_t, WorldId_c> Worlds;
|
||||
SCSKeyRemapper<PortalId_t, PortalId_c> Portals;
|
||||
SCSKeyRemapper<GlobalEntityId_t, EntityId_c> Entityes;
|
||||
SCSKeyRemapper<ServerEntityId_t, ClientEntityId_t> Entityes;
|
||||
SCSKeyRemapper<ServerFuncEntityId_t, ClientEntityId_t> FuncEntityes;
|
||||
} ResRemap;
|
||||
|
||||
Net::Packet NextPacket;
|
||||
ResourceRequest NextRequest;
|
||||
std::vector<Net::Packet> SimplePackets;
|
||||
ResourceRequest NextRequest;
|
||||
|
||||
public:
|
||||
const std::string Username;
|
||||
@@ -273,7 +310,7 @@ public:
|
||||
|
||||
public:
|
||||
RemoteClient(asio::io_context &ioc, tcp::socket socket, const std::string username, std::vector<HASH> &&client_cache)
|
||||
: LOG("RemoteClient " + username), Socket(ioc, std::move(socket)), Username(username), ClientCache(std::move(client_cache))
|
||||
: LOG("RemoteClient " + username), Socket(ioc, std::move(socket)), Username(username), ClientBinaryCache(std::move(client_cache))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -291,27 +328,40 @@ public:
|
||||
}
|
||||
|
||||
// Функции подготавливают пакеты к отправке
|
||||
|
||||
// Отслеживаемое игроком использование контента
|
||||
// Maybe?
|
||||
// Текущий список вокселей, определения нод, которые больше не используются в чанке, и определения нод, которые теперь используются
|
||||
//void prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::vector<VoxelCube> &voxels, const std::vector<DefVoxelId_t> &noLongerInUseDefs, const std::vector<DefVoxelId_t> &nowUsed);
|
||||
void prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::vector<VoxelCube> &voxels);
|
||||
void prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::unordered_map<Pos::Local16_u, Node> &nodes);
|
||||
void prepareChunkUpdate_LightPrism(WorldId_t worldId, Pos::GlobalChunk chunkPos, const LightPrism *lights);
|
||||
// В зоне видимости добавился чанк или изменились его воксели
|
||||
void prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::vector<VoxelCube>* voxels);
|
||||
// В зоне видимости добавился чанк или изменились его ноды
|
||||
void prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const Node* nodes);
|
||||
void prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::unordered_map<Pos::bvec16u, Node> &nodes);
|
||||
//void prepareChunkUpdate_LightPrism(WorldId_t worldId, Pos::GlobalChunk chunkPos, const LightPrism *lights);
|
||||
// Чанк удалён из зоны видимости
|
||||
void prepareChunkRemove(WorldId_t worldId, Pos::GlobalChunk chunkPos);
|
||||
|
||||
void prepareEntitySwap(GlobalEntityId_t prevEntityId, GlobalEntityId_t nextEntityId);
|
||||
void prepareEntityUpdate(GlobalEntityId_t entityId, const Entity *entity);
|
||||
void prepareEntityRemove(GlobalEntityId_t entityId);
|
||||
// В зоне видимости добавилась новая сущность или она изменилась
|
||||
void prepareEntityUpdate(ServerEntityId_t entityId, const Entity *entity);
|
||||
// Наблюдаемая сущность пересекла границы региона, у неё изменился серверный идентификатор
|
||||
void prepareEntitySwap(ServerEntityId_t prevEntityId, ServerEntityId_t nextEntityId);
|
||||
// Клиент перестал наблюдать за сущностью
|
||||
void prepareEntityRemove(ServerEntityId_t entityId);
|
||||
|
||||
void prepareFuncEntitySwap(ServerEntityId_t prevEntityId, ServerEntityId_t nextEntityId);
|
||||
void prepareFuncEntityUpdate(ServerEntityId_t entityId, const FuncEntity *funcRntity);
|
||||
void prepareFuncEntityRemove(ServerEntityId_t entityId);
|
||||
|
||||
// В зоне видимости добавился мир или он изменился
|
||||
void prepareWorldUpdate(WorldId_t worldId, World* world);
|
||||
// Клиент перестал наблюдать за миром
|
||||
void prepareWorldRemove(WorldId_t worldId);
|
||||
|
||||
// В зоне видимости добавился порта или он изменился
|
||||
void preparePortalUpdate(PortalId_t portalId, void* portal);
|
||||
// Клиент перестал наблюдать за порталом
|
||||
void preparePortalRemove(PortalId_t portalId);
|
||||
|
||||
// Прочие моменты
|
||||
void prepareCameraSetEntity(GlobalEntityId_t entityId);
|
||||
void prepareCameraSetEntity(ServerEntityId_t entityId);
|
||||
|
||||
// Отправка подготовленных пакетов
|
||||
ResourceRequest pushPreparedPackets();
|
||||
@@ -321,16 +371,20 @@ public:
|
||||
// Глобально их можно запросить в выдаче pushPreparedPackets()
|
||||
|
||||
// Двоичные файлы
|
||||
void informateDefTexture(const std::unordered_map<BinTextureId_t, std::shared_ptr<ResourceFile>> &textures);
|
||||
void informateDefSound(const std::unordered_map<BinSoundId_t, std::shared_ptr<ResourceFile>> &sounds);
|
||||
void informateDefModel(const std::unordered_map<BinModelId_t, std::shared_ptr<ResourceFile>> &models);
|
||||
void informateBinTexture(const std::unordered_map<BinTextureId_t, std::shared_ptr<ResourceFile>> &textures);
|
||||
void informateBinAnimation(const std::unordered_map<BinAnimationId_t, std::shared_ptr<ResourceFile>> &animations);
|
||||
void informateBinModel(const std::unordered_map<BinModelId_t, std::shared_ptr<ResourceFile>> &models);
|
||||
void informateBinSound(const std::unordered_map<BinSoundId_t, std::shared_ptr<ResourceFile>> &sounds);
|
||||
void informateBinFont(const std::unordered_map<BinFontId_t, std::shared_ptr<ResourceFile>> &fonts);
|
||||
|
||||
// Игровые определения
|
||||
void informateDefWorld(const std::unordered_map<DefWorldId_t, World*> &worlds);
|
||||
void informateDefVoxel(const std::unordered_map<DefVoxelId_t, void*> &voxels);
|
||||
void informateDefNode(const std::unordered_map<DefNodeId_t, void*> &nodes);
|
||||
void informateDefEntityes(const std::unordered_map<DefEntityId_t, void*> &entityes);
|
||||
void informateDefPortals(const std::unordered_map<DefPortalId_t, void*> &portals);
|
||||
void informateDefWorld(const std::unordered_map<DefWorldId_t, void*> &worlds);
|
||||
void informateDefPortal(const std::unordered_map<DefPortalId_t, void*> &portals);
|
||||
void informateDefEntity(const std::unordered_map<DefEntityId_t, void*> &entityes);
|
||||
void informateDefFuncEntity(const std::unordered_map<DefFuncEntityId_t, void*> &funcEntityes);
|
||||
void informateDefItem(const std::unordered_map<DefItemId_t, void*> &items);
|
||||
|
||||
private:
|
||||
void checkPacketBorder(uint16_t size);
|
||||
@@ -338,10 +392,24 @@ private:
|
||||
coro<> readPacket(Net::AsyncSocket &sock);
|
||||
coro<> rP_System(Net::AsyncSocket &sock);
|
||||
|
||||
void incrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
std::unordered_set<BinModelId_t> &models);
|
||||
void decrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
std::unordered_set<BinModelId_t> &models);
|
||||
void incrementBinary(const std::vector<BinTextureId_t> &textures, const std::vector<BinAnimationId_t> &animation,
|
||||
const std::vector<BinSoundId_t> &sounds, const std::vector<BinModelId_t> &models,
|
||||
const std::vector<BinFontId_t> &fonts
|
||||
);
|
||||
void decrementBinary(std::vector<BinTextureId_t>&& textures, std::vector<BinAnimationId_t>&& animation,
|
||||
std::vector<BinSoundId_t>&& sounds, std::vector<BinModelId_t>&& models,
|
||||
std::vector<BinFontId_t>&& fonts
|
||||
);
|
||||
void informateBin(ToClient::L2Resource type, ResourceId_t id, const std::shared_ptr<ResourceFile>& pair);
|
||||
|
||||
// void incrementProfile(const std::vector<TextureId_t> &textures, const std::vector<ModelId_t> &model,
|
||||
// const std::vector<SoundId_t> &sounds, const std::vector<FontId_t> &font
|
||||
// );
|
||||
// void decrementProfile(std::vector<TextureId_t> &&textures, std::vector<ModelId_t> &&model,
|
||||
// std::vector<SoundId_t> &&sounds, std::vector<FontId_t> &&font
|
||||
// );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace LV::Server {
|
||||
struct SB_Region {
|
||||
std::vector<VoxelCube_Region> Voxels;
|
||||
std::unordered_map<DefVoxelId_t, std::string> VoxelsMap;
|
||||
std::unordered_map<Pos::Local16_u, Node> Nodes;
|
||||
std::unordered_map<Pos::bvec16u, Node> Nodes;
|
||||
std::unordered_map<DefNodeId_t, std::string> NodeMap;
|
||||
std::vector<Entity> Entityes;
|
||||
std::unordered_map<DefEntityId_t, std::string> EntityMap;
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
}
|
||||
|
||||
fs::path getPath(std::string worldId, Pos::GlobalRegion regionPos) {
|
||||
return Dir / worldId / std::to_string(regionPos.X) / std::to_string(regionPos.Y) / std::to_string(regionPos.Z);
|
||||
return Dir / worldId / std::to_string(regionPos.x) / std::to_string(regionPos.y) / std::to_string(regionPos.z);
|
||||
}
|
||||
|
||||
virtual bool isAsync() { return false; };
|
||||
@@ -48,13 +48,13 @@ public:
|
||||
for(js::value &jvVoxel : jaVoxels) {
|
||||
js::object &joVoxel = jvVoxel.as_object();
|
||||
VoxelCube_Region cube;
|
||||
cube.VoxelId = joVoxel.at("Material").as_uint64();
|
||||
cube.Left.X = joVoxel.at("LeftX").as_uint64();
|
||||
cube.Left.Y = joVoxel.at("LeftY").as_uint64();
|
||||
cube.Left.Z = joVoxel.at("LeftZ").as_uint64();
|
||||
cube.Right.X = joVoxel.at("RightX").as_uint64();
|
||||
cube.Right.Y = joVoxel.at("RightY").as_uint64();
|
||||
cube.Right.Z = joVoxel.at("RightZ").as_uint64();
|
||||
cube.Data = joVoxel.at("Data").as_uint64();
|
||||
cube.Left.x = joVoxel.at("LeftX").as_uint64();
|
||||
cube.Left.y = joVoxel.at("LeftY").as_uint64();
|
||||
cube.Left.z = joVoxel.at("LeftZ").as_uint64();
|
||||
cube.Right.x = joVoxel.at("RightX").as_uint64();
|
||||
cube.Right.y = joVoxel.at("RightY").as_uint64();
|
||||
cube.Right.z = joVoxel.at("RightZ").as_uint64();
|
||||
data->Voxels.push_back(cube);
|
||||
}
|
||||
}
|
||||
@@ -74,13 +74,13 @@ public:
|
||||
js::array jaVoxels;
|
||||
for(const VoxelCube_Region &cube : data->Voxels) {
|
||||
js::object joVoxel;
|
||||
joVoxel["Material"] = cube.VoxelId;
|
||||
joVoxel["LeftX"] = cube.Left.X;
|
||||
joVoxel["LeftY"] = cube.Left.Y;
|
||||
joVoxel["LeftZ"] = cube.Left.Z;
|
||||
joVoxel["RightX"] = cube.Right.X;
|
||||
joVoxel["RightY"] = cube.Right.Y;
|
||||
joVoxel["RightZ"] = cube.Right.Z;
|
||||
joVoxel["Data"] = cube.Data;
|
||||
joVoxel["LeftX"] = cube.Left.x;
|
||||
joVoxel["LeftY"] = cube.Left.y;
|
||||
joVoxel["LeftZ"] = cube.Left.z;
|
||||
joVoxel["RightX"] = cube.Right.x;
|
||||
joVoxel["RightY"] = cube.Right.y;
|
||||
joVoxel["RightZ"] = cube.Right.z;
|
||||
jaVoxels.push_back(std::move(joVoxel));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,17 @@ class GameServer;
|
||||
|
||||
class Region {
|
||||
public:
|
||||
uint64_t IsChunkChanged_Voxels[64] = {0};
|
||||
uint64_t IsChunkChanged_Nodes[64] = {0};
|
||||
uint64_t IsChunkChanged_Voxels = 0;
|
||||
uint64_t IsChunkChanged_Nodes = 0;
|
||||
bool IsChanged = false; // Изменён ли был регион, относительно последнего сохранения
|
||||
// cx cy cz
|
||||
std::vector<VoxelCube> Voxels[16][16][16];
|
||||
std::unordered_map<Pos::bvec4u, std::vector<VoxelCube>> Voxels;
|
||||
// x y cx cy cz
|
||||
LightPrism Lights[16][16][16][16][16];
|
||||
std::unordered_map<Pos::Local16_u, Node> Nodes[16][16][16];
|
||||
//LightPrism Lights[16][16][4][4][4];
|
||||
|
||||
Node Nodes[16][16][16][4][4][4];
|
||||
|
||||
std::vector<Entity> Entityes;
|
||||
std::vector<FuncEntity> FuncEntityes;
|
||||
std::vector<ContentEventController*> CECs;
|
||||
// Используется для прорежения количества проверок на наблюдаемые чанки и сущности
|
||||
// В одно обновление региона - проверка одного наблюдателя
|
||||
@@ -35,11 +36,10 @@ public:
|
||||
|
||||
void getCollideBoxes(Pos::GlobalRegion rPos, AABB aabb, std::vector<CollisionAABB> &boxes) {
|
||||
// Абсолютная позиция начала региона
|
||||
Pos::Object raPos(rPos.X, rPos.Y, rPos.Z);
|
||||
raPos <<= Pos::Object_t::BS_Bit;
|
||||
Pos::Object raPos = Pos::Object(rPos) << Pos::Object_t::BS_Bit;
|
||||
|
||||
// Бокс региона
|
||||
AABB regionAABB(raPos, raPos+Pos::Object(Pos::Object_t::BS*256));
|
||||
AABB regionAABB(raPos, raPos+Pos::Object(Pos::Object_t::BS*64));
|
||||
|
||||
// Если регион не загружен, то он весь непроходим
|
||||
if(!IsLoaded) {
|
||||
@@ -65,46 +65,48 @@ public:
|
||||
|
||||
// Собираем коробки вокселей
|
||||
if(aabb.isCollideWith(regionAABB)) {
|
||||
// Определяем с какими чанками есть пересечения
|
||||
glm::ivec3 beg, end;
|
||||
for(int axis = 0; axis < 3; axis++)
|
||||
beg[axis] = std::max(aabb.VecMin[axis], regionAABB.VecMin[axis]) >> 16;
|
||||
beg[axis] = std::max(aabb.VecMin[axis], regionAABB.VecMin[axis]) >> 12 >> 4;
|
||||
for(int axis = 0; axis < 3; axis++)
|
||||
end[axis] = (std::min(aabb.VecMax[axis], regionAABB.VecMax[axis])+0xffff) >> 16;
|
||||
end[axis] = (std::min(aabb.VecMax[axis], regionAABB.VecMax[axis])+0xffff) >> 12 >> 4;
|
||||
|
||||
for(; beg.z <= end.z; beg.z++)
|
||||
for(; beg.y <= end.y; beg.y++)
|
||||
for(; beg.x <= end.x; beg.x++) {
|
||||
std::vector<VoxelCube> &voxels = Voxels[beg.x][beg.y][beg.z];
|
||||
auto iterVoxels = Voxels.find(Pos::bvec4u(beg));
|
||||
|
||||
if(voxels.empty())
|
||||
if(iterVoxels == Voxels.end() && iterVoxels->second.empty())
|
||||
continue;
|
||||
|
||||
auto &voxels = iterVoxels->second;
|
||||
|
||||
CollisionAABB aabbInfo = CollisionAABB(regionAABB);
|
||||
for(int axis = 0; axis < 3; axis++)
|
||||
aabbInfo.VecMin[axis] |= beg[axis] << 16;
|
||||
aabbInfo.VecMin.set(axis, aabbInfo.VecMin[axis] | beg[axis] << 16);
|
||||
|
||||
for(size_t iter = 0; iter < voxels.size(); iter++) {
|
||||
VoxelCube &cube = voxels[iter];
|
||||
|
||||
for(int axis = 0; axis < 3; axis++)
|
||||
aabbInfo.VecMin[axis] &= ~0xff00;
|
||||
aabbInfo.VecMin.set(axis, aabbInfo.VecMin[axis] & ~0xff00);
|
||||
aabbInfo.VecMax = aabbInfo.VecMin;
|
||||
|
||||
aabbInfo.VecMin.x |= int(cube.Left.X) << 8;
|
||||
aabbInfo.VecMin.y |= int(cube.Left.Y) << 8;
|
||||
aabbInfo.VecMin.z |= int(cube.Left.Z) << 8;
|
||||
aabbInfo.VecMin.x |= int(cube.Left.x) << 8;
|
||||
aabbInfo.VecMin.y |= int(cube.Left.y) << 8;
|
||||
aabbInfo.VecMin.z |= int(cube.Left.z) << 8;
|
||||
|
||||
aabbInfo.VecMax.x |= int(cube.Right.X) << 8;
|
||||
aabbInfo.VecMax.y |= int(cube.Right.Y) << 8;
|
||||
aabbInfo.VecMax.z |= int(cube.Right.Z) << 8;
|
||||
aabbInfo.VecMax.x |= int(cube.Right.x) << 8;
|
||||
aabbInfo.VecMax.y |= int(cube.Right.y) << 8;
|
||||
aabbInfo.VecMax.z |= int(cube.Right.z) << 8;
|
||||
|
||||
if(aabb.isCollideWith(aabbInfo)) {
|
||||
aabbInfo = {
|
||||
.Type = CollisionAABB::EnumType::Voxel,
|
||||
.Voxel = {
|
||||
.Chunk = Pos::Local16_u(beg.x, beg.y, beg.z),
|
||||
.Chunk = Pos::bvec4u(beg.x, beg.y, beg.z),
|
||||
.Index = static_cast<uint32_t>(iter),
|
||||
.Id = cube.VoxelId
|
||||
}
|
||||
};
|
||||
|
||||
@@ -118,7 +120,7 @@ public:
|
||||
|
||||
}
|
||||
|
||||
LocalEntityId_t pushEntity(Entity &entity) {
|
||||
RegionEntityId_t pushEntity(Entity &entity) {
|
||||
for(size_t iter = 0; iter < Entityes.size(); iter++) {
|
||||
Entity &obj = Entityes[iter];
|
||||
|
||||
@@ -135,16 +137,17 @@ public:
|
||||
return Entityes.size()-1;
|
||||
}
|
||||
|
||||
return LocalEntityId_t(-1);
|
||||
// В регионе не осталось места
|
||||
return RegionEntityId_t(-1);
|
||||
}
|
||||
|
||||
void load(SB_Region *data) {
|
||||
convertRegionVoxelsToChunks(data->Voxels, (std::vector<VoxelCube>*) Voxels);
|
||||
convertRegionVoxelsToChunks(data->Voxels, Voxels);
|
||||
}
|
||||
|
||||
void save(SB_Region *data) {
|
||||
data->Voxels.clear();
|
||||
convertChunkVoxelsToRegion((const std::vector<VoxelCube>*) Voxels, data->Voxels);
|
||||
convertChunkVoxelsToRegion(Voxels, data->Voxels);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user