#ifndef _WORLD_HPP #define _WORLD_HPP #include "generic.pb.h" #include #include #include #include namespace Connection { class Client; class Global; } namespace World { class Room; void fillSettings(Generic::Settings& settings); struct Vector2 { float x, y; inline static Vector2 makeFromGeneric(const Generic::Vector2& generic) { return {generic.x(), generic.y()}; } void fromGeneric(const Generic::Vector2& generic) { x = generic.x(); y = generic.y(); } auto toGeneric() const { Generic::Vector2 fres; fres.set_x(x); fres.set_y(y); return fres; } float getDistanceTo(const Vector2& o) const { return fabs(x - o.x) + fabs(y - o.y); } }; struct LocalRobot { Generic::Robot generic; uint64_t stateTimer = 0; auto& operator *() { return generic; } auto operator ->() { return &generic; } const auto& operator *() const { return generic; } const auto operator ->() const { return &generic; } }; class Playfield { Room& room; std::vector robots; uint64_t turn = 0; public: Playfield(Room& room, const std::vector>& clients, const Generic::Settings& settings) : room(room) {} boost::asio::awaitable reset(); boost::asio::awaitable updateRobot(const Connection::Client *sender, Generic::Robot& newRobot); LocalRobot& getLocalRobot(const Connection::Client *sender, unsigned robot); float getDistanceBetween(const Generic::Robot& a, const Generic::Robot& b) { return Vector2::makeFromGeneric(a.position()).getDistanceTo(Vector2::makeFromGeneric(b.position())); } auto getPlayfieldSync() const { Generic::PlayfieldSync fres; for (const auto& robot : robots) { *fres.add_robots() = robot.generic; } return fres; } auto getTurn() const { return turn; } }; struct Room { Connection::Global &global; Generic::RoomInfo info; std::vector> clients; std::unique_ptr playfield = nullptr; Room(Connection::Global& global) : global(global) {} Generic::RoomInfo getFullRoomInfo() const; boost::asio::awaitable addClient(const std::shared_ptr& client); boost::asio::awaitable removeClient(const std::shared_ptr& client); void removeRoom(); boost::asio::awaitable removeAllClients(); bool isMasterClient(const Connection::Client *client) const { return client == clients.front().get(); } bool isFull() const { return clients.size() >= info.settings().maxplayers(); } bool isRunning() const { return bool(playfield); } bool isOpen() const { return !isFull() && !isRunning(); } }; } #endif