*
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
#include "Abstract.hpp"
|
#include "Abstract.hpp"
|
||||||
|
#include "Common/Net.hpp"
|
||||||
#include "TOSLib.hpp"
|
#include "TOSLib.hpp"
|
||||||
#include "boost/json.hpp"
|
#include "boost/json.hpp"
|
||||||
#include "boost/json/array.hpp"
|
|
||||||
#include "boost/json/object.hpp"
|
|
||||||
#include "boost/json/string_view.hpp"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/iostreams/filtering_streambuf.hpp>
|
#include <boost/iostreams/filtering_streambuf.hpp>
|
||||||
#include <boost/iostreams/copy.hpp>
|
#include <boost/iostreams/copy.hpp>
|
||||||
@@ -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<uint8_t>();
|
||||||
|
Node node;
|
||||||
|
|
||||||
|
switch(index) {
|
||||||
|
case 0: node.v = Node::Num(lr.read<int>()); break;
|
||||||
|
case 1: node.v = Node::Var(lr.read<std::string>()); break;
|
||||||
|
case 2: {
|
||||||
|
Node::Unary unary;
|
||||||
|
unary.op = Op(lr.read<uint8_t>());
|
||||||
|
unary.rhs = lr.read<uint16_t>();
|
||||||
|
node.v = unary;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
Node::Binary binary;
|
||||||
|
binary.op = Op(lr.read<uint8_t>());
|
||||||
|
binary.lhs = lr.read<uint16_t>();
|
||||||
|
binary.rhs = lr.read<uint16_t>();
|
||||||
|
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<float, std::variant<Model, VectorModel>>,
|
||||||
|
1
|
||||||
|
> variants;
|
||||||
|
variants.reserve(variantsSize);
|
||||||
|
|
||||||
|
for(int counter2 = 0; counter2 < variantsSize; counter2++) {
|
||||||
|
float weight;
|
||||||
|
lr >> weight;
|
||||||
|
|
||||||
|
if(lr.read<uint8_t>()) {
|
||||||
|
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<uint8_t>();
|
||||||
|
|
||||||
|
uint16_t transformsSize;
|
||||||
|
lr >> transformsSize;
|
||||||
|
|
||||||
|
mod2.Transforms.reserve(transformsSize);
|
||||||
|
for(int counter4 = 0; counter4 < transformsSize; counter4++) {
|
||||||
|
Transformation tr;
|
||||||
|
tr.Op = Transformation::EnumTransform(lr.read<uint8_t>());
|
||||||
|
mod2.Transforms.push_back(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.UVLock = lr.read<uint8_t>();
|
||||||
|
|
||||||
|
uint16_t transformsSize;
|
||||||
|
lr >> transformsSize;
|
||||||
|
|
||||||
|
mod.Transforms.reserve(transformsSize);
|
||||||
|
for(int counter3 = 0; counter3 < transformsSize; counter3++) {
|
||||||
|
Transformation tr;
|
||||||
|
tr.Op = Transformation::EnumTransform(lr.read<uint8_t>());
|
||||||
|
mod.Transforms.push_back(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
variants.emplace_back(weight, std::move(mod));
|
||||||
|
} else {
|
||||||
|
Model mod;
|
||||||
|
lr >> mod.Id;
|
||||||
|
mod.UVLock = lr.read<uint8_t>();
|
||||||
|
uint16_t transformsSize;
|
||||||
|
lr >> transformsSize;
|
||||||
|
|
||||||
|
mod.Transforms.reserve(transformsSize);
|
||||||
|
for(int counter3 = 0; counter3 < transformsSize; counter3++) {
|
||||||
|
Transformation tr;
|
||||||
|
tr.Op = Transformation::EnumTransform(lr.read<uint8_t>());
|
||||||
|
mod.Transforms.push_back(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
variants.emplace_back(weight, std::move(mod));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u8string PreparedNodeState::dump() const {
|
std::u8string PreparedNodeState::dump() const {
|
||||||
std::basic_stringstream<char8_t> result;
|
Net::Packet result;
|
||||||
uint16_t v16;
|
|
||||||
|
|
||||||
// ResourceToLocalId
|
// ResourceToLocalId
|
||||||
assert(ResourceToLocalId.size() < (1 << 16));
|
assert(ResourceToLocalId.size() < (1 << 16));
|
||||||
v16 = ResourceToLocalId.size();
|
result << uint16_t(ResourceToLocalId.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const auto& [domain, key] : ResourceToLocalId) {
|
for(const auto& [domain, key] : ResourceToLocalId) {
|
||||||
assert(domain.size() < 32);
|
assert(domain.size() < 32);
|
||||||
result.put(uint8_t(domain.size() & 0xff));
|
result << domain;
|
||||||
result << (const std::u8string&) domain;
|
|
||||||
assert(key.size() < 32);
|
assert(key.size() < 32);
|
||||||
result.put(uint8_t(key.size() & 0xff));
|
result << key;
|
||||||
result << (const std::u8string&) key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
assert(Nodes.size() < (1 << 16));
|
assert(Nodes.size() < (1 << 16));
|
||||||
v16 = Nodes.size();
|
result << uint16_t(Nodes.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const Node& node : Nodes) {
|
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::Num>(&node.v)) {
|
if(const Node::Num* val = std::get_if<Node::Num>(&node.v)) {
|
||||||
for(int iter = 0; iter < 4; iter++) {
|
result << val->v;
|
||||||
result.put((val->v >> 8*iter) & 0xff);
|
|
||||||
}
|
|
||||||
} else if(const Node::Var* val = std::get_if<Node::Var>(&node.v)) {
|
} else if(const Node::Var* val = std::get_if<Node::Var>(&node.v)) {
|
||||||
assert(val->name.size() < 32);
|
assert(val->name.size() < 32);
|
||||||
result << (const std::u8string&) val->name;
|
result << val->name;
|
||||||
} else if(const Node::Unary* val = std::get_if<Node::Unary>(&node.v)) {
|
} else if(const Node::Unary* val = std::get_if<Node::Unary>(&node.v)) {
|
||||||
result.put(uint8_t(val->op));
|
result << uint8_t(val->op) << val->rhs;
|
||||||
result.put(uint8_t(val->rhs & 0xff));
|
|
||||||
result.put(uint8_t((val->rhs >> 8) & 0xff));
|
|
||||||
} else if(const Node::Binary* val = std::get_if<Node::Binary>(&node.v)) {
|
} else if(const Node::Binary* val = std::get_if<Node::Binary>(&node.v)) {
|
||||||
result.put(uint8_t(val->op));
|
result << uint8_t(val->op) << val->lhs << val->rhs;
|
||||||
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));
|
|
||||||
} else {
|
} else {
|
||||||
std::unreachable();
|
std::unreachable();
|
||||||
}
|
}
|
||||||
@@ -920,288 +1015,52 @@ std::u8string PreparedNodeState::dump() const {
|
|||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
assert(Routes.size() < (1 << 16));
|
assert(Routes.size() < (1 << 16));
|
||||||
v16 = Routes.size();
|
result << uint16_t(Routes.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const auto& [nodeId, variants] : Routes) {
|
for(const auto& [nodeId, variants] : Routes) {
|
||||||
result.put(uint8_t(nodeId & 0xff));
|
result << nodeId;
|
||||||
result.put(uint8_t((nodeId >> 8) & 0xff));
|
|
||||||
|
|
||||||
assert(variants.size() < (1 << 16));
|
assert(variants.size() < (1 << 16));
|
||||||
v16 = variants.size();
|
result << uint16_t(variants.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const auto& [weight, model] : variants) {
|
for(const auto& [weight, model] : variants) {
|
||||||
union {
|
result << weight << uint8_t(model.index());
|
||||||
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()));
|
|
||||||
if(const Model* val = std::get_if<Model>(&model)) {
|
if(const Model* val = std::get_if<Model>(&model)) {
|
||||||
result.put(uint8_t(val->Id & 0xff));
|
result << val->Id << uint8_t(val->UVLock);
|
||||||
result.put(uint8_t((val->Id >> 8) & 0xff));
|
|
||||||
|
|
||||||
result.put(uint8_t(val->UVLock));
|
|
||||||
|
|
||||||
assert(val->Transforms.size() < (1 << 16));
|
assert(val->Transforms.size() < (1 << 16));
|
||||||
v16 = val->Transforms.size();
|
result << uint16_t(val->Transforms.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const Transformation& val : val->Transforms) {
|
for(const Transformation& val : val->Transforms) {
|
||||||
result.put(uint8_t(val.Op));
|
result << uint8_t(val.Op) << val.Value;
|
||||||
f_val = val.Value;
|
|
||||||
for(int iter = 0; iter < 4; iter++)
|
|
||||||
result.put((i_val >> 8*iter) & 0xff);
|
|
||||||
}
|
}
|
||||||
} else if(const VectorModel* val = std::get_if<VectorModel>(&model)) {
|
} else if(const VectorModel* val = std::get_if<VectorModel>(&model)) {
|
||||||
assert(val->Models.size() < (1 << 16));
|
assert(val->Models.size() < (1 << 16));
|
||||||
v16 = val->Models.size();
|
result << uint16_t(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.put(uint8_t(subModel.UVLock));
|
for(const Model& subModel : val->Models) {
|
||||||
|
result << subModel.Id << uint8_t(subModel.UVLock);
|
||||||
|
|
||||||
assert(subModel.Transforms.size() < (1 << 16));
|
assert(subModel.Transforms.size() < (1 << 16));
|
||||||
v16 = subModel.Transforms.size();
|
result << uint16_t(subModel.Transforms.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const Transformation& val : subModel.Transforms) {
|
for(const Transformation& val : subModel.Transforms)
|
||||||
result.put(uint8_t(val.Op));
|
result << uint8_t(val.Op) << val.Value;
|
||||||
f_val = val.Value;
|
|
||||||
for(int iter = 0; iter < 4; iter++)
|
|
||||||
result.put((i_val >> 8*iter) & 0xff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.put(uint8_t(val->UVLock));
|
result << uint8_t(val->UVLock);
|
||||||
|
|
||||||
assert(val->Transforms.size() < (1 << 16));
|
assert(val->Transforms.size() < (1 << 16));
|
||||||
v16 = val->Transforms.size();
|
result << uint16_t(val->Transforms.size());
|
||||||
result.put(uint8_t(v16 & 0xff));
|
|
||||||
result.put(uint8_t((v16 >> 8) & 0xff));
|
|
||||||
|
|
||||||
for(const Transformation& val : val->Transforms) {
|
for(const Transformation& val : val->Transforms)
|
||||||
result.put(uint8_t(val.Op));
|
result << uint8_t(val.Op) << val.Value;
|
||||||
f_val = val.Value;
|
|
||||||
for(int iter = 0; iter < 4; iter++)
|
|
||||||
result.put((i_val >> 8*iter) & 0xff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.str();
|
return result.complite();
|
||||||
}
|
|
||||||
|
|
||||||
bool PreparedNodeState::read_uint16(std::basic_istream<char8_t>& stream, uint16_t& value) noexcept {
|
|
||||||
char8_t lo, hi;
|
|
||||||
if (!(stream >> lo)) return false;
|
|
||||||
if (!(stream >> hi)) return false;
|
|
||||||
value = (static_cast<uint16_t>(hi) << 8) | lo;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PreparedNodeState::load(const std::u8string& data) noexcept {
|
|
||||||
// TODO: Это нейронка писала
|
|
||||||
|
|
||||||
std::basic_istringstream<char8_t> 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<uint32_t>(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<std::pair<float, std::variant<Model, VectorModel>>, 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<uint32_t>(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<bool>(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<uint32_t>(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<bool>(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<uint32_t>(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<bool>(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<uint32_t>(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t PreparedNodeState::parseCondition(const std::string_view expression) {
|
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();
|
std::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
PreparedModel::PreparedModel(const std::string_view modid, const std::u8string& data) {
|
PreparedModel::PreparedModel(const std::u8string& data) {
|
||||||
std::unreachable();
|
Net::LinearReader lr(data);
|
||||||
|
|
||||||
|
if(lr.read<uint8_t>()) {
|
||||||
|
std::string domain, key;
|
||||||
|
lr >> domain >> key;
|
||||||
|
Parent.emplace(std::move(domain), std::move(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lr.read<uint8_t>()) {
|
||||||
|
GuiLight = (EnumGuiLight) lr.read<uint8_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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<uint8_t>();
|
||||||
|
|
||||||
|
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<uint8_t>();
|
||||||
|
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<uint8_t>();
|
||||||
|
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<uint16_t>();
|
||||||
|
if(val != uint16_t(-1)) {
|
||||||
|
sub.Scene = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTF.push_back(std::move(sub));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u8string PreparedModel::dump() const {
|
std::u8string PreparedModel::dump() const {
|
||||||
std::basic_ostringstream<char8_t> result;
|
Net::Packet result;
|
||||||
|
|
||||||
uint16_t val;
|
|
||||||
|
|
||||||
auto push16 = [&]() {
|
|
||||||
result.put(uint8_t(val & 0xff));
|
|
||||||
result.put(uint8_t((val >> 8) & 0xff));
|
|
||||||
};
|
|
||||||
|
|
||||||
if(Parent.has_value()) {
|
if(Parent.has_value()) {
|
||||||
result.put(1);
|
result << uint8_t(1);
|
||||||
|
|
||||||
assert(Parent->first.size() < 32);
|
assert(Parent->first.size() < 32);
|
||||||
val = Parent->first.size();
|
result << Parent->first;
|
||||||
push16();
|
|
||||||
result.write((const char8_t*) Parent->first.data(), val);
|
|
||||||
|
|
||||||
assert(Parent->second.size() < 32);
|
assert(Parent->second.size() < 32);
|
||||||
val = Parent->second.size();
|
result << Parent->second;
|
||||||
push16();
|
|
||||||
result.write((const char8_t*) Parent->second.data(), val);
|
|
||||||
} else {
|
} else {
|
||||||
result.put(0);
|
result << uint8_t(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GuiLight.has_value()) {
|
if(GuiLight.has_value()) {
|
||||||
result.put(1);
|
result << uint8_t(1);
|
||||||
result.put(int(GuiLight.value()));
|
result << uint8_t(GuiLight.value());
|
||||||
} else
|
} else
|
||||||
result.put(0);
|
result << uint8_t(0);
|
||||||
|
|
||||||
if(AmbientOcclusion.has_value()) {
|
if(AmbientOcclusion.has_value()) {
|
||||||
if(*AmbientOcclusion)
|
if(*AmbientOcclusion)
|
||||||
result.put(2);
|
result << uint8_t(2);
|
||||||
else
|
else
|
||||||
result.put(1);
|
result << uint8_t(1);
|
||||||
} else
|
} else
|
||||||
result.put(0);
|
result << uint8_t(0);
|
||||||
|
|
||||||
assert(Display.size() < (1 << 16));
|
assert(Display.size() < (1 << 16));
|
||||||
val = Display.size();
|
result << uint16_t(Display.size());
|
||||||
push16();
|
|
||||||
|
|
||||||
union {
|
|
||||||
float f_value;
|
|
||||||
uint32_t u_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
for(const auto& [key, tsf] : Display) {
|
for(const auto& [key, tsf] : Display) {
|
||||||
assert(key.size() < (1 << 16));
|
assert(key.size() < (1 << 16));
|
||||||
val = key.size();
|
result << key;
|
||||||
push16();
|
|
||||||
result.write((const char8_t*) key.data(), val);
|
|
||||||
|
|
||||||
for(int iter = 0; iter < 3; iter++) {
|
for(int iter = 0; iter < 3; iter++)
|
||||||
f_value = tsf.Rotation[iter];
|
result << tsf.Rotation[iter];
|
||||||
|
|
||||||
for(int iter2 = 0; iter2 < 4; iter2++) {
|
for(int iter = 0; iter < 3; iter++)
|
||||||
result.put(uint8_t((u_value >> (iter2*8)) & 0xff));
|
result << tsf.Translation[iter];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int iter = 0; iter < 3; iter++) {
|
for(int iter = 0; iter < 3; iter++)
|
||||||
f_value = tsf.Translation[iter];
|
result << 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++) {
|
|
||||||
f_value = tsf.Scale[iter];
|
|
||||||
|
|
||||||
for(int iter2 = 0; iter2 < 4; iter2++) {
|
|
||||||
result.put(uint8_t((u_value >> (iter2*8)) & 0xff));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Textures.size() < (1 << 16));
|
assert(Textures.size() < (1 << 16));
|
||||||
val = Textures.size();
|
result << uint16_t(Textures.size());
|
||||||
push16();
|
|
||||||
|
|
||||||
for(const auto& [tkey, dk] : Textures) {
|
for(const auto& [tkey, dk] : Textures) {
|
||||||
assert(tkey.size() < 32);
|
assert(tkey.size() < 32);
|
||||||
val = tkey.size();
|
result << tkey;
|
||||||
push16();
|
|
||||||
result.write((const char8_t*) tkey.data(), val);
|
|
||||||
|
|
||||||
assert(dk.first.size() < 32);
|
assert(dk.first.size() < 32);
|
||||||
val = dk.first.size();
|
result << dk.first;
|
||||||
push16();
|
|
||||||
result.write((const char8_t*) dk.first.data(), val);
|
|
||||||
|
|
||||||
assert(dk.second.size() < 32);
|
assert(dk.second.size() < 32);
|
||||||
val = dk.second.size();
|
result << dk.second;
|
||||||
push16();
|
|
||||||
result.write((const char8_t*) dk.second.data(), val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Cuboids.size() < (1 << 16));
|
assert(Cuboids.size() < (1 << 16));
|
||||||
val = Cuboids.size();
|
result << uint16_t(Cuboids.size());
|
||||||
push16();
|
|
||||||
|
|
||||||
for(const Cub)
|
for(const Cuboid& cuboid : Cuboids) {
|
||||||
|
result << uint8_t(cuboid.Shade);
|
||||||
|
|
||||||
// Cuboids
|
for(int iter = 0; iter < 3; iter++)
|
||||||
// GLTF
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common/Net.hpp"
|
|
||||||
#include "TOSLib.hpp"
|
#include "TOSLib.hpp"
|
||||||
#include "boost/json/array.hpp"
|
#include "boost/json/array.hpp"
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
#include <initializer_list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sol/forward.hpp>
|
#include <sol/forward.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -571,7 +568,7 @@ struct PreparedNodeState {
|
|||||||
|
|
||||||
PreparedNodeState(const std::string_view modid, const js::object& profile);
|
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 sol::table& profile);
|
||||||
PreparedNodeState(const std::string_view modid, const std::u8string& data);
|
PreparedNodeState(const std::u8string& data);
|
||||||
|
|
||||||
PreparedNodeState() = default;
|
PreparedNodeState() = default;
|
||||||
PreparedNodeState(const PreparedNodeState&) = default;
|
PreparedNodeState(const PreparedNodeState&) = default;
|
||||||
@@ -590,8 +587,6 @@ struct PreparedNodeState {
|
|||||||
private:
|
private:
|
||||||
bool HasVariability = false;
|
bool HasVariability = false;
|
||||||
|
|
||||||
static bool read_uint16(std::basic_istream<char8_t>& stream, uint16_t& value) noexcept;
|
|
||||||
bool load(const std::u8string& data) noexcept;
|
|
||||||
uint16_t parseCondition(const std::string_view condition);
|
uint16_t parseCondition(const std::string_view condition);
|
||||||
std::pair<float, std::variant<Model, VectorModel>> parseModel(const std::string_view modid, const js::object& obj);
|
std::pair<float, std::variant<Model, VectorModel>> parseModel(const std::string_view modid, const js::object& obj);
|
||||||
std::vector<Transformation> parseTransormations(const js::array& arr);
|
std::vector<Transformation> parseTransormations(const js::array& arr);
|
||||||
@@ -662,7 +657,7 @@ struct PreparedModel {
|
|||||||
// Json
|
// Json
|
||||||
PreparedModel(const std::string_view modid, const js::object& profile);
|
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 sol::table& profile);
|
||||||
PreparedModel(const std::string_view modid, const std::u8string& data);
|
PreparedModel(const std::u8string& data);
|
||||||
|
|
||||||
PreparedModel() = default;
|
PreparedModel() = default;
|
||||||
PreparedModel(const PreparedModel&) = default;
|
PreparedModel(const PreparedModel&) = default;
|
||||||
|
|||||||
@@ -7,13 +7,12 @@
|
|||||||
#include "Async.hpp"
|
#include "Async.hpp"
|
||||||
#include "TOSLib.hpp"
|
#include "TOSLib.hpp"
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include <condition_variable>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace LV::Net {
|
namespace LV::Net {
|
||||||
|
|
||||||
@@ -40,10 +39,10 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
|
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
|
template <typename T, std::enable_if_t<std::is_floating_point_v<T> or std::is_integral_v<T>, int> = 0>
|
||||||
static inline T swapEndian(const T &u) { return u; }
|
static inline T swapEndian(const T &u) { return u; }
|
||||||
#else
|
#else
|
||||||
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
|
template <typename T, std::enable_if_t<std::is_floating_point_v<T> or std::is_integral_v<T>, int> = 0>
|
||||||
static inline T swapEndian(const T &u) {
|
static inline T swapEndian(const T &u) {
|
||||||
if constexpr (sizeof(T) == 1) {
|
if constexpr (sizeof(T) == 1) {
|
||||||
return u;
|
return u;
|
||||||
@@ -65,7 +64,7 @@ protected:
|
|||||||
using NetPool = BoostPool<12, 14>;
|
using NetPool = BoostPool<12, 14>;
|
||||||
|
|
||||||
class Packet {
|
class Packet {
|
||||||
static constexpr size_t MAX_PACKET_SIZE = 1 << 16;
|
static constexpr size_t MAX_PACKET_SIZE = 1 << 24;
|
||||||
uint16_t Size = 0;
|
uint16_t Size = 0;
|
||||||
std::vector<NetPool::PagePtr> Pages;
|
std::vector<NetPool::PagePtr> Pages;
|
||||||
|
|
||||||
@@ -109,7 +108,7 @@ protected:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, int> = 0>
|
||||||
inline Packet& write(T u) {
|
inline Packet& write(T u) {
|
||||||
u = swapEndian(u);
|
u = swapEndian(u);
|
||||||
write((const std::byte*) &u, sizeof(u));
|
write((const std::byte*) &u, sizeof(u));
|
||||||
@@ -130,7 +129,7 @@ protected:
|
|||||||
inline uint16_t size() const { return Size; }
|
inline uint16_t size() const { return Size; }
|
||||||
inline const std::vector<NetPool::PagePtr>& getPages() const { return Pages; }
|
inline const std::vector<NetPool::PagePtr>& getPages() const { return Pages; }
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_convertible_v<T, std::string_view>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_floating_point_v<T> || std::is_integral_v<T> or std::is_convertible_v<T, std::string_view>, int> = 0>
|
||||||
inline Packet& operator<<(const T &value) {
|
inline Packet& operator<<(const T &value) {
|
||||||
if constexpr (std::is_convertible_v<T, std::string_view>)
|
if constexpr (std::is_convertible_v<T, std::string_view>)
|
||||||
return write((std::string_view) value);
|
return write((std::string_view) value);
|
||||||
@@ -147,7 +146,7 @@ protected:
|
|||||||
Size = 0;
|
Size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet& complite(std::vector<std::byte> &out) {
|
Packet& complite(std::u8string &out) {
|
||||||
out.resize(Size);
|
out.resize(Size);
|
||||||
|
|
||||||
for(size_t pos = 0; pos < Size; pos += NetPool::PageSize) {
|
for(size_t pos = 0; pos < Size; pos += NetPool::PageSize) {
|
||||||
@@ -158,8 +157,8 @@ protected:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::byte> complite() {
|
std::u8string complite() {
|
||||||
std::vector<std::byte> out;
|
std::u8string out;
|
||||||
complite(out);
|
complite(out);
|
||||||
return 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<typename T, std::enable_if_t<std::is_floating_point_v<T> || std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
||||||
|
T read() {
|
||||||
|
if constexpr(std::is_floating_point_v<T> || std::is_integral_v<T>) {
|
||||||
|
T value;
|
||||||
|
read((std::byte*) &value, sizeof(value));
|
||||||
|
return swapEndian(value);
|
||||||
|
} else {
|
||||||
|
uint16_t size = read<uint16_t>();
|
||||||
|
T value(size, ' ');
|
||||||
|
read((std::byte*) value.data(), size);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
LinearReader& read(T& val) {
|
||||||
|
val = read<T>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
LinearReader& operator>>(T& val) {
|
||||||
|
val = read<T>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkUnreaded() {
|
||||||
|
if(Pos != Input.size())
|
||||||
|
MAKE_ERROR("Остались не использованные данные");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t Pos = 0;
|
||||||
|
const std::u8string& Input;
|
||||||
|
};
|
||||||
|
|
||||||
class SmartPacket : public Packet {
|
class SmartPacket : public Packet {
|
||||||
public:
|
public:
|
||||||
std::function<bool()> IsStillRelevant;
|
std::function<bool()> IsStillRelevant;
|
||||||
@@ -221,7 +275,7 @@ protected:
|
|||||||
|
|
||||||
boost::asio::socket_base::linger optionLinger(true, 4); // После закрытия сокета оставшиеся данные будут доставлены
|
boost::asio::socket_base::linger optionLinger(true, 4); // После закрытия сокета оставшиеся данные будут доставлены
|
||||||
Socket.set_option(optionLinger);
|
Socket.set_option(optionLinger);
|
||||||
boost::asio::ip::tcp::no_delay optionNoDelay(true); // Отключает попытки объёденить данные в крупные пакеты
|
boost::asio::ip::tcp::no_delay optionNoDelay(true); // Отключает попытки объединить данные в крупные пакеты
|
||||||
Socket.set_option(optionNoDelay);
|
Socket.set_option(optionNoDelay);
|
||||||
|
|
||||||
co_spawn(runSender(SendPackets.Context));
|
co_spawn(runSender(SendPackets.Context));
|
||||||
@@ -243,9 +297,9 @@ protected:
|
|||||||
coro<> read(std::byte *data, uint32_t size);
|
coro<> read(std::byte *data, uint32_t size);
|
||||||
void closeRead();
|
void closeRead();
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_floating_point_v<T> or std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
||||||
coro<T> read() {
|
coro<T> read() {
|
||||||
if constexpr(std::is_integral_v<T>) {
|
if constexpr(std::is_floating_point_v<T> or std::is_integral_v<T>) {
|
||||||
T value;
|
T value;
|
||||||
co_await read((std::byte*) &value, sizeof(value));
|
co_await read((std::byte*) &value, sizeof(value));
|
||||||
co_return swapEndian(value);
|
co_return swapEndian(value);
|
||||||
@@ -263,9 +317,9 @@ protected:
|
|||||||
co_await asio::async_read(socket, asio::mutable_buffer(data, size));
|
co_await asio::async_read(socket, asio::mutable_buffer(data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_floating_point_v<T> or std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
||||||
static inline coro<T> read(tcp::socket &socket) {
|
static inline coro<T> read(tcp::socket &socket) {
|
||||||
if constexpr(std::is_integral_v<T>) {
|
if constexpr(std::is_floating_point_v<T> or std::is_integral_v<T>) {
|
||||||
T value;
|
T value;
|
||||||
co_await read(socket, (std::byte*) &value, sizeof(value));
|
co_await read(socket, (std::byte*) &value, sizeof(value));
|
||||||
co_return swapEndian(value);
|
co_return swapEndian(value);
|
||||||
@@ -280,7 +334,7 @@ protected:
|
|||||||
co_await asio::async_write(socket, asio::const_buffer(data, size));
|
co_await asio::async_write(socket, asio::const_buffer(data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_floating_point_v<T> or std::is_integral_v<T>, int> = 0>
|
||||||
static inline coro<> write(tcp::socket &socket, T u) {
|
static inline coro<> write(tcp::socket &socket, T u) {
|
||||||
u = swapEndian(u);
|
u = swapEndian(u);
|
||||||
co_await write(socket, (const std::byte*) &u, sizeof(u));
|
co_await write(socket, (const std::byte*) &u, sizeof(u));
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Abstract.hpp"
|
|
||||||
#include "Common/Abstract.hpp"
|
#include "Common/Abstract.hpp"
|
||||||
#include "TOSLib.hpp"
|
#include "TOSLib.hpp"
|
||||||
|
#include "Common/Net.hpp"
|
||||||
#include "assets.hpp"
|
#include "assets.hpp"
|
||||||
#include "boost/asio/io_context.hpp"
|
|
||||||
#include "sha2.hpp"
|
#include "sha2.hpp"
|
||||||
#include <boost/interprocess/file_mapping.hpp>
|
#include <boost/interprocess/file_mapping.hpp>
|
||||||
#include <boost/interprocess/mapped_region.hpp>
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user