Сейчас оно компилируется, пересмотр расчёта зон наблюдения

This commit is contained in:
2025-06-29 11:55:46 +06:00
parent e083510525
commit cfc80660dd
17 changed files with 1286 additions and 893 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
#include "Common/Abstract.hpp"
#include <iostream>
#pragma once
#include <algorithm>
namespace LV {

View File

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

View File

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

View File

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

View File

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

View File

@@ -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*) &region->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] = &region.Voxels[pos.X][pos.Y][pos.Z];
}
if(((bits_nodes >> little) & 1) == 1) {
ChangedNodes[pos] = &region.Nodes[pos.X][pos.Y][pos.Z];
}
if(((region.IsChunkChanged_Nodes >> index) & 1) == 1) {
ChangedNodes[pos] = (Node*) &region.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, &region.Lights[0][0][chunkPos.X][chunkPos.Y][chunkPos.Z]});
newVoxels.insert({chunkPos, &region.Voxels[chunkPos.X][chunkPos.Y][chunkPos.Z]});
newNodes.insert({chunkPos, &region.Nodes[chunkPos.X][chunkPos.Y][chunkPos.Z]});
//newLightPrism.insert({chunkPos, &region.Lights[0][0][chunkPos.X][chunkPos.Y][chunkPos.Z]});
newVoxels.insert({chunkPos, &region.Voxels[chunkPos]});
newNodes.insert({chunkPos, &region.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() {

View File

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

View File

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

View File

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

View File

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

View File

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