#pragma once #include #include #include #include #include #include #include #include using namespace boost::asio; using ip::udp; enum class MessageType : uint8_t { Login = 0x01, Position = 0x02, Spawn = 0x03, Move = 0x04, Update = 0x05, PlayerJoined = 0x06, PlayerLeft = 0x07, PlayerList = 0x08, ChangeColor = 0x09, ColorChanged = 0x0A, LoginResponse = 0x0B, Logout = 0x0C, Heartbeat = 0x0D, TimeSync = 0x0E }; struct RemotePlayer { uint32_t id; Vector3 position; std::string color; float lastUpdate; }; class NetworkManager { public: NetworkManager(); ~NetworkManager(); void sendLogin(); void sendLoginWithUsername(const std::string& username); void sendLogout(); void sendMove(float dx, float dy, float dz); void sendColorChange(const std::string& newColor); void sendHeartbeat(); Vector3 getPosition(); bool isConnected() const { return connected; } bool hasLoginError() const { return !loginErrorMsg.empty(); } std::string getLoginError() const { return loginErrorMsg; } uint32_t getPlayerID() const { return playerID; } std::string getPlayerColor() const { return playerColor; } std::unordered_map getRemotePlayers(); float getServerTimeOfDay() const { return serverTimeOfDay.load(); } // Available colors for cycling static const std::vector AVAILABLE_COLORS; private: io_context ioContext; udp::socket socket{ioContext}; udp::endpoint serverEndpoint; std::thread ioThread; std::array recvBuffer; std::atomic playerID{0}; std::string playerColor{"red"}; std::string currentUsername{""}; std::string loginErrorMsg{""}; std::mutex positionMutex; Vector3 serverPosition{0, 0, 0}; std::atomic connected{false}; std::mutex remotePlayersMutex; std::unordered_map remotePlayers; std::atomic serverTimeOfDay{0.0f}; void startReceive(); void processMessage(const uint8_t* data, std::size_t size); void handleSpawn(const uint8_t* data, std::size_t size); void handleUpdate(const uint8_t* data, std::size_t size); void handlePlayerJoined(const uint8_t* data, std::size_t size); void handlePlayerLeft(const uint8_t* data, std::size_t size); void handlePlayerList(const uint8_t* data, std::size_t size); void handleColorChanged(const uint8_t* data, std::size_t size); void handleLoginResponse(const uint8_t* data, std::size_t size); void handleTimeSync(const uint8_t* data, std::size_t size); };