#include "net_msg.hpp" #include #include "q_stdinc.hpp" #include "quakedef.hpp" #include "common.hpp" #include "mathlib.hpp" namespace net { void msg::write_lores_coord(const float f) { write_short(static_cast(std::round(f * 8))); } void msg::write_hires_coord(const float f) { write_short(static_cast(f)); write_byte(static_cast(f * 255) % 255); } std::optional msg::read_lores_coord() { const auto c = read_short(); if (!c.has_value()) { return std::nullopt; } return c.value() * (1.0 / 8); } std::optional msg::read_hires_coord() { const auto c = read_short(); const auto d = read_byte(); if (!c.has_value() || !d.has_value()) { return std::nullopt; } return c.value() + (d.value() * (1.0 / 255)); } void msg::clear() { _data.clear(); _eos = false; _offset = 0; } void msg::write_char(const char c) { _data.push_back(c); } void msg::write_byte(const std::uint8_t b) { _data.push_back(b); } void msg::write_short(const short s) { _data.push_back(s & 0xFF); _data.push_back((s >> 8) & 0xFF); } void msg::write_long(const int l) { _data.push_back(l & 0xFF); _data.push_back((l >> 8) & 0xFF); _data.push_back((l >> 16) & 0xFF); _data.push_back((l >> 24) & 0xFF); } void msg::write_float(const float f) { write_long(std::bit_cast(f)); } void msg::write_string(const std::string_view s) { if (!s.empty()) { for (const auto &c: s) { _data.push_back(c); } } _data.push_back('\0'); } static rmq_flags operator&(rmq_flags lhs, rmq_flags rhs) { return static_cast(static_cast(lhs) & static_cast(rhs)); } void msg::write_coord(const float f, const rmq_flags flags) { if ((flags & rmq_flags::float_coord) != rmq_flags::none) { write_float(f); } else if ((flags & rmq_flags::int_coord) != rmq_flags::none) { write_long(static_cast(std::round(f * 16))); } else if ((flags & rmq_flags::hires_coord) != rmq_flags::none) { write_hires_coord(f); } else { write_lores_coord(f); } } void msg::write_angle(const float f, const rmq_flags flags) { if ((flags & rmq_flags::float_angle) != rmq_flags::none) { write_float(f); } else if ((flags & rmq_flags::short_angle) != rmq_flags::none) { const auto rounded = static_cast(std::round(f * 65536.0 / 360.0)); write_short(static_cast(rounded & 65535)); } else { const auto rounded = static_cast(std::round(f * 256.0 / 360.0)); write_byte(static_cast(rounded & 255)); } } void msg::write_angle_16(const float f, const rmq_flags flags) { if ((flags & rmq_flags::float_angle) != rmq_flags::none) { write_float(f); } else { const auto rounded = static_cast(std::round(f * 65536.0 / 360.0)); write_short(static_cast(rounded & 65535)); } } void msg::begin_reading() { _offset = 0; _eos = false; } std::optional msg::read_char() { if (_eos || _offset + 1 > _data.size()) { _eos = true; return std::nullopt; } return static_cast(_data[_offset++]); } std::optional msg::read_byte() { if (_eos || _offset + 1 > _data.size()) { _eos = true; return std::nullopt; } return _data[_offset++]; } std::optional msg::read_short() { if (_eos || _offset + 2 > _data.size()) { _eos = true; return std::nullopt; } auto res = static_cast(_data[_offset] + (_data[_offset + 1] << 8)); _offset += 2; return res; } std::optional msg::read_long() { if (_eos || _offset + 4 > _data.size()) { _eos = true; return std::nullopt; } auto res = _data[_offset] + (_data[_offset + 1] << 8) + (_data[_offset + 2] << 16) + ( _data[_offset + 3] << 24); _offset += 4; return res; } std::optional msg::read_float() { if (_eos || _offset + 4 > _data.size()) { _eos = true; return std::nullopt; } auto res = std::bit_cast(read_long().value()); return res; } std::optional msg::read_string() { std::string res{}; if (_eos) { return std::nullopt; } do { auto c = read_char(); if (!c.has_value() || c.value() == 0) { break; } res += c.value(); } while (!_eos); return res; } std::optional msg::read_coord(const rmq_flags flags) { if ((flags & rmq_flags::float_coord) != rmq_flags::none) { return read_float(); } if ((flags & rmq_flags::int_coord) != rmq_flags::none) { const auto i = read_long(); if (!i.has_value()) { return std::nullopt; } return i.value() * (1.0 / 16.0); } if ((flags & rmq_flags::hires_coord) != rmq_flags::none) { return read_hires_coord(); } return read_lores_coord(); } std::optional msg::read_angle(const rmq_flags flags) { if ((flags & rmq_flags::float_angle) != rmq_flags::none) { return read_float(); } if ((flags & rmq_flags::short_angle) != rmq_flags::none) { auto a = read_short(); if (!a.has_value()) { return std::nullopt; } return a.value() * (360.0 / 65536); } const auto c = read_char(); if (!c.has_value()) { return std::nullopt; } return c.value() * (360.0 / 256); } std::optional msg::read_angle_16(rmq_flags flags) { if ((flags & rmq_flags::float_angle) != rmq_flags::none) { return read_float(); } const auto s = read_short(); if (!s.has_value()) { return std::nullopt; } return s.value() * (360.0 / 65536); } void msg::write(const std::uint8_t *data, std::size_t size) { for (auto i = 0; i < size; i++) { _data.push_back(data[i]); } } }