#include "glfw/glfw_initialization.h" #include "glfw/glfw_monitor.h" #include "glfw/glfw_window.h" #include "socket/iocp.h" #include "socket/packet.h" #include "socket/tcp_socket.h" #include "socket/udp_socket.h" #include "socket/wsa_manager.h" #include "utils/log.h" #include "utils/snowflake.h" #include "vulkan_engine/asset/object/model.h" #include "utils/utils.h" #define LISTENIP "::" #define LISTENPORT 9010 #define TICKRATE 60 constexpr double TICKDELAY = (1 / TICKRATE); std::uint8_t CLIENTID = 0; std::unordered_map MODELS; std::mutex MODELS_MUTEX; std::list> CLIENTS; std::mutex CLIENTS_MUTEX; void EchoClient(utils::ThreadPool* tp, Network::IOCP* iocp, std::shared_ptr NewSock, Network::Address NewAddr) { if (NewSock->sock == 0) return; std::future> result; Packet::Header header; std::vector recv_data; result = iocp->recv(NewSock, 14); recv_data = utils::CvtListToVector(result.get()); header.Deserialize(recv_data); result = iocp->recv(NewSock, header.body_length); recv_data = utils::CvtListToVector(result.get()); switch (header.opcode) { case Packet::Opcode::UPDATEMODEL: { veng::Model model; model.Deserialize(recv_data); std::lock_guard lock(MODELS_MUTEX); auto ID = model.ID; if (MODELS.find(ID) == MODELS.end()) spdlog::info("model received: {}:{}", model.name, ID.snowflake); MODELS[ID] = std::move(model); MODELS[ID].needsUpdate = true; } break; default: spdlog::error("unknown data type"); } tp->enqueueJob(EchoClient, iocp, NewSock, NewAddr); } void ClientRefresher(utils::ThreadPool* tp, Network::IOCP* iocp) { static double last_all_updated; static double last_frame_time_; auto current_time = glfwGetTime(); bool needs_all_update = false; if (current_time - last_all_updated >= TICKDELAY) { needs_all_update = true; last_all_updated = glfwGetTime(); } auto delta_time = current_time - last_frame_time_; last_frame_time_ = current_time; CLIENTS_MUTEX.lock(); for (auto it = CLIENTS.begin(); it != CLIENTS.end();) { if (*it == nullptr || it->get()->sock == 0) { it = CLIENTS.erase(it); } else { ++it; } } CLIENTS_MUTEX.unlock(); for (auto it = MODELS.begin(); it != MODELS.end();) { auto& model = it->second; if (std::abs(model.lifespan + 1.f) < std::numeric_limits::epsilon()) { ++it; continue; } if (model.lifespan <= 0.f) { it = MODELS.erase(it); continue; } if (model.shouldBeDestroyed) { it = MODELS.erase(it); continue; } model.lifespan -= delta_time; ++it; } CLIENTS_MUTEX.lock(); for (auto& model : MODELS) { if (model.second.name == "camera_lag") continue; model.second.Update(delta_time); for (auto& client : CLIENTS) { if (client->sock == 0) continue; std::vector send_data; auto model_serialized = model.second.Serialize(); Packet::Header header; header.opcode = Packet::Opcode::UPDATEMODEL; header.timestamp = glfwGetTime(); header.body_length = model_serialized.size(); auto header_serialized = header.Serialize(); send_data.insert(send_data.end(), header_serialized.begin(), header_serialized.end()); send_data.insert(send_data.end(), model_serialized.begin(), model_serialized.end()); if (!model.second.needsUpdate && !needs_all_update) { continue; } model.second.needsUpdate = false; if (iocp->send(client, send_data) == -1) { client->sock = 0; } spdlog::debug("server-side updated : [{}:{}]", model.second.name, model.second.ID.snowflake); } } CLIENTS_MUTEX.unlock(); tp->enqueueJob(ClientRefresher, iocp); } int main(int argc, char* argv[]) { Network::WSAManager wsamanager; const veng::GlfwInitialization _glfw; #if !defined(NDEBUG) utils::setDefaultLogger(spdlog::level::level_enum::debug, "log.log", 1024 * 1024, 2); #endif utils::ThreadPool tp(0); Network::IOCP iocp; iocp.init(&tp, SessionProtocol::TCP); Network::Address addr; addr.set(AF_INET6, "::", 9010); std::shared_ptr TCPSock = std::make_shared(); TCPSock->init(AF_INET6); if (TCPSock->bind(addr) == INVALID_SOCKET) { spdlog::error("bind()"); std::exit(EXIT_FAILURE); } if (TCPSock->listen(SOMAXCONN) == INVALID_SOCKET) { spdlog::error("listen()"); std::exit(EXIT_FAILURE); } tp.enqueueJob(ClientRefresher, &iocp); while (true) { std::shared_ptr NewSock; Network::Address NewAddr = addr; spdlog::info("Waiting for connection"); TCPSock->accept(NewSock, NewAddr); iocp.registerSocket(NewSock); Packet::Header header; std::vector packet; header.opcode = Packet::Opcode::CLIENTID; header.timestamp = glfwGetTime(); header.body_length = 1; packet = header.Serialize(); packet.resize(packet.size() + 1); std::lock_guard lock(CLIENTS_MUTEX); std::uint8_t client_id = (std::uint8_t)(CLIENTS.size() - 1); ::memcpy(packet.data() + 14, &client_id, 1); iocp.send(NewSock, packet); auto ping = glfwGetTime() - header.timestamp; CLIENTS.push_back(NewSock); tp.enqueueJob(EchoClient, &iocp, NewSock, NewAddr); } }