#pragma once #include #include #include #include #include #include #include "dvlnet/abstract_net.h" #include "dvlnet/packet.h" #include "multi.h" #include "storm/storm_net.hpp" namespace devilution { namespace net { class base : public abstract_net { public: bool SNetReceiveMessage(uint8_t *sender, void **data, uint32_t *size) override; bool SNetSendMessage(int playerId, void *data, unsigned int size) override; bool SNetReceiveTurns(char **data, size_t *size, uint32_t *status) override; bool SNetSendTurn(char *data, unsigned int size) override; void SNetGetProviderCaps(struct _SNETCAPS *caps) override; bool SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func) override; bool SNetUnregisterEventHandler(event_type evtype) override; bool SNetLeaveGame(int type) override; bool SNetDropPlayer(int playerid, uint32_t flags) override; bool SNetGetOwnerTurnsWaiting(uint32_t *turns) override; bool SNetGetTurnsInTransit(uint32_t *turns) override; virtual tl::expected poll() = 0; virtual void send(packet &pkt) = 0; virtual void DisconnectNet(plr_t plr); void setup_gameinfo(buffer_t info); void setup_password(std::string pw) override; void clear_password() override; ~base() override = default; protected: std::map registered_handlers; buffer_t game_init_info; struct message_t { uint8_t sender; buffer_t payload; message_t() : sender(-1) , payload({}) { } message_t(int s, buffer_t p) : sender(s) , payload(p) { } }; struct PlayerState { bool isConnected = {}; std::deque turnQueue; int32_t lastTurnValue = {}; uint32_t roundTripLatency = {}; }; seq_t current_turn = 0; seq_t next_turn = 0; message_t message_last; std::deque message_queue; plr_t plr_self = PLR_BROADCAST; cookie_t cookie_self = 0; std::unique_ptr pktfty; tl::expected Connect(plr_t player); tl::expected RecvLocal(packet &pkt); void RunEventHandler(_SNETEVENT &ev); tl::expected SendEchoRequest(plr_t player); [[nodiscard]] bool IsConnected(plr_t player) const; virtual bool IsGameHost() = 0; private: std::array playerStateTable_; bool awaitingSequenceNumber_ = true; plr_t GetOwner(); bool AllTurnsArrived(); tl::expected MakeReady(seq_t sequenceNumber); tl::expected SendTurnIfReady(turn_t turn); tl::expected SendFirstTurnIfReady(plr_t player); void ClearMsg(plr_t plr); tl::expected HandleAccept(packet &pkt); tl::expected HandleConnect(packet &pkt); tl::expected HandleTurn(packet &pkt); tl::expected HandleDisconnect(packet &pkt); tl::expected HandleEchoRequest(packet &pkt); tl::expected HandleEchoReply(packet &pkt); }; } // namespace net } // namespace devilution