#pragma once #include "Common/Net.hpp" #include "TOSLib.hpp" #include #include #include #include #include #include #include namespace LV { namespace Pos { template class BitVec3 { static_assert(std::is_integral_v, "T must be an integral type"); static_assert(BitsPerComponent > 0, "Bits per component must be at least 1"); static constexpr size_t N = 3; static constexpr auto getType() { constexpr size_t bits = N*BitsPerComponent; if constexpr(bits <= 8) return uint8_t(0); else if constexpr(bits <= 16) return uint16_t(0); else if constexpr(bits <= 32) return uint32_t(0); else if constexpr(bits <= 64) return uint64_t(0); else { static_assert("Нет подходящего хранилища"); return uint8_t(0); } } public: using Pack = decltype(getType()); using Type = T; using value_type = Type; T x : BitsPerComponent, y : BitsPerComponent, z : BitsPerComponent; 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 BitVec3(const glm::vec<3, vT, vQ> vec) : x(vec.x), y(vec.y), z(vec.z) {} BitVec3(const BitVec3&) = default; BitVec3(BitVec3&&) = default; BitVec3& operator=(const BitVec3&) = default; BitVec3& operator=(BitVec3&&) = default; void set(size_t index, const T value) { assert(index < N); if(index == 0) x = value; else if(index == 1) y = value; else if(index == 2) z = value; } const T get(size_t index) const { assert(index < N); if(index == 0) return x; else if(index == 1) return y; else if(index == 2) return z; return 0; } const T operator[](size_t index) const { return get(index); } Pack pack() const requires (N*BitsPerComponent <= 64) { Pack out = 0; using U = std::make_unsigned_t; for(size_t iter = 0; iter < N; iter++) { out |= Pack(U(get(iter)) & U((Pack(1) << BitsPerComponent)-1)) << BitsPerComponent*iter; } return out; } BitVec3 unpack(const Pack pack) requires (N*BitsPerComponent <= 64) { using U = std::make_unsigned_t; for(size_t iter = 0; iter < N; iter++) { set(iter, T(U((pack >> BitsPerComponent*iter) & U((Pack(1) << BitsPerComponent)-1)))); } return *this; } auto operator<=>(const BitVec3&) const = default; template operator BitVec3() const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) { out.set(iter, T2(std::make_unsigned_t(std::make_unsigned_t(get(iter))))); } return out; } template 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.set(iter, get(iter) + other[iter]); return out; } BitVec3& operator+=(const BitVec3 &other) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) + other[iter]); return *this; } BitVec3 operator+(const T value) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) + value); return out; } BitVec3& operator+=(const T value) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) + value); return *this; } BitVec3 operator-(const BitVec3 &other) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) - other[iter]); return out; } BitVec3& operator-=(const BitVec3 &other) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) - other[iter]); return *this; } BitVec3 operator-(const T value) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) - value); return out; } BitVec3& operator-=(const T value) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) - value); return *this; } BitVec3 operator*(const BitVec3 &other) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) * other[iter]); return out; } BitVec3& operator*=(const BitVec3 &other) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) * other[iter]); return *this; } BitVec3 operator*(const T value) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) * value); return out; } BitVec3& operator*=(const T value) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) * value); return *this; } BitVec3 operator/(const BitVec3 &other) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) / other[iter]); return out; } BitVec3& operator/=(const BitVec3 &other) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) / other[iter]); return *this; } BitVec3 operator/(const T value) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) / value); return out; } BitVec3& operator/=(const T value) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) / value); return *this; } BitVec3 operator>>(const auto offset) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) >> offset); return out; } BitVec3& operator>>=(const auto offset) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) >> offset); return *this; } BitVec3 operator<<(const auto offset) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) << offset); return out; } BitVec3& operator<<=(const auto offset) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) << offset); return *this; } BitVec3 operator|(const BitVec3 other) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) | other[iter]); return out; } BitVec3& operator|=(const BitVec3 other) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) | other[iter]); return *this; } BitVec3 operator|(const T value) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) | value); return out; } BitVec3& operator|=(const T value) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) | value); return *this; } BitVec3 operator&(const BitVec3 other) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) & other[iter]); return out; } BitVec3& operator&=(const BitVec3 other) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) & other[iter]); return *this; } BitVec3 operator&(const T value) const { BitVec3 out; for(size_t iter = 0; iter < N; iter++) out.set(iter, get(iter) & value); return out; } BitVec3& operator&=(const T value) { for(size_t iter = 0; iter < N; iter++) set(iter, get(iter) & value); return *this; } static constexpr size_t length() { return N; } }; using bvec4i = BitVec3; using bvec4u = BitVec3; using bvec16i = BitVec3; using bvec16u = BitVec3; using bvec64i = BitVec3; using bvec64u = BitVec3; using bvec256i = BitVec3; using bvec256u = BitVec3; using bvec1024i = BitVec3; using bvec1024u = BitVec3; using bvec4096i = BitVec3; using bvec4096u = BitVec3; using GlobalVoxel = BitVec3; using GlobalNode = BitVec3; using GlobalChunk = BitVec3; using GlobalRegion = BitVec3; using Object = BitVec3; struct Object_t { // Позиции объектов целочисленные, BS единиц это один метр static constexpr int32_t BS = 4096, BS_Bit = 12; static glm::vec3 asFloatVec(const Object &obj) { return glm::vec3(float(obj[0])/float(BS), float(obj[1])/float(BS), float(obj[2])/float(BS)); } static GlobalNode asNodePos(const Object &obj) { return (GlobalNode) (obj >> BS_Bit); } static GlobalChunk asChunkPos(const Object &obj) { return (GlobalChunk) (obj >> BS_Bit >> 4); } static GlobalRegion asRegionsPos(const Object &obj) { return (GlobalRegion) (obj >> BS_Bit >> 6); } }; } using ResourceId_t = uint32_t; /* Bin привязывается к путю. Если по путю обновляется объект, пересчитывается его кеш и на клиентах обновляется */ enum class EnumBinResource { Texture, Animation, Model, Sound, Font, MAX_ENUM }; using BinaryResource = std::shared_ptr; // Двоичные данные using BinTextureId_t = ResourceId_t; using BinAnimationId_t = ResourceId_t; using BinModelId_t = ResourceId_t; using BinSoundId_t = ResourceId_t; using BinFontId_t = ResourceId_t; enum class EnumDefContent { Voxel, Node, Generator, World, Portal, Entity, Item, MAX_ENUM }; // Игровые определения 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 DefItemId_t = ResourceId_t; // Контент, основанный на игровых определениях using WorldId_t = ResourceId_t; using PortalId_t = ResourceId_t; // struct LightPrism { // uint8_t R : 2, G : 2, B : 2; // }; struct VoxelCube { union { struct { DefVoxelId_t VoxelId : 24, Meta : 8; }; DefVoxelId_t Data = 0; }; Pos::bvec256u Pos, Size; // Размер+1, 0 это единичный размер auto operator<=>(const VoxelCube& other) const { if (auto cmp = Pos <=> other.Pos; cmp != 0) return cmp; if (auto cmp = Size <=> other.Size; cmp != 0) return cmp; return Data <=> other.Data; } bool operator==(const VoxelCube& other) const { return Pos == other.Pos && Size == other.Size && Data == other.Data; } }; struct CompressedVoxels { std::u8string Compressed; // Уникальный сортированный список идентификаторов вокселей std::vector Defines; }; CompressedVoxels compressVoxels(const std::vector& voxels, bool fast = true); std::vector unCompressVoxels(const std::u8string& compressed); struct Node { union { struct { DefNodeId_t NodeId : 24, Meta : 8; }; DefNodeId_t Data; }; }; struct CompressedNodes { std::u8string Compressed; // Уникальный сортированный список идентификаторов нод std::vector Defines; }; CompressedNodes compressNodes(const Node* nodes, bool fast = true); void unCompressNodes(const std::u8string& compressed, Node* ptr); std::u8string compressLinear(const std::u8string& data); std::u8string unCompressLinear(const std::u8string& data); enum struct TexturePipelineCMD : uint8_t { Texture, // Указание текстуры Combine, // Комбинирование }; struct TexturePipeline { std::vector BinTextures; std::u8string Pipeline; }; struct DefVoxel_t { }; struct DefNode_t { enum struct EnumDrawType : uint8_t { NoDraw, // Не рисуется Simple, // Простая нода с текстурами на каждой стороне } DrawType = EnumDrawType::Simple; TexturePipeline Texs[6]; }; struct DefWorld_t { }; struct DefPortal_t { }; struct DefEntity_t { }; struct DefItem_t { }; using Hash_t = std::array; } #include namespace std { template struct hash> { std::size_t operator()(const LV::Pos::BitVec3& obj) const { std::size_t result = 0; constexpr std::size_t seed = 0x9E3779B9; for (size_t i = 0; i < 3; ++i) { T value = obj[i]; std::hash hasher; std::size_t h = hasher(value); result ^= h + seed + (result << 6) + (result >> 2); } return result; } }; template <> struct hash { std::size_t operator()(const LV::Hash_t& hash) const noexcept { std::size_t v = 14695981039346656037ULL; for (const auto& byte : hash) { v ^= static_cast(byte); v *= 1099511628211ULL; } return v; } }; }