249 lines
6.6 KiB
C++
249 lines
6.6 KiB
C++
#include "net_msg.hpp"
|
|
|
|
#include <array>
|
|
|
|
#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<short>(std::round(f * 8)));
|
|
}
|
|
|
|
void msg::write_hires_coord(const float f) {
|
|
write_short(static_cast<short>(f));
|
|
write_byte(static_cast<int>(f * 255) % 255);
|
|
}
|
|
|
|
std::optional<float> msg::read_lores_coord() {
|
|
const auto c = read_short();
|
|
|
|
if (!c.has_value()) {
|
|
return std::nullopt;
|
|
}
|
|
|
|
return c.value() * (1.0 / 8);
|
|
}
|
|
|
|
std::optional<float> 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<std::int32_t>(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<rmq_flags>(static_cast<int>(lhs) & static_cast<int>(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<int>(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<int>(std::round(f * 65536.0 / 360.0));
|
|
write_short(static_cast<short>(rounded & 65535));
|
|
} else {
|
|
const auto rounded = static_cast<int>(std::round(f * 256.0 / 360.0));
|
|
write_byte(static_cast<std::uint8_t>(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<int>(std::round(f * 65536.0 / 360.0));
|
|
write_short(static_cast<short>(rounded & 65535));
|
|
}
|
|
}
|
|
|
|
void msg::begin_reading() {
|
|
_offset = 0;
|
|
_eos = false;
|
|
}
|
|
|
|
std::optional<char> msg::read_char() {
|
|
if (_eos || _offset + 1 > _data.size()) {
|
|
_eos = true;
|
|
return std::nullopt;
|
|
}
|
|
|
|
return static_cast<signed char>(_data[_offset++]);
|
|
}
|
|
|
|
std::optional<std::uint8_t> msg::read_byte() {
|
|
if (_eos || _offset + 1 > _data.size()) {
|
|
_eos = true;
|
|
return std::nullopt;
|
|
}
|
|
|
|
return _data[_offset++];
|
|
}
|
|
|
|
std::optional<short> msg::read_short() {
|
|
if (_eos || _offset + 2 > _data.size()) {
|
|
_eos = true;
|
|
return std::nullopt;
|
|
}
|
|
|
|
auto res = static_cast<short>(_data[_offset] + (_data[_offset + 1] << 8));
|
|
|
|
_offset += 2;
|
|
|
|
return res;
|
|
}
|
|
|
|
std::optional<int> 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<float> msg::read_float() {
|
|
if (_eos || _offset + 4 > _data.size()) {
|
|
_eos = true;
|
|
return std::nullopt;
|
|
}
|
|
|
|
auto res = std::bit_cast<float>(read_long().value());
|
|
|
|
return res;
|
|
}
|
|
|
|
std::optional<std::string> 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<float> 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<float> 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<float> 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]);
|
|
}
|
|
}
|
|
}
|