From c624c1ad0b1c5900b7a6e4167ec60954a3106260 Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Fri, 22 Aug 2025 17:49:49 +0600 Subject: [PATCH] * --- Src/Common/Abstract.cpp | 683 +++++++++++++++++------------------ Src/Common/Abstract.hpp | 9 +- Src/Common/Net.hpp | 86 ++++- Src/Server/AssetsManager.hpp | 3 +- 4 files changed, 400 insertions(+), 381 deletions(-) diff --git a/Src/Common/Abstract.cpp b/Src/Common/Abstract.cpp index ea94372..8da0af3 100644 --- a/Src/Common/Abstract.cpp +++ b/Src/Common/Abstract.cpp @@ -1,9 +1,7 @@ #include "Abstract.hpp" +#include "Common/Net.hpp" #include "TOSLib.hpp" #include "boost/json.hpp" -#include "boost/json/array.hpp" -#include "boost/json/object.hpp" -#include "boost/json/string_view.hpp" #include #include #include @@ -864,55 +862,152 @@ PreparedNodeState::PreparedNodeState(const std::string_view modid, const sol::ta } -PreparedNodeState::PreparedNodeState(const std::string_view modid, const std::u8string& data) { +PreparedNodeState::PreparedNodeState(const std::u8string& data) { + Net::LinearReader lr(data); + + uint16_t size; + lr >> size; + + ResourceToLocalId.reserve(size); + for(int counter = 0; counter < size; counter++) { + std::string domain, key; + lr >> domain >> key; + ResourceToLocalId.emplace_back(std::move(domain), std::move(key)); + } + + lr >> size; + Nodes.reserve(size); + for(int counter = 0; counter < size; counter++) { + uint8_t index = lr.read(); + Node node; + + switch(index) { + case 0: node.v = Node::Num(lr.read()); break; + case 1: node.v = Node::Var(lr.read()); break; + case 2: { + Node::Unary unary; + unary.op = Op(lr.read()); + unary.rhs = lr.read(); + node.v = unary; + break; + } + case 3: { + Node::Binary binary; + binary.op = Op(lr.read()); + binary.lhs = lr.read(); + binary.rhs = lr.read(); + node.v = binary; + break; + } + default: + MAKE_ERROR("Ошибка формата данных"); + } + + Nodes.emplace_back(std::move(node)); + } + + lr >> size; + Routes.reserve(size); + for(int counter = 0; counter < size; counter++) { + uint16_t nodeId, variantsSize; + lr >> nodeId >> variantsSize; + + boost::container::small_vector< + std::pair>, + 1 + > variants; + variants.reserve(variantsSize); + + for(int counter2 = 0; counter2 < variantsSize; counter2++) { + float weight; + lr >> weight; + + if(lr.read()) { + VectorModel mod; + uint16_t modelsSize; + lr >> modelsSize; + mod.Models.reserve(modelsSize); + + for(int counter3 = 0; counter3 < modelsSize; counter3++) { + Model mod2; + lr >> mod2.Id; + mod2.UVLock = lr.read(); + + uint16_t transformsSize; + lr >> transformsSize; + + mod2.Transforms.reserve(transformsSize); + for(int counter4 = 0; counter4 < transformsSize; counter4++) { + Transformation tr; + tr.Op = Transformation::EnumTransform(lr.read()); + mod2.Transforms.push_back(tr); + } + } + + mod.UVLock = lr.read(); + + uint16_t transformsSize; + lr >> transformsSize; + + mod.Transforms.reserve(transformsSize); + for(int counter3 = 0; counter3 < transformsSize; counter3++) { + Transformation tr; + tr.Op = Transformation::EnumTransform(lr.read()); + mod.Transforms.push_back(tr); + } + + variants.emplace_back(weight, std::move(mod)); + } else { + Model mod; + lr >> mod.Id; + mod.UVLock = lr.read(); + uint16_t transformsSize; + lr >> transformsSize; + + mod.Transforms.reserve(transformsSize); + for(int counter3 = 0; counter3 < transformsSize; counter3++) { + Transformation tr; + tr.Op = Transformation::EnumTransform(lr.read()); + mod.Transforms.push_back(tr); + } + + variants.emplace_back(weight, std::move(mod)); + } + } + } } std::u8string PreparedNodeState::dump() const { - std::basic_stringstream result; - uint16_t v16; + Net::Packet result; // ResourceToLocalId assert(ResourceToLocalId.size() < (1 << 16)); - v16 = ResourceToLocalId.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(ResourceToLocalId.size()); for(const auto& [domain, key] : ResourceToLocalId) { assert(domain.size() < 32); - result.put(uint8_t(domain.size() & 0xff)); - result << (const std::u8string&) domain; + result << domain; assert(key.size() < 32); - result.put(uint8_t(key.size() & 0xff)); - result << (const std::u8string&) key; + result << key; } // Nodes assert(Nodes.size() < (1 << 16)); - v16 = Nodes.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(Nodes.size()); for(const Node& node : Nodes) { - result.put(uint8_t(node.v.index())); + result << uint8_t(node.v.index()); if(const Node::Num* val = std::get_if(&node.v)) { - for(int iter = 0; iter < 4; iter++) { - result.put((val->v >> 8*iter) & 0xff); - } + result << val->v; } else if(const Node::Var* val = std::get_if(&node.v)) { assert(val->name.size() < 32); - result << (const std::u8string&) val->name; + result << val->name; } else if(const Node::Unary* val = std::get_if(&node.v)) { - result.put(uint8_t(val->op)); - result.put(uint8_t(val->rhs & 0xff)); - result.put(uint8_t((val->rhs >> 8) & 0xff)); + result << uint8_t(val->op) << val->rhs; } else if(const Node::Binary* val = std::get_if(&node.v)) { - result.put(uint8_t(val->op)); - result.put(uint8_t(val->lhs & 0xff)); - result.put(uint8_t((val->lhs >> 8) & 0xff)); - result.put(uint8_t(val->rhs & 0xff)); - result.put(uint8_t((val->rhs >> 8) & 0xff)); + result << uint8_t(val->op) << val->lhs << val->rhs; } else { std::unreachable(); } @@ -920,288 +1015,52 @@ std::u8string PreparedNodeState::dump() const { // Routes assert(Routes.size() < (1 << 16)); - v16 = Routes.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(Routes.size()); for(const auto& [nodeId, variants] : Routes) { - result.put(uint8_t(nodeId & 0xff)); - result.put(uint8_t((nodeId >> 8) & 0xff)); + result << nodeId; assert(variants.size() < (1 << 16)); - v16 = variants.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(variants.size()); for(const auto& [weight, model] : variants) { - union { - float f_val; - uint32_t i_val; - }; - - f_val = weight; - - for(int iter = 0; iter < 4; iter++) { - result.put((i_val >> 8*iter) & 0xff); - } - - result.put(uint8_t(model.index())); + result << weight << uint8_t(model.index()); + if(const Model* val = std::get_if(&model)) { - result.put(uint8_t(val->Id & 0xff)); - result.put(uint8_t((val->Id >> 8) & 0xff)); - - result.put(uint8_t(val->UVLock)); + result << val->Id << uint8_t(val->UVLock); assert(val->Transforms.size() < (1 << 16)); - v16 = val->Transforms.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(val->Transforms.size()); for(const Transformation& val : val->Transforms) { - result.put(uint8_t(val.Op)); - f_val = val.Value; - for(int iter = 0; iter < 4; iter++) - result.put((i_val >> 8*iter) & 0xff); + result << uint8_t(val.Op) << val.Value; } } else if(const VectorModel* val = std::get_if(&model)) { assert(val->Models.size() < (1 << 16)); - v16 = val->Models.size(); - for(const Model& subModel : val->Models) { - result.put(uint8_t(subModel.Id & 0xff)); - result.put(uint8_t((subModel.Id >> 8) & 0xff)); + result << uint16_t(val->Models.size()); - result.put(uint8_t(subModel.UVLock)); + for(const Model& subModel : val->Models) { + result << subModel.Id << uint8_t(subModel.UVLock); assert(subModel.Transforms.size() < (1 << 16)); - v16 = subModel.Transforms.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(subModel.Transforms.size()); - for(const Transformation& val : subModel.Transforms) { - result.put(uint8_t(val.Op)); - f_val = val.Value; - for(int iter = 0; iter < 4; iter++) - result.put((i_val >> 8*iter) & 0xff); - } + for(const Transformation& val : subModel.Transforms) + result << uint8_t(val.Op) << val.Value; } - result.put(uint8_t(val->UVLock)); + result << uint8_t(val->UVLock); assert(val->Transforms.size() < (1 << 16)); - v16 = val->Transforms.size(); - result.put(uint8_t(v16 & 0xff)); - result.put(uint8_t((v16 >> 8) & 0xff)); + result << uint16_t(val->Transforms.size()); - for(const Transformation& val : val->Transforms) { - result.put(uint8_t(val.Op)); - f_val = val.Value; - for(int iter = 0; iter < 4; iter++) - result.put((i_val >> 8*iter) & 0xff); - } + for(const Transformation& val : val->Transforms) + result << uint8_t(val.Op) << val.Value; } } } - return result.str(); -} - -bool PreparedNodeState::read_uint16(std::basic_istream& stream, uint16_t& value) noexcept { - char8_t lo, hi; - if (!(stream >> lo)) return false; - if (!(stream >> hi)) return false; - value = (static_cast(hi) << 8) | lo; - return true; -} - -bool PreparedNodeState::load(const std::u8string& data) noexcept { - // TODO: Это нейронка писала - - std::basic_istringstream stream(data); - char8_t byte; - uint16_t size, v16; - char8_t buffer[32]; - - // Читаем ResourceToLocalId - if (!read_uint16(stream, size)) return false; - ResourceToLocalId.clear(); - for (uint16_t i = 0; i < size; ++i) { - if (!(stream >> byte)) return false; - size_t domain_len = byte & 0xff; - if (domain_len >= 32) return false; - if (!stream.read(buffer, domain_len)) return false; - std::string domain((const char*) buffer, domain_len); - - if (!(stream >> byte)) return false; - size_t key_len = byte & 0xff; - if (key_len >= 32) return false; - if (!stream.read(buffer, key_len)) return false; - std::string key((const char*) buffer, key_len); - - ResourceToLocalId.emplace_back(std::move(domain), std::move(key)); - } - - // Читаем Nodes - if (!read_uint16(stream, size)) return false; - Nodes.clear(); - Nodes.reserve(size); - for (uint16_t i = 0; i < size; ++i) { - if (!(stream >> byte)) return false; - uint8_t tag = byte; - - Node node; - switch (tag) { - case 0: { // Node::Num - uint32_t val = 0; - for (int iter = 0; iter < 4; ++iter) { - if (!(stream >> byte)) return false; - val |= (static_cast(byte) << (8 * iter)); - } - node.v = Node::Num{ int32_t(val) }; - break; - } - case 1: { // Node::Var - if (!(stream >> byte)) return false; - size_t len = byte & 0xff; - if (len >= 32) return false; - if (!stream.read(buffer, len)) return false; - node.v = Node::Var{ std::string((const char*) buffer, len) }; - break; - } - case 2: { // Node::Unary - if (!(stream >> byte)) return false; - uint8_t op = byte; - if (!read_uint16(stream, v16)) return false; - node.v = Node::Unary{Op(op), v16}; - break; - } - case 3: { // Node::Binary - if (!(stream >> byte)) return false; - uint8_t op = byte; - if (!read_uint16(stream, v16)) return false; - uint16_t lhs = v16; - if (!read_uint16(stream, v16)) return false; - uint16_t rhs = v16; - node.v = Node::Binary{Op(op), lhs, rhs}; - break; - } - default: - return false; // неизвестный тип - } - Nodes.push_back(std::move(node)); - } - - // Читаем Routes - if (!read_uint16(stream, size)) return false; - Routes.clear(); - for (uint16_t i = 0; i < size; ++i) { - if (!read_uint16(stream, v16)) return false; - uint16_t nodeId = v16; - - if (!read_uint16(stream, size)) return false; - boost::container::small_vector>, 1> variants; - variants.reserve(size); - - for (uint16_t j = 0; j < size; ++j) { - // Читаем вес (float) - uint32_t f_bits = 0; - for (int iter = 0; iter < 4; ++iter) { - if (!(stream >> byte)) return false; - f_bits |= (static_cast(byte) << (8 * iter)); - } - float weight; - std::memcpy(&weight, &f_bits, 4); - - if (!(stream >> byte)) return false; - uint8_t model_tag = byte; - - if (model_tag == 0) { // Model - Model model; - if (!read_uint16(stream, v16)) return false; - model.Id = v16; - - if (!(stream >> byte)) return false; - model.UVLock = static_cast(byte & 1); - - if (!read_uint16(stream, v16)) return false; - model.Transforms.clear(); - for (uint16_t k = 0; k < v16; ++k) { - if (!(stream >> byte)) return false; - uint8_t op = byte; - - uint32_t val_bits = 0; - for (int iter = 0; iter < 4; ++iter) { - if (!(stream >> byte)) return false; - val_bits |= (static_cast(byte) << (8 * iter)); - } - float f_val; - std::memcpy(&f_val, &val_bits, 4); - - model.Transforms.emplace_back(Transformation::EnumTransform(op), f_val); - } - variants.emplace_back(weight, std::move(model)); - } else if (model_tag == 1) { // VectorModel - VectorModel vecModel; - if (!read_uint16(stream, v16)) return false; - size_t num_models = v16; - vecModel.Models.clear(); - vecModel.Models.reserve(num_models); - - for (size_t m = 0; m < num_models; ++m) { - Model subModel; - if (!read_uint16(stream, v16)) return false; - subModel.Id = v16; - - if (!(stream >> byte)) return false; - subModel.UVLock = static_cast(byte & 1); - - if (!read_uint16(stream, v16)) return false; - subModel.Transforms.clear(); - for (uint16_t k = 0; k < v16; ++k) { - if (!(stream >> byte)) return false; - uint8_t op = byte; - - uint32_t val_bits = 0; - for (int iter = 0; iter < 4; ++iter) { - if (!(stream >> byte)) return false; - val_bits |= (static_cast(byte) << (8 * iter)); - } - float f_val; - std::memcpy(&f_val, &val_bits, 4); - - subModel.Transforms.emplace_back(Transformation::EnumTransform(op), f_val); - } - vecModel.Models.push_back(std::move(subModel)); - } - - if (!(stream >> byte)) return false; - vecModel.UVLock = static_cast(byte & 1); - - if (!read_uint16(stream, v16)) return false; - vecModel.Transforms.clear(); - for (uint16_t k = 0; k < v16; ++k) { - if (!(stream >> byte)) return false; - uint8_t op = byte; - - uint32_t val_bits = 0; - for (int iter = 0; iter < 4; ++iter) { - if (!(stream >> byte)) return false; - val_bits |= (static_cast(byte) << (8 * iter)); - } - float f_val; - std::memcpy(&f_val, &val_bits, 4); - - vecModel.Transforms.emplace_back(Transformation::EnumTransform(op), f_val); - } - variants.emplace_back(weight, std::move(vecModel)); - } else { - return false; // неизвестный тип модели - } - } - - Routes.emplace_back(nodeId, std::move(variants)); - } - - return true; + return result.complite(); } uint16_t PreparedNodeState::parseCondition(const std::string_view expression) { @@ -1905,121 +1764,233 @@ PreparedModel::PreparedModel(const std::string_view modid, const sol::table& pro std::unreachable(); } -PreparedModel::PreparedModel(const std::string_view modid, const std::u8string& data) { - std::unreachable(); +PreparedModel::PreparedModel(const std::u8string& data) { + Net::LinearReader lr(data); + + if(lr.read()) { + std::string domain, key; + lr >> domain >> key; + Parent.emplace(std::move(domain), std::move(key)); + } + + if(lr.read()) { + GuiLight = (EnumGuiLight) lr.read(); + } + + { + uint8_t val; + lr >> val; + + if(val == 2) + AmbientOcclusion = true; + else if(val == 1) + AmbientOcclusion = false; + else if(val != 0) + MAKE_ERROR("Ошибка формата данных"); + } + + uint16_t size; + lr >> size; + Display.reserve(size); + + for(int counter = 0; counter < size; counter++) { + std::string key; + lr >> key; + + FullTransformation tsf; + for(int iter = 0; iter < 3; iter++) + lr >> tsf.Rotation[iter]; + + for(int iter = 0; iter < 3; iter++) + lr >> tsf.Translation[iter]; + + for(int iter = 0; iter < 3; iter++) + lr >> tsf.Scale[iter]; + + Display.insert({key, tsf}); + } + + lr >> size; + Textures.reserve(size); + for(int counter = 0; counter < size; counter++) { + std::string tkey, domain, key; + lr >> tkey >> domain >> key; + Textures.insert({tkey, {std::move(domain), std::move(key)}}); + } + + lr >> size; + Cuboids.reserve(size); + for(int counter = 0; counter < size; counter++) { + Cuboid cuboid; + cuboid.Shade = lr.read(); + + for(int iter = 0; iter < 3; iter++) + lr >> cuboid.From[iter]; + + for(int iter = 0; iter < 3; iter++) + lr >> cuboid.To[iter]; + + uint16_t facesSize; + lr >> facesSize; + cuboid.Faces.reserve(facesSize); + + for(int counter2 = 0; counter2 < facesSize; counter2++) { + Cuboid::Face face; + uint8_t type; + lr >> type; + + for(int iter = 0; iter < 4; iter++) + lr >> face.UV[iter]; + + lr >> face.Texture; + uint8_t val = lr.read(); + if(val != uint8_t(-1)) { + face.Cullface = Cuboid::EnumFace(val); + } + + lr >> face.TintIndex >> face.Rotation; + + cuboid.Faces.insert({(Cuboid::EnumFace) type, face}); + } + + uint16_t transformationsSize; + lr >> transformationsSize; + cuboid.Transformations.reserve(transformationsSize); + + for(int counter2 = 0; counter2 < transformationsSize; counter2++) { + Cuboid::Transformation tsf; + tsf.Op = (Cuboid::Transformation::EnumTransform) lr.read(); + lr >> tsf.Value; + cuboid.Transformations.emplace_back(tsf); + } + + Cuboids.emplace_back(std::move(cuboid)); + } + + lr >> size; + GLTF.reserve(size); + for(int counter = 0; counter < size; counter++) { + SubGLTF sub; + lr >> sub.Domain >> sub.Key; + uint16_t val = lr.read(); + if(val != uint16_t(-1)) { + sub.Scene = val; + } + + GLTF.push_back(std::move(sub)); + } } std::u8string PreparedModel::dump() const { - std::basic_ostringstream result; - - uint16_t val; - - auto push16 = [&]() { - result.put(uint8_t(val & 0xff)); - result.put(uint8_t((val >> 8) & 0xff)); - }; + Net::Packet result; if(Parent.has_value()) { - result.put(1); + result << uint8_t(1); assert(Parent->first.size() < 32); - val = Parent->first.size(); - push16(); - result.write((const char8_t*) Parent->first.data(), val); + result << Parent->first; assert(Parent->second.size() < 32); - val = Parent->second.size(); - push16(); - result.write((const char8_t*) Parent->second.data(), val); + result << Parent->second; } else { - result.put(0); + result << uint8_t(0); } if(GuiLight.has_value()) { - result.put(1); - result.put(int(GuiLight.value())); + result << uint8_t(1); + result << uint8_t(GuiLight.value()); } else - result.put(0); + result << uint8_t(0); if(AmbientOcclusion.has_value()) { if(*AmbientOcclusion) - result.put(2); + result << uint8_t(2); else - result.put(1); + result << uint8_t(1); } else - result.put(0); + result << uint8_t(0); assert(Display.size() < (1 << 16)); - val = Display.size(); - push16(); - - union { - float f_value; - uint32_t u_value; - }; + result << uint16_t(Display.size()); for(const auto& [key, tsf] : Display) { assert(key.size() < (1 << 16)); - val = key.size(); - push16(); - result.write((const char8_t*) key.data(), val); + result << key; - for(int iter = 0; iter < 3; iter++) { - f_value = tsf.Rotation[iter]; + for(int iter = 0; iter < 3; iter++) + result << tsf.Rotation[iter]; - for(int iter2 = 0; iter2 < 4; iter2++) { - result.put(uint8_t((u_value >> (iter2*8)) & 0xff)); - } - } + for(int iter = 0; iter < 3; iter++) + result << tsf.Translation[iter]; - for(int iter = 0; iter < 3; iter++) { - f_value = tsf.Translation[iter]; - - for(int iter2 = 0; iter2 < 4; iter2++) { - result.put(uint8_t((u_value >> (iter2*8)) & 0xff)); - } - } - - for(int iter = 0; iter < 3; iter++) { - f_value = tsf.Scale[iter]; - - for(int iter2 = 0; iter2 < 4; iter2++) { - result.put(uint8_t((u_value >> (iter2*8)) & 0xff)); - } - } + for(int iter = 0; iter < 3; iter++) + result << tsf.Scale[iter]; } assert(Textures.size() < (1 << 16)); - val = Textures.size(); - push16(); + result << uint16_t(Textures.size()); for(const auto& [tkey, dk] : Textures) { assert(tkey.size() < 32); - val = tkey.size(); - push16(); - result.write((const char8_t*) tkey.data(), val); + result << tkey; assert(dk.first.size() < 32); - val = dk.first.size(); - push16(); - result.write((const char8_t*) dk.first.data(), val); + result << dk.first; assert(dk.second.size() < 32); - val = dk.second.size(); - push16(); - result.write((const char8_t*) dk.second.data(), val); + result << dk.second; } assert(Cuboids.size() < (1 << 16)); - val = Cuboids.size(); - push16(); + result << uint16_t(Cuboids.size()); - for(const Cub) + for(const Cuboid& cuboid : Cuboids) { + result << uint8_t(cuboid.Shade); - // Cuboids - // GLTF + for(int iter = 0; iter < 3; iter++) + result << cuboid.From[iter]; - return result.str(); + for(int iter = 0; iter < 3; iter++) + result << cuboid.To[iter]; + + assert(cuboid.Faces.size() < 7); + result << uint8_t(cuboid.Faces.size()); + for(const auto& [type, face] : cuboid.Faces) { + result << uint8_t(type); + + for(int iter = 0; iter < 4; iter++) + result << face.UV[iter]; + + result << face.Texture; + if(face.Cullface) + result << uint8_t(*face.Cullface); + else + result << uint8_t(-1); + + result << face.TintIndex << face.Rotation; + } + + assert(cuboid.Transformations.size() < 256); + result << uint8_t(cuboid.Transformations.size()); + for(const auto& [op, value] : cuboid.Transformations) { + result << uint8_t(op) << value; + } + } + + assert(GLTF.size() < 256); + result << uint8_t(GLTF.size()); + for(const SubGLTF& gltf : GLTF) { + assert(gltf.Domain.size() < 32); + assert(gltf.Key.size() < 32); + + result << gltf.Domain << gltf.Key; + if(gltf.Scene) + result << uint16_t(*gltf.Scene); + else + result << uint16_t(-1); + } + + return result.complite(); } } \ No newline at end of file diff --git a/Src/Common/Abstract.hpp b/Src/Common/Abstract.hpp index cf28f57..c065126 100644 --- a/Src/Common/Abstract.hpp +++ b/Src/Common/Abstract.hpp @@ -1,12 +1,9 @@ #pragma once -#include "Common/Net.hpp" #include "TOSLib.hpp" #include "boost/json/array.hpp" -#include #include #include -#include #include #include #include @@ -571,7 +568,7 @@ struct PreparedNodeState { PreparedNodeState(const std::string_view modid, const js::object& profile); PreparedNodeState(const std::string_view modid, const sol::table& profile); - PreparedNodeState(const std::string_view modid, const std::u8string& data); + PreparedNodeState(const std::u8string& data); PreparedNodeState() = default; PreparedNodeState(const PreparedNodeState&) = default; @@ -590,8 +587,6 @@ struct PreparedNodeState { private: bool HasVariability = false; - static bool read_uint16(std::basic_istream& stream, uint16_t& value) noexcept; - bool load(const std::u8string& data) noexcept; uint16_t parseCondition(const std::string_view condition); std::pair> parseModel(const std::string_view modid, const js::object& obj); std::vector parseTransormations(const js::array& arr); @@ -662,7 +657,7 @@ struct PreparedModel { // Json PreparedModel(const std::string_view modid, const js::object& profile); PreparedModel(const std::string_view modid, const sol::table& profile); - PreparedModel(const std::string_view modid, const std::u8string& data); + PreparedModel(const std::u8string& data); PreparedModel() = default; PreparedModel(const PreparedModel&) = default; diff --git a/Src/Common/Net.hpp b/Src/Common/Net.hpp index a5972c5..fe49678 100644 --- a/Src/Common/Net.hpp +++ b/Src/Common/Net.hpp @@ -7,13 +7,12 @@ #include "Async.hpp" #include "TOSLib.hpp" -#include #include #include #include #include #include -#include +#include namespace LV::Net { @@ -40,10 +39,10 @@ protected: }; #if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN - template , int> = 0> + template or std::is_integral_v, int> = 0> static inline T swapEndian(const T &u) { return u; } #else - template , int> = 0> + template or std::is_integral_v, int> = 0> static inline T swapEndian(const T &u) { if constexpr (sizeof(T) == 1) { return u; @@ -65,7 +64,7 @@ protected: using NetPool = BoostPool<12, 14>; class Packet { - static constexpr size_t MAX_PACKET_SIZE = 1 << 16; + static constexpr size_t MAX_PACKET_SIZE = 1 << 24; uint16_t Size = 0; std::vector Pages; @@ -109,7 +108,7 @@ protected: return *this; } - template, int> = 0> + template || std::is_floating_point_v, int> = 0> inline Packet& write(T u) { u = swapEndian(u); write((const std::byte*) &u, sizeof(u)); @@ -130,7 +129,7 @@ protected: inline uint16_t size() const { return Size; } inline const std::vector& getPages() const { return Pages; } - template or std::is_convertible_v, int> = 0> + template || std::is_integral_v or std::is_convertible_v, int> = 0> inline Packet& operator<<(const T &value) { if constexpr (std::is_convertible_v) return write((std::string_view) value); @@ -147,7 +146,7 @@ protected: Size = 0; } - Packet& complite(std::vector &out) { + Packet& complite(std::u8string &out) { out.resize(Size); for(size_t pos = 0; pos < Size; pos += NetPool::PageSize) { @@ -158,8 +157,8 @@ protected: return *this; } - std::vector complite() { - std::vector out; + std::u8string complite() { + std::u8string out; complite(out); return out; } @@ -175,6 +174,61 @@ protected: } }; + class LinearReader { + public: + LinearReader(const std::u8string& input, size_t pos = 0) + : Pos(pos), Input(input) + {} + + LinearReader(const LinearReader&) = delete; + LinearReader(LinearReader&&) = delete; + LinearReader& operator=(const LinearReader&) = delete; + LinearReader& operator=(LinearReader&&) = delete; + + void read(std::byte *data, uint32_t size) { + if(Input.size()-Pos < size) + MAKE_ERROR("Недостаточно данных"); + + std::copy((const std::byte*) Input.data()+Pos, (const std::byte*) Input.data()+Pos+size, data); + Pos += size; + } + + template || std::is_integral_v or std::is_same_v, int> = 0> + T read() { + if constexpr(std::is_floating_point_v || std::is_integral_v) { + T value; + read((std::byte*) &value, sizeof(value)); + return swapEndian(value); + } else { + uint16_t size = read(); + T value(size, ' '); + read((std::byte*) value.data(), size); + return value; + } + } + + template + LinearReader& read(T& val) { + val = read(); + return *this; + } + + template + LinearReader& operator>>(T& val) { + val = read(); + return *this; + } + + void checkUnreaded() { + if(Pos != Input.size()) + MAKE_ERROR("Остались не использованные данные"); + } + + private: + size_t Pos = 0; + const std::u8string& Input; + }; + class SmartPacket : public Packet { public: std::function IsStillRelevant; @@ -221,7 +275,7 @@ protected: boost::asio::socket_base::linger optionLinger(true, 4); // После закрытия сокета оставшиеся данные будут доставлены Socket.set_option(optionLinger); - boost::asio::ip::tcp::no_delay optionNoDelay(true); // Отключает попытки объёденить данные в крупные пакеты + boost::asio::ip::tcp::no_delay optionNoDelay(true); // Отключает попытки объединить данные в крупные пакеты Socket.set_option(optionNoDelay); co_spawn(runSender(SendPackets.Context)); @@ -243,9 +297,9 @@ protected: coro<> read(std::byte *data, uint32_t size); void closeRead(); - template or std::is_same_v, int> = 0> + template or std::is_integral_v or std::is_same_v, int> = 0> coro read() { - if constexpr(std::is_integral_v) { + if constexpr(std::is_floating_point_v or std::is_integral_v) { T value; co_await read((std::byte*) &value, sizeof(value)); co_return swapEndian(value); @@ -263,9 +317,9 @@ protected: co_await asio::async_read(socket, asio::mutable_buffer(data, size)); } - template or std::is_same_v, int> = 0> + template or std::is_integral_v or std::is_same_v, int> = 0> static inline coro read(tcp::socket &socket) { - if constexpr(std::is_integral_v) { + if constexpr(std::is_floating_point_v or std::is_integral_v) { T value; co_await read(socket, (std::byte*) &value, sizeof(value)); co_return swapEndian(value); @@ -280,7 +334,7 @@ protected: co_await asio::async_write(socket, asio::const_buffer(data, size)); } - template, int> = 0> + template or std::is_integral_v, int> = 0> static inline coro<> write(tcp::socket &socket, T u) { u = swapEndian(u); co_await write(socket, (const std::byte*) &u, sizeof(u)); diff --git a/Src/Server/AssetsManager.hpp b/Src/Server/AssetsManager.hpp index 8b004b0..05f79ad 100644 --- a/Src/Server/AssetsManager.hpp +++ b/Src/Server/AssetsManager.hpp @@ -1,10 +1,9 @@ #pragma once -#include "Abstract.hpp" #include "Common/Abstract.hpp" #include "TOSLib.hpp" +#include "Common/Net.hpp" #include "assets.hpp" -#include "boost/asio/io_context.hpp" #include "sha2.hpp" #include #include