245 lines
5.7 KiB
C++
245 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <boost/asio.hpp>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <glm/vec2.hpp>
|
|
#include <glm/vec3.hpp>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <memory>
|
|
|
|
#include "spdlog/spdlog.h"
|
|
|
|
namespace commons {
|
|
|
|
static constexpr size_t screen_size = 30;
|
|
|
|
namespace protocol {
|
|
struct vec2;
|
|
struct pixel;
|
|
} // namespace protocol
|
|
|
|
class render_interface {
|
|
public:
|
|
virtual ~render_interface() = default;
|
|
virtual void update_pixel(commons::protocol::vec2 position,
|
|
commons::protocol::pixel pixel) = 0;
|
|
virtual void update_rect(commons::protocol::vec2 position,
|
|
commons::protocol::vec2 width,
|
|
commons::protocol::pixel pixel) = 0;
|
|
virtual void draw() = 0;
|
|
};
|
|
|
|
namespace protocol {
|
|
|
|
enum class Type {
|
|
DRAW_RECTANGLE = 0,
|
|
DRAW_PIXEL,
|
|
DRAW,
|
|
};
|
|
|
|
class generic_message_base
|
|
: std::enable_shared_from_this<generic_message_base> {
|
|
public:
|
|
virtual ~generic_message_base() = default;
|
|
virtual constexpr Type get_type() const = 0;
|
|
virtual uint32_t get_size() const = 0;
|
|
|
|
auto get_shared_ptr() { return shared_from_this(); }
|
|
|
|
auto serialize() const {
|
|
const auto* void_ptr = reinterpret_cast<const void*>(this);
|
|
return boost::asio::buffer(void_ptr, get_size());
|
|
}
|
|
|
|
virtual void operator()() {
|
|
if (is_handler) {
|
|
handle_message();
|
|
return;
|
|
}
|
|
|
|
create_message();
|
|
}
|
|
|
|
virtual void handle_message() = 0;
|
|
virtual void handle_message(render_interface* renderer){};
|
|
virtual void create_message() {
|
|
spdlog::debug("create_message is not implemented yet");
|
|
}
|
|
|
|
virtual void handle_sent(const boost::system::error_code& er) {
|
|
if (!er) {
|
|
spdlog::debug("size {}", get_size());
|
|
std::cout << "MSG WAS SNT \n";
|
|
spdlog::debug("Message was sent");
|
|
} else {
|
|
spdlog::error("Error occured on client::send");
|
|
}
|
|
}
|
|
|
|
protected:
|
|
bool is_handler = true;
|
|
};
|
|
|
|
class draw_rectangle;
|
|
|
|
template <Type TypeValue>
|
|
class generic_message : public generic_message_base {
|
|
public:
|
|
virtual ~generic_message() = default;
|
|
virtual constexpr Type get_type() const override { return type_; }
|
|
|
|
protected:
|
|
static constexpr Type type_ = TypeValue;
|
|
};
|
|
|
|
inline std::unique_ptr<generic_message_base> deserialize(
|
|
char* buffer, std::size_t object_size) {
|
|
void* base_ptr = std::malloc(object_size);
|
|
std::memcpy(base_ptr, buffer, object_size);
|
|
|
|
return std::unique_ptr<generic_message_base>(
|
|
reinterpret_cast<generic_message_base*>(base_ptr));
|
|
}
|
|
|
|
struct vec2 {
|
|
int x, y;
|
|
};
|
|
|
|
struct vec3 {
|
|
int x, y, z;
|
|
};
|
|
|
|
enum class background_color {
|
|
BLACK = 40,
|
|
RED,
|
|
GREEN,
|
|
YELlOW,
|
|
BLUE,
|
|
MAGENTA,
|
|
CYAN,
|
|
WHITE,
|
|
};
|
|
|
|
enum class foreground_color {
|
|
BLACK = 30,
|
|
RED,
|
|
GREEN,
|
|
YELlOW,
|
|
BLUE,
|
|
MAGENTA,
|
|
CYAN,
|
|
WHITE,
|
|
};
|
|
|
|
struct pixel {
|
|
char value = ' ';
|
|
foreground_color color_fg = foreground_color::GREEN;
|
|
background_color color_bg = background_color::BLACK;
|
|
};
|
|
|
|
class draw_rectangle : public generic_message<Type::DRAW_RECTANGLE> {
|
|
public:
|
|
virtual ~draw_rectangle() = default;
|
|
|
|
virtual uint32_t get_size() const override { return sizeof(*this); }
|
|
|
|
virtual void handle_message() override {
|
|
spdlog::debug("draw_rectangle::handle_message()");
|
|
spdlog::debug("Position: X = {}, Y = {}", position.x, position.y);
|
|
spdlog::debug("handle_message sleeps for 1 sec to test concurrency");
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
|
|
virtual void handle_message(render_interface* renderer) override {
|
|
renderer->update_rect(position, size, pixel_);
|
|
}
|
|
|
|
vec2 position;
|
|
vec2 size;
|
|
pixel pixel_;
|
|
};
|
|
|
|
class draw_pixel : public generic_message<Type::DRAW_PIXEL> {
|
|
public:
|
|
virtual ~draw_pixel() = default;
|
|
|
|
virtual uint32_t get_size() const override { return sizeof(*this); }
|
|
|
|
virtual void handle_message() override {
|
|
spdlog::debug("draw_pixel::handle_message()");
|
|
spdlog::debug("Color: ({}, {}, {})", color.x, color.y, color.z);
|
|
spdlog::debug("handle_message sleeps for 1 sec to test concurrency");
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
|
|
virtual void handle_message(render_interface* renderer) override {
|
|
renderer->update_pixel(position, pixel_);
|
|
}
|
|
|
|
vec2 position;
|
|
pixel pixel_;
|
|
vec3 color;
|
|
};
|
|
|
|
class draw : public generic_message<Type::DRAW> {
|
|
public:
|
|
virtual ~draw() = default;
|
|
|
|
virtual uint32_t get_size() const override { return sizeof(*this); }
|
|
|
|
virtual void handle_message() override {}
|
|
|
|
virtual void handle_message(render_interface* renderer) override {
|
|
renderer->draw();
|
|
}
|
|
};
|
|
|
|
class Serializer {};
|
|
|
|
} // namespace protocol
|
|
|
|
class cli_renderer : public render_interface {
|
|
public:
|
|
cli_renderer(size_t screen_size)
|
|
: size_(screen_size),
|
|
screen_{screen_size, std::vector<protocol::pixel>{screen_size}} {}
|
|
|
|
virtual ~cli_renderer() = default;
|
|
|
|
virtual void update_pixel(protocol::vec2 position,
|
|
protocol::pixel pixel) override {
|
|
screen_[position.y][position.x] = pixel;
|
|
}
|
|
|
|
virtual void update_rect(protocol::vec2 position, protocol::vec2 width,
|
|
protocol::pixel pixel) override {
|
|
for (int y = position.y; y < size_ && y < width.y + position.y; ++y) {
|
|
for (int x = position.x; x < size_ && x < width.x + position.x; ++x)
|
|
update_pixel(protocol::vec2{x, y}, pixel);
|
|
}
|
|
}
|
|
|
|
virtual void draw() override {
|
|
std::stringstream str;
|
|
for (const auto& row : screen_) {
|
|
for (const auto& pixel : row) {
|
|
str << "\033[" << static_cast<size_t>(pixel.color_fg) << ";"
|
|
<< static_cast<size_t>(pixel.color_bg) << "m" << pixel.value;
|
|
}
|
|
str << "\033[30;40m\n";
|
|
}
|
|
|
|
str << "\033[30;40m\n";
|
|
std::cout << str.str() << '\n';
|
|
}
|
|
|
|
private:
|
|
size_t size_;
|
|
std::vector<std::vector<protocol::pixel>> screen_;
|
|
};
|
|
|
|
} // namespace commons
|