diff --git a/Client/src/asteroid/begin_play.cpp b/Client/src/asteroid/begin_play.cpp index d587f49..e3888ff 100644 --- a/Client/src/asteroid/begin_play.cpp +++ b/Client/src/asteroid/begin_play.cpp @@ -1,78 +1,104 @@ #include "asteroid/game.h" - #include "vulkan_engine/vulkan/engine.h" - void BeginPlay(veng::Engine& engine) { std::random_device rd; std::mt19937 gen = std::mt19937(rd()); - std::uniform_real_distribution jitterDist = std::uniform_real_distribution(-2, 2); + std::uniform_real_distribution jitterDist = + std::uniform_real_distribution(-2, 2); - veng::Model* const player = engine.SpawnLifedModel("player", "player", -1); - player->position = glm::vec3(jitterDist(gen), jitterDist(gen), 0.f); - player->scale = glm::vec3(.02f); - player->colision = true; - player->OnColision = [](veng::Model* self, veng::Model* other) { - if (other->owner == self) return; - spdlog::info("{} and {} is nearby.", (void*)self, (void*)other); + std::shared_ptr const player = + engine.SpawnLifedModel("player", "player", -1); + { + std::lock_guard lock(player->modding); + player->position = glm::vec3(jitterDist(gen), jitterDist(gen), 0.f); + player->scale = glm::vec3(.02f); + player->colision = true; + player->OnColision = [](std::shared_ptr self, + std::shared_ptr other) { + auto self_owner = self->owner.lock(); + auto other_owner = other->owner.lock(); + if (other_owner == nullptr || self_owner == nullptr) return; + if (other_owner->ID == self->ID) return; + spdlog::info("[{}:{}] and [{}:{}] is nearby.", self->name, + self->ID.snowflake, other->name, other->ID.snowflake); - spdlog::info("{} 's owner: {}", (void*)self, (void*)self->owner); - spdlog::info("{} 's owner: {}", (void*)other, (void*)other->owner); + spdlog::info("[{}:{}] 's owner: [{}:{}]", self->name, self->ID.snowflake, + self_owner->name, self_owner->ID.snowflake); + spdlog::info("[{}:{}] 's owner: [{}:{}]", other->name, + other->ID.snowflake, other_owner->name, + other_owner->ID.snowflake); - other->colision = false; - other->visible = false; - other->shouldBeDestroyed = true; - }; - veng::Model* const player_flame = + other->colision = false; + other->visible = false; + other->shouldBeDestroyed = true; + }; + } + + std::shared_ptr const player_flame = engine.SpawnLifedModel("player_flame", "player_flame", -1); - player_flame->scale = player->scale; - player_flame->colision = false; - player_flame->networkReplicated = false; + { + std::lock_guard lock(player_flame->modding); + player_flame->scale = player->scale; + player_flame->colision = false; + player_flame->networkReplicated = true; + player_flame->needsUpdate = true; + } - spdlog::info("player addr: {}", (void*)player); + std::shared_ptr const other_player = + engine.SpawnLifedModel("player", "other_player", -1); + { + std::lock_guard lock(other_player->modding); + other_player->position = glm::vec3(1.f, 0.f, 0.f); + other_player->scale = glm::vec3(.02f); + other_player->colision = true; + } - veng::Model* const other_player = engine.SpawnLifedModel("player", "other_player", -1); - other_player->position = glm::vec3(1.f, 0.f, 0.f); - other_player->scale = glm::vec3(.02f); - other_player->colision = true; - other_player->OnColision = [](veng::Model* self, veng::Model* other) { - if (other->owner == self) return; - spdlog::info("{} and {} is nearby.", (void*)self, (void*)other); + std::shared_ptr const camera_lag = + engine.SpawnLifedModel("", "camera_lag", -1); + { + std::lock_guard lock(camera_lag->modding); + camera_lag->colision = false; + camera_lag->position = player->position; + } - spdlog::info("{} 's owner: {}", (void*)self, (void*)self->owner); - spdlog::info("{} 's owner: {}", (void*)other, (void*)other->owner); + std::shared_ptr const background = + engine.SpawnLifedModel("", "background", -1); + { + std::lock_guard lock(background->modding); + background->colision = false; + background->position = {background->position.x, background->position.y, + 30.f}; + background->scale *= 100; + background->networkReplicated = false; + } - other->colision = false; - other->visible = false; - other->shouldBeDestroyed = true; - }; - - spdlog::info("other player addr: {}", (void*)other_player); - - veng::Model* const camera_lag = engine.SpawnLifedModel("", "camera_lag", -1); - camera_lag->colision = false; - camera_lag->position = player->position; - - veng::Model* const background = engine.SpawnLifedModel("", "background", -1); - background->colision = false; - background->position = {background->position.x, background->position.y, 30.f}; - background->scale *= 100; - background->networkReplicated = false; - - veng::Model* const background0 = + std::shared_ptr const background0 = engine.SpawnLifedModel("background", "background0", -1); - background0->scale = background->scale; - background0->networkReplicated = false; - veng::Model* const background1 = + { + std::lock_guard lock(background0->modding); + background0->scale = background->scale; + background0->networkReplicated = false; + } + std::shared_ptr const background1 = engine.SpawnLifedModel("background", "background1", -1); - background1->scale = background->scale; - background1->networkReplicated = false; - veng::Model* const background2 = + { + std::lock_guard lock(background1->modding); + background1->scale = background->scale; + background1->networkReplicated = false; + } + std::shared_ptr const background2 = engine.SpawnLifedModel("background", "background2", -1); - background2->scale = background->scale; - background2->networkReplicated = false; - veng::Model* const background3 = + { + std::lock_guard lock(background2->modding); + background2->scale = background->scale; + background2->networkReplicated = false; + } + std::shared_ptr const background3 = engine.SpawnLifedModel("background", "background3", -1); - background3->scale = background->scale; - background3->networkReplicated = false; + { + std::lock_guard lock(background3->modding); + background3->scale = background->scale; + background3->networkReplicated = false; + } } diff --git a/Client/src/asteroid/main.cpp b/Client/src/asteroid/main.cpp index 544a6b9..a7f06e2 100644 --- a/Client/src/asteroid/main.cpp +++ b/Client/src/asteroid/main.cpp @@ -9,6 +9,7 @@ #include "socket/wsa_manager.h" #include "utils/log.h" #include "utils/snowflake.h" +#include "utils/utils.h" #include "vulkan_engine/vulkan/engine.h" #include "vulkan_engine/vulkan/graphics.h" @@ -28,28 +29,24 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { addr.set(AF_INET6, "::1", 9010); - Network::TCPSocket TCPSock; - TCPSock.init(AF_INET6); - if (TCPSock.connect(addr) == INVALID_SOCKET) { + std::shared_ptr TCPSock = + std::make_shared(); + TCPSock->init(AF_INET6); + if (TCPSock->connect(addr) == INVALID_SOCKET) { spdlog::error("connect()"); std::exit(EXIT_FAILURE); } - iocp.registerTCPSocket(TCPSock, 16 * 1024); + iocp.registerSocket(TCPSock); + + auto result = iocp.recv(TCPSock, 14); + auto header_serialized = utils::CvtListToVector(result.get()); - while (iocp.GetRecvedBytes(TCPSock.sock) < 6); - std::vector header_serialized(6); - iocp.recv(TCPSock, header_serialized); Packet::Header header; header.Deserialize(header_serialized); - while (iocp.GetRecvedBytes(TCPSock.sock) < header.body_length); - std::vector data(header.body_length); - iocp.recv(TCPSock, data); - ::memcpy(&CLIENTID, data.data(), 1); //id 받기 - header.opcode = Packet::Opcode::CLIENTID; - header.body_length = 0; - header_serialized = header.Serialize(); - iocp.send(TCPSock, header_serialized); + result = iocp.recv(TCPSock, header.body_length); + std::vector data = utils::CvtListToVector(result.get()); + ::memcpy(&CLIENTID, data.data(), 1); // id 받기 const veng::GlfwInitialization _glfw; @@ -69,11 +66,17 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { engine.init(); + tp.enqueueJob( + [engine = &engine, TCPSock](utils::ThreadPool* tp, std::uint32_t __) { + engine->ResponseToServerAndRefresh(TCPSock); + }, + 0); + while (!window.ShouldClose()) { glfwPollEvents(); engine.Update(); - engine.NetUpdate(std::make_shared(TCPSock)); + engine.NetUpdate(TCPSock); } return EXIT_SUCCESS; diff --git a/Client/src/asteroid/tick.cpp b/Client/src/asteroid/tick.cpp index 55ce9a7..0f1aa2b 100644 --- a/Client/src/asteroid/tick.cpp +++ b/Client/src/asteroid/tick.cpp @@ -5,15 +5,26 @@ void Tick(veng::Engine& engine, std::float_t delta_time) { static std::float_t bullet_cooldown = 0.f; - veng::Model* const player = engine.GetSpawnedObject("player"); - veng::Model* const player_flame = engine.GetSpawnedObject("player_flame"); - veng::Model* const camera_lag = engine.GetSpawnedObject("camera_lag"); + std::shared_ptr const player = engine.GetSpawnedObject("player"); + std::shared_ptr const player_flame = engine.GetSpawnedObject("player_flame"); + std::shared_ptr const camera_lag = engine.GetSpawnedObject("camera_lag"); - veng::Model* const background = engine.GetSpawnedObject("background"); - veng::Model* const background0 = engine.GetSpawnedObject("background0"); - veng::Model* const background1 = engine.GetSpawnedObject("background1"); - veng::Model* const background2 = engine.GetSpawnedObject("background2"); - veng::Model* const background3 = engine.GetSpawnedObject("background3"); + std::shared_ptr const background = engine.GetSpawnedObject("background"); + std::shared_ptr const background0 = engine.GetSpawnedObject("background0"); + std::shared_ptr const background1 = engine.GetSpawnedObject("background1"); + std::shared_ptr const background2 = engine.GetSpawnedObject("background2"); + std::shared_ptr const background3 = engine.GetSpawnedObject("background3"); + + std::lock_guard lock[] = { + std::lock_guard(player->modding), + std::lock_guard(player_flame->modding), + std::lock_guard(camera_lag->modding), + std::lock_guard(background->modding), + std::lock_guard(background0->modding), + std::lock_guard(background1->modding), + std::lock_guard(background2->modding), + std::lock_guard(background3->modding) + }; glm::vec3 forward = player->rotation * glm::vec3(0, 1, 0); glm::vec3 right = player->rotation * glm::vec3(1, 0, 0); @@ -43,8 +54,11 @@ void Tick(veng::Engine& engine, std::float_t delta_time) { GLFW_PRESS) { player->linear_acceleration = glm::normalize(forward) * 10.f; player_flame->visible = true; - player->needsUpdate = true; - w_laststate = true; + + if (!w_laststate) { + player->needsUpdate = true; + w_laststate = true; + } } else { player->linear_acceleration = forward * .0f; player_flame->visible = false; @@ -63,17 +77,35 @@ void Tick(veng::Engine& engine, std::float_t delta_time) { bullet_cooldown -= delta_time; } else { bullet_cooldown = .2f; - veng::Model* const bullet = + std::shared_ptr const bullet = engine.SpawnLifedModel("bullet", "bullet", 10.f); bullet->linear_velocity = player->linear_velocity + forward * 10.f; bullet->position = player->position + forward * player->scale.x * 10.f; bullet->owner = player; bullet->scale = player->scale; bullet->colision = true; + bullet->OnColision = [](std::shared_ptr self, + std::shared_ptr other) { + auto self_owner = self->owner.lock(); + auto other_owner = other->owner.lock(); + if (other_owner == nullptr || self_owner == nullptr) return; + if (other_owner->ID == self->ID) return; + spdlog::info("[{}:{}] and [{}:{}] is nearby.", self->name, + self->ID.snowflake, other->name, other->ID.snowflake); + + spdlog::info("[{}:{}] 's owner: [{}:{}]", self->name, + self->ID.snowflake, self_owner->name, + self_owner->ID.snowflake); + spdlog::info("[{}:{}] 's owner: [{}:{}]", other->name, + other->ID.snowflake, other_owner->name, + other_owner->ID.snowflake); + + other->colision = false; + other->visible = false; + other->shouldBeDestroyed = true; + }; bullet->networkReplicated = true; bullet->needsUpdate = true; - - spdlog::info("bullet address: {}", (void*)bullet); } } @@ -82,14 +114,18 @@ void Tick(veng::Engine& engine, std::float_t delta_time) { GLFW_PRESS) { right = player->rotation * glm::vec3(0, 0, 1); player->angular_velocity = right * 6.f; - player->needsUpdate = true; - ad_laststate = true; + if (!ad_laststate) { + player->needsUpdate = true; + ad_laststate = true; + } } else if (glfwGetKey(engine.vulkan_graphics->window->GetHandle(), GLFW_KEY_D) == GLFW_PRESS) { right = player->rotation * glm::vec3(0, 0, 1); player->angular_velocity = right * -6.f; - player->needsUpdate = true; - ad_laststate = true; + if (!ad_laststate) { + player->needsUpdate = true; + ad_laststate = true; + } } else { right = player->rotation * glm::vec3(0, 0, 1); player->angular_velocity = right * 0.f; diff --git a/Server/src/server.cpp b/Server/src/server.cpp index 600b389..b5cb548 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -9,6 +9,7 @@ #include "utils/log.h" #include "utils/snowflake.h" #include "vulkan_engine/asset/object/model.h" +#include "utils/utils.h" #define LISTENIP "::" #define LISTENPORT 9010 @@ -16,37 +17,23 @@ std::uint8_t CLIENTID = 0; std::unordered_map MODELS; std::mutex MODELS_MUTEX; -std::vector> CLIENTS; +std::list> CLIENTS; std::mutex CLIENTS_MUTEX; -void recv_fully(Network::IOCP* iocp, Network::TCPSocket& sock, - std::vector& buffer) { - size_t total_received = 0; - size_t expected = buffer.size(); - - while (total_received < expected) { - if (total_received != 0) - Sleep(100); // 너무 빨리 재시도해서 큐가 채워질 틈이 없는 듯? - if (sock.sock == 0) return; - std::vector temp(expected - total_received); - - size_t received = iocp->recv(sock, temp); - - std::copy(temp.begin(), temp.begin() + received, - buffer.begin() + total_received); - total_received += received; - } -} - void EchoClient(utils::ThreadPool* tp, Network::IOCP* iocp, - Network::TCPSocket* NewSock, Network::Address NewAddr) { + std::shared_ptr NewSock, Network::Address NewAddr) { if (NewSock->sock == 0) return; - std::vector recv_data(6); - recv_fully(iocp, *NewSock, recv_data); + 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); - recv_data.resize(header.body_length); - recv_fully(iocp, *NewSock, recv_data); + + result = iocp->recv(NewSock, header.body_length); + recv_data = utils::CvtListToVector(result.get()); switch (header.opcode) { case Packet::Opcode::UPDATEMODEL: { @@ -68,24 +55,26 @@ void EchoClient(utils::ThreadPool* tp, Network::IOCP* iocp, } void ClientRefresher(utils::ThreadPool* tp, Network::IOCP* iocp) { - static auto last_all_updated = glfwGetTime(); - static auto last_frame_time_ = glfwGetTime(); + 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 >= 100) { + if (current_time - last_all_updated >= .01f) { 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->first.sock == 0) { + 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; @@ -110,15 +99,17 @@ void ClientRefresher(utils::ThreadPool* tp, Network::IOCP* iocp) { ++it; } + CLIENTS_MUTEX.lock(); for (auto& client : CLIENTS) { - if (client.first.sock == 0) continue; + if (client->sock == 0) continue; for (auto& model : MODELS) { if (model.second.name == "camera_lag") continue; std::vector send_data; - model.second.Update(delta_time + (client.second / 2)); + model.second.Update(delta_time); 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(), @@ -129,12 +120,13 @@ void ClientRefresher(utils::ThreadPool* tp, Network::IOCP* iocp) { continue; } model.second.needsUpdate = false; - if (client.first.send(send_data.data(), send_data.size(), 0) == -1) { - client.first.sock = 0; + if (iocp->send(client, send_data) == -1) { + client->sock = 0; } - spdlog::info("updated: {}", model.second.name); + spdlog::debug("server-side updated : [{}:{}]", model.second.name, model.second.ID.snowflake); } } + CLIENTS_MUTEX.unlock(); tp->enqueueJob(ClientRefresher, iocp); } @@ -154,15 +146,14 @@ int main(int argc, char* argv[]) { addr.set(AF_INET6, "::", 9010); - Network::Socket* sock; - Network::TCPSocket TCPSock; - TCPSock.init(AF_INET6); - sock = &TCPSock; - if (TCPSock.bind(addr) == INVALID_SOCKET) { + 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) { + if (TCPSock->listen(SOMAXCONN) == INVALID_SOCKET) { spdlog::error("listen()"); std::exit(EXIT_FAILURE); } @@ -170,32 +161,31 @@ int main(int argc, char* argv[]) { tp.enqueueJob(ClientRefresher, &iocp); while (true) { - Network::TCPSocket NewSock; - Network::Address NewAddr; - NewAddr.length = addr.length; + std::shared_ptr NewSock; + Network::Address NewAddr = addr; spdlog::info("Waiting for connection"); - TCPSock.accept(NewSock, NewAddr); + TCPSock->accept(NewSock, NewAddr); - iocp.registerTCPSocket(NewSock, 16 * 1024); + iocp.registerSocket(NewSock); Packet::Header header; + std::vector packet; + header.opcode = Packet::Opcode::CLIENTID; - header.body_length = 9; - auto packet = header.Serialize(); - packet.resize(packet.size() + 9); + 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 = CLIENTS.size() - 1; - ::memcpy(packet.data() + 6, &client_id, 1); + std::uint8_t client_id = (std::uint8_t)(CLIENTS.size() - 1); + ::memcpy(packet.data() + 14, &client_id, 1); - std::double_t timestamp = glfwGetTime(); - - ::memcpy(packet.data() + 7, ×tamp, 8); iocp.send(NewSock, packet); - std::vector header_buf(6); - recv_fully(&iocp, NewSock, header_buf); - auto ping = glfwGetTime() - timestamp; - CLIENTS.emplace_back(std::move(NewSock), ping); - tp.enqueueJob(EchoClient, &iocp, &CLIENTS.back().first, NewAddr); + auto ping = glfwGetTime() - header.timestamp; + CLIENTS.push_back(NewSock); + + tp.enqueueJob(EchoClient, &iocp, NewSock, NewAddr); } } diff --git a/impl/socket/address.cpp b/impl/socket/address.cpp index 5b30d35..84d1f1b 100644 --- a/impl/socket/address.cpp +++ b/impl/socket/address.cpp @@ -4,50 +4,6 @@ namespace Network { -//void Address::set(int type, gsl::czstring presentationAddr, -// std::uint16_t port) { -// zeroFill(); -// setType(type); -// -// if (type == AF_INET) { -// ::inet_pton(AF_INET, presentationAddr, &addr_in.sin_addr); -// addr_in.sin_port = htons(port); -// } else if (type == AF_INET6) { -// ::inet_pton(AF_INET6, presentationAddr, &addr_in6.sin6_addr); -// addr_in6.sin6_port = htons(port); -// } -// -// BIO_ADDRINFO* res; -// if (!BIO_lookup_ex(presentationAddr, std::to_string(port).c_str(), -// BIO_LOOKUP_CLIENT, type, SOCK_DGRAM, 0, &res)) { -// ::BIO_ADDRINFO_free(res); -// throw std::runtime_error("can't resolve address"); -// } -// -// int sock = -1; -// for (const BIO_ADDRINFO* ai = res; ai != nullptr; -// ai = ::BIO_ADDRINFO_next(ai)) { -// sock = ::BIO_socket(BIO_ADDRINFO_family(ai), type, 0, 0); -// if (sock == -1) -// continue; -// else { -// auto bio_addr = ::BIO_ADDRINFO_address(ai); -// BIO_ADDR_rawaddress(bio_addr, &addr, (unsigned long long*)&length); -// bio_addr_info = ::BIO_ADDR_dup(bio_addr); -// -// break; -// } -// } -// -// if (sock != -1) -// ::close(sock); -// -// ::BIO_ADDRINFO_free(res); -// -// addr_in.sin_family = type; -// addr_in.sin_port = htons(port); -//} - Address::Address() { zeroFill(); } Address::Address(int type, gsl::czstring presentationAddr, std::uint16_t port) { @@ -58,19 +14,18 @@ void Address::zeroFill() { memset(&addr_in6, 0, sizeof(addr_in6)); } void Address::set(int type, gsl::czstring presentationAddr, std::uint16_t port) { - zeroFill(); + setType(type); if (type == AF_INET) { addr_in.sin_family = AF_INET; ::inet_pton(AF_INET, presentationAddr, &addr_in.sin_addr); addr_in.sin_port = htons(port); - length = sizeof(sockaddr_in); } else if (type == AF_INET6) { addr_in6.sin6_family = AF_INET6; ::inet_pton(AF_INET6, presentationAddr, &addr_in6.sin6_addr); addr_in6.sin6_port = htons(port); - length = sizeof(sockaddr_in6); } + family = type; } void Address::setType(int type) { @@ -87,12 +42,12 @@ Address::operator std::string() { if (!port) return std::string(); - if (length == sizeof(addr_in)) { + if (family == AF_INET) { char addrStr[INET_ADDRSTRLEN]; ::inet_ntop(AF_INET, &addr_in.sin_addr, addrStr, sizeof(addrStr)); return std::format("{}:{}", addrStr, port.value()); - } else if (length == sizeof(addr_in6)) { + } else if (family == AF_INET6) { char addrStr[INET6_ADDRSTRLEN]; ::inet_ntop(AF_INET6, &addr_in6.sin6_addr, addrStr, sizeof(addrStr)); diff --git a/impl/socket/iocp.cpp b/impl/socket/iocp.cpp index ca7268b..c2a813f 100644 --- a/impl/socket/iocp.cpp +++ b/impl/socket/iocp.cpp @@ -4,7 +4,7 @@ namespace Network { -IOCP::IOCP() { +IOCP::IOCP() : IOCPThread_(nullptr), proto_(SessionProtocol::TCP) { gen_ = std::mt19937(rd_()); jitterDist_ = std::uniform_int_distribution(-10, 10); } @@ -40,22 +40,86 @@ void IOCP::destruct() { #endif } -void IOCP::registerTCPSocket(Socket& sock, std::uint32_t bufsize) { +void IOCP::registerSocket(std::shared_ptr sock) { #ifdef _WIN32 - HANDLE returnData = ::CreateIoCompletionPort((HANDLE)sock.sock, - completionPort_, sock.sock, 0); + HANDLE returnData = ::CreateIoCompletionPort((HANDLE)sock->sock, + completionPort_, sock->sock, 0); if (returnData == 0) completionPort_ = returnData; +#endif +} - IOCPPASSINDATA* recv_data = new IOCPPASSINDATA(bufsize); - recv_data->event = IOCPEVENT::READ; - recv_data->socket = std::make_shared(sock); - recv_data->IOCPInstance = this; - DWORD recvbytes = 0, flags = 0; +std::future> IOCP::recvFull(std::shared_ptr sock, + std::uint32_t bufsize) { + auto promise = std::make_shared>>(); + auto future = promise->get_future(); + + auto buffer = std::make_shared>(); + buffer->reserve(bufsize); + + std::function recvChunk; + recvChunk = [=](std::uint32_t remaining) mutable { + this->recv(sock, remaining, + [=](utils::ThreadPool* th, IOCPPASSINDATA* data) { + buffer->insert(buffer->end(), data->wsabuf.buf, + data->wsabuf.buf + data->transferredbytes); + + std::uint32_t still_left = + bufsize - static_cast(buffer->size()); + if (still_left > 0) { + recvChunk(still_left); + } else { + promise->set_value(std::move(*buffer)); + } + + return std::list(); + }); + }; + + recvChunk(bufsize); + + return future; +} + +std::list DEFAULT_RECVALL_CALLBACK(utils::ThreadPool* th, + IOCPPASSINDATA* data) { + std::list return_value; + return_value.insert(return_value.end(), data->wsabuf.buf, + data->wsabuf.buf + data->transferredbytes); + + if (data->transferredbytes < data->wsabuf.len) { + auto future = data->IOCPInstance->recv( + data->socket, data->wsabuf.len - data->transferredbytes, + DEFAULT_RECVALL_CALLBACK); + auto result = future.get(); + return_value.insert(return_value.end(), result.begin(), result.end()); + } + + return return_value; +} + +std::future> IOCP::recv( + std::shared_ptr sock, std::uint32_t bufsize, + std::function(utils::ThreadPool*, IOCPPASSINDATA*)> + callback) { + std::lock_guard lock(*GetRecvQueueMutex(sock->sock)); + auto queue = GetRecvQueue(sock->sock); + + Network::IOCPPASSINDATA* data; + std::packaged_task(utils::ThreadPool*, IOCPPASSINDATA*)> task; + std::future> future; + if (callback != nullptr) { + task = std::packaged_task(utils::ThreadPool*, + IOCPPASSINDATA*)>(callback); + future = task.get_future(); + data = new Network::IOCPPASSINDATA(sock, bufsize, this, std::move(task)); + } else { + data = new Network::IOCPPASSINDATA(sock, bufsize, this); + } int result = SOCKET_ERROR; - - result = ::WSARecv(recv_data->socket->sock, &recv_data->wsabuf, 1, &recvbytes, - &flags, &recv_data->overlapped, NULL); + DWORD recvbytes = 0, flags = 0; + result = ::WSARecv(sock->sock, &data->wsabuf, 1, &recvbytes, &flags, + &data->overlapped, NULL); if (result == SOCKET_ERROR) { int err = ::WSAGetLastError(); if (err != WSA_IO_PENDING) { @@ -64,82 +128,22 @@ void IOCP::registerTCPSocket(Socket& sock, std::uint32_t bufsize) { } } -#endif + return future; } -void IOCP::registerUDPSocket(IOCPPASSINDATA* data, Address recv_addr) { -#ifdef _WIN32 - HANDLE returnData = ::CreateIoCompletionPort( - (HANDLE)data->socket->sock, completionPort_, data->socket->sock, 0); - if (returnData == 0) completionPort_ = returnData; - - IOCPPASSINDATA* recv_data = new IOCPPASSINDATA(data->bufsize); - recv_data->event = IOCPEVENT::READ; - recv_data->socket = data->socket; - DWORD recvbytes = 0, flags = 0; - - int result = SOCKET_ERROR; - - ::WSARecvFrom(recv_data->socket->sock, &recv_data->wsabuf, 1, &recvbytes, - &flags, &recv_addr.addr, &recv_addr.length, - &recv_data->overlapped, NULL); - - if (result == SOCKET_ERROR) { - int err = ::WSAGetLastError(); - if (err != WSA_IO_PENDING) { - auto err_msg = std::format("WSARecv failed: {}", err); - throw std::runtime_error(err_msg); - } - } - -#endif -} - -int IOCP::recv(Socket& sock, std::vector& data) { - std::lock_guard lock(*GetRecvQueueMutex_(sock.sock)); - auto queue = GetRecvQueue_(sock.sock); - - std::uint32_t left_data = data.size(); - std::uint32_t copied = 0; - - while (!queue->empty() && left_data != 0) { - auto front = queue->front(); - queue->pop_front(); - - std::uint32_t offset = front.second; - std::uint32_t available = front.first.size() - offset; - std::uint32_t to_copy = (left_data < available) ? left_data : available; - - ::memcpy(data.data() + copied, front.first.data() + offset, to_copy); - copied += to_copy; - left_data -= to_copy; - offset += to_copy; - - if (offset < front.first.size()) { - front.second = offset; - queue->push_front(front); - break; - } - } - - return copied; -} - -int IOCP::send(Socket& sock, std::vector& data) { - auto lk = GetSendQueueMutex_(sock.sock); - auto queue = GetSendQueue_(sock.sock); +int IOCP::send(std::shared_ptr sock, std::vector& data) { + auto lk = GetSendQueueMutex(sock->sock); + auto queue = GetSendQueue(sock->sock); std::lock_guard lock(*lk); - Network::IOCPPASSINDATA* packet = new Network::IOCPPASSINDATA(data.size()); + Network::IOCPPASSINDATA* packet = new Network::IOCPPASSINDATA(sock, data.size(), this); packet->event = IOCPEVENT::WRITE; - packet->socket = std::make_shared(sock); - packet->IOCPInstance = this; ::memcpy(packet->wsabuf.buf, data.data(), data.size()); packet->wsabuf.len = data.size(); queue->push_back(packet); IOCPThread_->enqueueJob( - [this, sock = sock.sock](utils::ThreadPool* th, std::uint8_t __) { + [this, sock = sock->sock](utils::ThreadPool* th, std::uint8_t __) { packet_sender_(sock); }, 0); @@ -147,7 +151,7 @@ int IOCP::send(Socket& sock, std::vector& data) { } int IOCP::GetRecvedBytes(SOCKET sock) { - auto queue = GetRecvQueue_(sock); + auto queue = GetRecvQueue(sock); std::lock_guard lock(socket_mod_mutex_); int bytes = 0; @@ -178,7 +182,15 @@ void IOCP::iocpWatcher_(utils::ThreadPool* IOCPThread) { data->event = IOCPEVENT::QUIT; spdlog::debug("Disconnected. [{}]", (std::string)(data->socket->remoteAddr)); - delete data; + auto task = [this, IOCPThread, data = std::move(data)]( + utils::ThreadPool* th, std::uint8_t __) { + if (data->callback.valid()) { + data->callback(th, data); + } + data->socket->destruct(); + delete data; + }; + IOCPThread->enqueueJob(task, 0); IOCPThread->enqueueJob( [this](utils::ThreadPool* th, std::uint8_t __) { iocpWatcher_(th); }, 0); @@ -187,34 +199,17 @@ void IOCP::iocpWatcher_(utils::ThreadPool* IOCPThread) { data->transferredbytes = cbTransfrred; } - std::vector buf(16384); // SSL_read최대 반환 크기 - int red_data = 0; - std::lock_guard lock(*GetRecvQueueMutex_(sock)); - auto queue_list = GetRecvQueue_(sock); - if (data->event == IOCPEVENT::READ) { - ::memcpy(buf.data(), data->wsabuf.buf, data->transferredbytes); - queue_list->emplace_back(std::make_pair( - std::vector(buf.begin(), buf.begin() + data->transferredbytes), - 0)); - DWORD recvbytes = 0, flags = 0; - - IOCPPASSINDATA* recv_data = new IOCPPASSINDATA(data->bufsize); - recv_data->event = IOCPEVENT::READ; - recv_data->socket = data->socket; - + auto task = [this, IOCPThread, data = std::move(data)](utils::ThreadPool* th, + std::uint8_t __) { + if (data->callback.valid()) data->callback(th, data); delete data; - ::WSARecv(recv_data->socket->sock, &recv_data->wsabuf, 1, &recvbytes, - &flags, &recv_data->overlapped, NULL); - } else { // WRITE 시, 무시한다. - spdlog::debug("writed {} bytes to {}", cbTransfrred, - (std::string)(data->socket->remoteAddr)); - delete data; - } + }; + IOCPThread->enqueueJob(task, 0); IOCPThread->enqueueJob( [this](utils::ThreadPool* th, std::uint8_t __) { iocpWatcher_(th); }, 0); } -std::shared_ptr> IOCP::GetSendQueue_(SOCKET sock) { +std::shared_ptr> IOCP::GetSendQueue(SOCKET sock) { std::lock_guard lock(socket_mod_mutex_); if (send_queue_.find(sock) == send_queue_.end()) { send_queue_[sock] = std::make_shared>( @@ -224,7 +219,7 @@ std::shared_ptr> IOCP::GetSendQueue_(SOCKET sock) { } std::shared_ptr, std::uint32_t>>> -IOCP::GetRecvQueue_(SOCKET sock) { +IOCP::GetRecvQueue(SOCKET sock) { std::lock_guard lock(socket_mod_mutex_); if (recv_queue_.find(sock) == recv_queue_.end()) { recv_queue_[sock] = std::make_shared< @@ -234,7 +229,7 @@ IOCP::GetRecvQueue_(SOCKET sock) { return recv_queue_[sock]; } -std::shared_ptr IOCP::GetSendQueueMutex_(SOCKET sock) { +std::shared_ptr IOCP::GetSendQueueMutex(SOCKET sock) { std::lock_guard lock(socket_mod_mutex_); if (send_queue_mutex_.find(sock) == send_queue_mutex_.end()) { send_queue_mutex_[sock] = std::make_shared(); @@ -242,7 +237,7 @@ std::shared_ptr IOCP::GetSendQueueMutex_(SOCKET sock) { return send_queue_mutex_[sock]; } -std::shared_ptr IOCP::GetRecvQueueMutex_(SOCKET sock) { +std::shared_ptr IOCP::GetRecvQueueMutex(SOCKET sock) { std::lock_guard lock(socket_mod_mutex_); if (recv_queue_mutex_.find(sock) == recv_queue_mutex_.end()) { recv_queue_mutex_[sock] = std::make_shared(); @@ -251,8 +246,8 @@ std::shared_ptr IOCP::GetRecvQueueMutex_(SOCKET sock) { } void IOCP::packet_sender_(SOCKET sock) { - auto queue = GetSendQueue_(sock); - std::unique_lock lock(*GetSendQueueMutex_(sock)); + auto queue = GetSendQueue(sock); + std::unique_lock lock(*GetSendQueueMutex(sock)); std::vector buf(16384); WSABUF wsabuf; diff --git a/impl/socket/socket.cpp b/impl/socket/socket.cpp index e3716fc..92b075a 100644 --- a/impl/socket/socket.cpp +++ b/impl/socket/socket.cpp @@ -70,12 +70,13 @@ int Socket::bind(Address __addr) { int Socket::connect(Address& serveraddr) { std::string addr_string = serveraddr; int retVal = -1; - if (serveraddr.family == AF_INET) + if (serveraddr.family == AF_INET) { retVal = ::connect(sock, (const sockaddr*)&serveraddr.addr_in, serveraddr.length); - else + } else if (serveraddr.family == AF_INET6) { retVal = ::connect(sock, (const sockaddr*)&serveraddr.addr_in6, serveraddr.length); + } memcpy(&remoteAddr, &serveraddr, sizeof(Address)); if (retVal == INVALID_SOCKET) { #ifdef _WIN32 @@ -110,12 +111,6 @@ Socket::Socket(const Socket& other_) { valid_ = false; } -Socket::Socket(Socket&& other_) noexcept { - other_.valid_ = false; - memcpy(this, &other_, sizeof(Socket)); - valid_ = true; -} - Socket& Socket::operator=(const Socket& other_) { memcpy(this, &other_, sizeof(Socket)); valid_ = false; @@ -123,6 +118,12 @@ Socket& Socket::operator=(const Socket& other_) { return *this; } +Socket::Socket(Socket&& other_) noexcept { + other_.valid_ = false; + memcpy(this, &other_, sizeof(Socket)); + valid_ = true; +} + Socket& Socket::operator=(Socket&& other_) noexcept { other_.valid_ = false; memcpy(this, &other_, sizeof(Socket)); diff --git a/impl/socket/tcp_socket.cpp b/impl/socket/tcp_socket.cpp index d113fe2..dd126c1 100644 --- a/impl/socket/tcp_socket.cpp +++ b/impl/socket/tcp_socket.cpp @@ -10,35 +10,17 @@ int TCPSocket::listen(int __n) { return retVal; } -void TCPSocket::accept(TCPSocket &newSock, Address &__addr) { +void TCPSocket::accept(std::shared_ptr &newSock, + Address &__addr) { SOCKET newsock = INVALID_SOCKET; newsock = ::accept(sock, &__addr.addr, &__addr.length); if (newsock == INVALID_SOCKET) { spdlog::error("accept() errno:{} {}", errno, strerror(errno)); std::exit(EXIT_FAILURE); } - newSock.set(newsock, domain); - memcpy(&newSock.remoteAddr, &__addr, sizeof(Address)); -} - -int TCPSocket::connect(Address &serveraddr) { - std::string addr_string = serveraddr; - int retVal = -1; - if (serveraddr.family == AF_INET) - retVal = ::connect(sock, (const sockaddr *)&serveraddr.addr_in, - serveraddr.length); - else - retVal = ::connect(sock, (const sockaddr *)&serveraddr.addr_in6, - serveraddr.length); - memcpy(&remoteAddr, &serveraddr, sizeof(Address)); - if (retVal == INVALID_SOCKET) { -#ifdef _WIN32 - int err = WSAGetLastError(); - spdlog::error("connect() failed: WSA error {} (0x{:X})", err, err); -#endif - spdlog::error("connect()"); - } - return retVal; + newSock = std::make_shared(); + newSock->set(newsock, domain); + newSock->remoteAddr = __addr; } int TCPSocket::recv(void *__restrict __buf, size_t __n, int __flags) { diff --git a/impl/utils/generate_id.cpp b/impl/utils/generate_id.cpp index a62650a..dd2880d 100644 --- a/impl/utils/generate_id.cpp +++ b/impl/utils/generate_id.cpp @@ -9,7 +9,7 @@ static struct EpochInitializer { std::chrono::system_clock::time_point EPOCH; } epochInitializer; -Snowflake GenerateID(std::uint16_t instance) { +Snowflake GenerateID(std::uint8_t instance) { static std::mutex snowflakeGenerateMutex_; std::lock_guard lock(snowflakeGenerateMutex_); diff --git a/impl/utils/utils.cpp b/impl/utils/utils.cpp new file mode 100644 index 0000000..c2de94d --- /dev/null +++ b/impl/utils/utils.cpp @@ -0,0 +1,11 @@ +#include "utils/utils.h" + +namespace utils { + +std::vector CvtListToVector(std::list data) { + std::vector returnValue; + returnValue.insert(returnValue.end(), data.begin(), data.end()); + return returnValue; +} + +} diff --git a/impl/vulkan_engine/asset/object/model.cpp b/impl/vulkan_engine/asset/object/model.cpp index 5790bc8..ce4efc0 100644 --- a/impl/vulkan_engine/asset/object/model.cpp +++ b/impl/vulkan_engine/asset/object/model.cpp @@ -53,7 +53,6 @@ std::vector Model::Serialize() { Append(buffer, angular_acceleration); Append(buffer, scale); - Append(buffer, transform); Append(buffer, original_offset); Append(buffer, radius); @@ -62,6 +61,8 @@ std::vector Model::Serialize() { Append(buffer, visible); Append(buffer, colision); + Append(buffer, lastUpdatedTime); + return buffer; } @@ -81,7 +82,6 @@ void Model::Deserialize(std::vector data) { Read(data, offset, angular_acceleration); Read(data, offset, scale); - Read(data, offset, transform); Read(data, offset, original_offset); Read(data, offset, radius); @@ -89,6 +89,8 @@ void Model::Deserialize(std::vector data) { Read(data, offset, visible); Read(data, offset, colision); + + Read(data, offset, lastUpdatedTime); } void veng::Model::Update(float dt) { diff --git a/impl/vulkan_engine/vulkan/buffers.cpp b/impl/vulkan_engine/vulkan/buffers.cpp index 8ca2b25..5bb0f23 100644 --- a/impl/vulkan_engine/vulkan/buffers.cpp +++ b/impl/vulkan_engine/vulkan/buffers.cpp @@ -170,7 +170,7 @@ void Graphics::RenderIndexedBuffer(BufferHandle vertex_buffer, vkCmdDrawIndexed(frames_[current_frame_].command_buffer, count, 1, 0, 0, 0); SetModelMatrix(glm::mat4(1.f)); } -void Graphics::RenderModel(Model* model) { +void Graphics::RenderModel(std::shared_ptr model) { if (!model->visible) return; SetTexture(model->material.texture_handle); SetModelMatrix(model->transform); diff --git a/impl/vulkan_engine/vulkan/engine.cpp b/impl/vulkan_engine/vulkan/engine.cpp index 4da34ee..0a44003 100644 --- a/impl/vulkan_engine/vulkan/engine.cpp +++ b/impl/vulkan_engine/vulkan/engine.cpp @@ -2,6 +2,7 @@ #include "precomp.h" #include "socket/packet.h" +#include "utils/utils.h" namespace veng { @@ -36,16 +37,18 @@ const Model* Engine::GetStaticModel(std::string name) { return nullptr; } -Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, - std::float_t lifespan) { +std::shared_ptr Engine::SpawnLifedModel(std::string asset_name, + std::string name, + std::float_t lifespan) { if (asset_name == "") { Model model_to_spawn(nullptr); model_to_spawn.asset_name = ""; model_to_spawn.name = name; model_to_spawn.visible = false; model_to_spawn.lifespan = lifespan; - models_[name] = std::move(model_to_spawn); - return &models_[name]; + models_[name] = std::make_shared(model_to_spawn); + model_to_spawn.owner = models_[name]; + return models_[name]; } if (models_.find(name) == models_.end()) { @@ -53,8 +56,9 @@ Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, model_to_spawn.asset_name = asset_name; model_to_spawn.name = name; model_to_spawn.lifespan = lifespan; - models_[name] = std::move(model_to_spawn); - return &models_[name]; + models_[name] = std::make_shared(model_to_spawn); + model_to_spawn.owner = models_[name]; + return models_[name]; } std::uint32_t i = 0; @@ -64,7 +68,10 @@ Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, model_to_spawn.asset_name = asset_name; model_to_spawn.name = name + std::to_string(i); model_to_spawn.lifespan = lifespan; - models_[name + std::to_string(i)] = std::move(model_to_spawn); + + models_[name + std::to_string(i)] = + std::make_shared(model_to_spawn); + model_to_spawn.owner = models_[name + std::to_string(i)]; break; } i++; @@ -73,12 +80,12 @@ Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, if (i == std::numeric_limits::max() - 1) return nullptr; else - return &models_[name + std::to_string(i)]; + return models_[name + std::to_string(i)]; } -Model* Engine::GetSpawnedObject(std::string name) { +std::shared_ptr Engine::GetSpawnedObject(std::string name) { for (auto it = models_.begin(); it != models_.end();) { - if (it->first == name) return &it->second; + if (it->first == name) return it->second; ++it; } @@ -110,149 +117,131 @@ void Engine::Update() { if (Tick != nullptr) Tick(*this, delta_time); - std::vector models; + std::vector> models; models.reserve(models_.size()); for (auto it = models_.begin(); it != models_.end();) { auto& model = it->second; - if (std::abs(model.lifespan + 1.f) < + if (std::abs(model->lifespan + 1.f) < std::numeric_limits::epsilon()) { - models.push_back(&model); + models.push_back(model); ++it; continue; } - if (model.lifespan <= 0.f) { + if (model->lifespan <= 0.f) { it = models_.erase(it); continue; } - if (model.shouldBeDestroyed) { + if (model->shouldBeDestroyed) { it = models_.erase(it); continue; } - model.lifespan -= delta_time; + model->lifespan -= delta_time; - models.push_back(&model); + models.push_back(model); ++it; } for (auto& it : models_) { - it.second.Update(delta_time); - vulkan_graphics->RenderModel(&it.second); + it.second->Update(it.second->lastUpdatedTime + delta_time); + vulkan_graphics->RenderModel(it.second); } - physics_controller_.invokeOnColisionEvent(thread_pool_, - {models.data(), models.size()}); + physics_controller_.invokeOnColisionEvent(thread_pool_, models); vulkan_graphics->EndFrame(); } } void Engine::NetUpdate(std::shared_ptr sock) { NetworkUpload(sock); - ResponseToServerAndRefresh(sock); } void Engine::NetworkUpload(std::shared_ptr sock) { std::vector data; for (auto& it : models_) { - if (!it.second.networkReplicated) continue; - if (!it.second.needsUpdate) continue; + std::lock_guard lock(it.second->modding); + if (!it.second->networkReplicated) continue; + if (!it.second->needsUpdate) continue; Packet::Header header; header.opcode = Packet::Opcode::UPDATEMODEL; - std::vector model = it.second.Serialize(); + header.timestamp = glfwGetTime(); + std::vector model = it.second->Serialize(); header.body_length = model.size(); std::vector header_serialized = header.Serialize(); data.insert(data.end(), header_serialized.begin(), header_serialized.end()); data.insert(data.end(), model.begin(), model.end()); - it.second.needsUpdate = false; + it.second->needsUpdate = false; + spdlog::debug("{} uploaded", it.second->name); } - iocp_->send(*sock, data); + iocp_->send(sock, data); } -int recv_partial(Network::IOCP* iocp, Network::Socket& sock, - std::vector& buffer) { - size_t total_received = 0; - size_t expected = buffer.size(); - - while (total_received < expected) { - if (total_received != 0) - Sleep(100); // 너무 빨리 재시도해서 큐가 채워질 틈이 없는 듯? - if (sock.sock == 0) return 0; - std::vector temp(expected - total_received); - - size_t received = iocp->recv(sock, temp); - if (received == 0) return 0; - - std::copy(temp.begin(), temp.begin() + received, - buffer.begin() + total_received); - total_received += received; - } - - return total_received; +float GetAlpha(double old_time, double new_time) { + return (glfwGetTime() - old_time) / (new_time - old_time); } -void recv_fully(Network::IOCP* iocp, Network::Socket& sock, - std::vector& buffer) { - size_t total_received = 0; - size_t expected = buffer.size(); +void Interpolation(Packet::Header header, std::shared_ptr local, + std::shared_ptr remote) { + std::lock_guard lock(local->modding); + local->position = + glm::mix(local->position, remote->position, + GetAlpha(local->lastUpdatedTime, header.timestamp)); + local->linear_velocity = + glm::mix(local->linear_velocity, remote->linear_velocity, + GetAlpha(local->lastUpdatedTime, header.timestamp)); + local->linear_acceleration = + glm::mix(local->linear_acceleration, remote->linear_acceleration, + GetAlpha(local->lastUpdatedTime, header.timestamp)); - while (total_received < expected) { - if (total_received != 0) - Sleep(100); // 너무 빨리 재시도해서 큐가 채워질 틈이 없는 듯? - if (sock.sock == 0) return; - std::vector temp(expected - total_received); + local->rotation = + glm::mix(local->rotation, remote->rotation, + GetAlpha(local->lastUpdatedTime, header.timestamp)); + local->angular_velocity = + glm::mix(local->angular_velocity, remote->angular_velocity, + GetAlpha(local->lastUpdatedTime, header.timestamp)); + local->angular_acceleration = + glm::mix(local->angular_acceleration, remote->angular_acceleration, + GetAlpha(local->lastUpdatedTime, header.timestamp)); - size_t received = iocp->recv(sock, temp); + local->scale = glm::mix(local->scale, remote->scale, + GetAlpha(local->lastUpdatedTime, header.timestamp)); - std::copy(temp.begin(), temp.begin() + received, - buffer.begin() + total_received); - total_received += received; - } + local->original_offset = remote->original_offset; + local->radius = remote->radius; + local->lifespan = remote->lifespan; + + local->visible = remote->visible; + local->colision = remote->colision; } void Engine::ResponseToServerAndRefresh(std::shared_ptr sock) { if (sock->sock == 0) return; - std::vector recv_data(6); - if (recv_partial(iocp_, *sock, recv_data) == 0) return; + + auto result = iocp_->recv(sock, 14); + auto recv_data = utils::CvtListToVector(result.get()); // 여기서 막혀서 프로그램이 리턴을 못하는 문제가 있음.. + Packet::Header header; header.Deserialize(recv_data); - recv_data.resize(header.body_length); - recv_fully(iocp_, *sock, recv_data); + + result = iocp_->recv(sock, header.body_length); + recv_data = utils::CvtListToVector(result.get()); switch (header.opcode) { case Packet::Opcode::UPDATEMODEL: { - veng::Model model; - model.Deserialize(recv_data); + std::shared_ptr model = std::make_shared(); + model->Deserialize(recv_data); bool found = false; for (auto& it : models_) { - if (it.second.ID == model.ID) { - it.second.position = model.position; - it.second.linear_velocity = model.linear_velocity; - it.second.linear_acceleration = model.linear_acceleration; - - it.second.rotation = model.rotation; - it.second.angular_velocity = model.angular_velocity; - it.second.angular_acceleration = model.angular_acceleration; - - it.second.scale = model.scale; - it.second.transform = model.transform; - - it.second.original_offset = model.original_offset; - it.second.radius = model.radius; - it.second.lifespan = model.lifespan; - - it.second.visible = model.visible; - it.second.colision = model.colision; - - spdlog::info("model updated: {}", model.name); - spdlog::info("model pos: ({},{},{})", model.position.x, - model.position.y, model.position.z); + if (it.second->ID == model->ID) { + Interpolation(header, it.second, model); + spdlog::debug("model updated: [{}:{}]", model->name, model->ID.snowflake); found = true; break; } @@ -260,32 +249,38 @@ void Engine::ResponseToServerAndRefresh(std::shared_ptr sock) { if (!found) { auto spawnedModel = - SpawnLifedModel(model.asset_name, model.name, model.lifespan); - spawnedModel->ID = model.ID; - spawnedModel->position = model.position; - spawnedModel->linear_velocity = model.linear_velocity; - spawnedModel->linear_acceleration = model.linear_acceleration; + SpawnLifedModel(model->asset_name, model->name, model->lifespan); + std::lock_guard lock(spawnedModel->modding); + spawnedModel->ID = model->ID; + spawnedModel->position = model->position; + spawnedModel->linear_velocity = model->linear_velocity; + spawnedModel->linear_acceleration = model->linear_acceleration; - spawnedModel->rotation = model.rotation; - spawnedModel->angular_velocity = model.angular_velocity; - spawnedModel->angular_acceleration = model.angular_acceleration; + spawnedModel->rotation = model->rotation; + spawnedModel->angular_velocity = model->angular_velocity; + spawnedModel->angular_acceleration = model->angular_acceleration; - spawnedModel->scale = model.scale; - spawnedModel->transform = model.transform; + spawnedModel->scale = model->scale; + spawnedModel->transform = model->transform; - spawnedModel->original_offset = model.original_offset; - spawnedModel->radius = model.radius; - spawnedModel->lifespan = model.lifespan; + spawnedModel->original_offset = model->original_offset; + spawnedModel->radius = model->radius; + spawnedModel->lifespan = model->lifespan; - spawnedModel->visible = model.visible; - spawnedModel->colision = model.colision; + spawnedModel->visible = model->visible; + spawnedModel->colision = model->colision; spawnedModel->networkReplicated = false; - spdlog::info("model spawned: {}", model.ID.snowflake); + spdlog::info("model spawned: {}", model->ID.snowflake); } } break; default: spdlog::error("unknown data type"); } + thread_pool_->enqueueJob( + [this, sock](utils::ThreadPool* tp, std::uint32_t __) { + ResponseToServerAndRefresh(sock); + }, + 0); } } // namespace veng diff --git a/impl/vulkan_engine/vulkan/physics.cpp b/impl/vulkan_engine/vulkan/physics.cpp index 057a48c..39f8b9f 100644 --- a/impl/vulkan_engine/vulkan/physics.cpp +++ b/impl/vulkan_engine/vulkan/physics.cpp @@ -5,34 +5,36 @@ namespace veng { void Physics::invokeOnColisionEvent( - gsl::not_null thread_pool, gsl::span models) { + gsl::not_null thread_pool, std::vector> models) { constexpr std::float_t EPSILON = std::numeric_limits::epsilon(); for (int first = 0; first < models.size(); first++) { - if (!models[first]->colision) continue; + auto first_model = models[first]; + if (first_model != nullptr || !first_model->colision) continue; for (int second = first + 1; second < models.size(); second++) { - if (!models[second]->colision) continue; + auto second_model = models[second]; + if (second_model != nullptr || !second_model->colision) continue; std::float_t distance = - glm::distance(models[first]->position, models[second]->position); - std::float_t model1_radius = - models[first]->radius * models[first]->scale.x; - std::float_t model2_radius = - models[second]->radius * models[second]->scale.x; + glm::distance(first_model->position, second_model->position); + std::float_t model1_radius = first_model->radius * first_model->scale.x; + std::float_t model2_radius = second_model->radius * second_model->scale.x; if (distance <= model1_radius + model2_radius) { - if (models[first]->OnColision != nullptr) + if (first_model->OnColision != nullptr) thread_pool->enqueueJob( - [OnColision = models[first]->OnColision]( - utils::ThreadPool* thread_pool, Model* self, Model* other) { + [OnColision = first_model->OnColision]( + utils::ThreadPool* thread_pool, std::shared_ptr self, + std::shared_ptr other) { OnColision(self, other); }, - models[first], models[second]); - if (models[second]->OnColision != nullptr) + first_model, second_model); + if (second_model->OnColision != nullptr) thread_pool->enqueueJob( - [OnColision = models[second]->OnColision]( - utils::ThreadPool* thread_pool, Model* self, Model* other) { + [OnColision = second_model->OnColision]( + utils::ThreadPool* thread_pool, std::shared_ptr self, + std::shared_ptr other) { OnColision(self, other); }, - models[second], models[first]); + first_model, second_model); break; } } diff --git a/include/socket/address.h b/include/socket/address.h index d479347..ce1f6a4 100644 --- a/include/socket/address.h +++ b/include/socket/address.h @@ -10,6 +10,9 @@ struct Address { void set(int type, gsl::czstring presentationAddr, std::uint16_t port); void setType(int type); + Address(const Address&) = default; + Address& operator=(const Address&) = default; + operator std::string(); std::uint16_t getPort() const; diff --git a/include/socket/iocp.h b/include/socket/iocp.h index 18eb387..6a82d4e 100644 --- a/include/socket/iocp.h +++ b/include/socket/iocp.h @@ -24,80 +24,10 @@ typedef struct __WSABUF { namespace Network { -class IOCP; +struct IOCPPASSINDATA; -enum class IOCPEVENT { QUIT, READ, WRITE }; - -struct IOCPPASSINDATA { - OVERLAPPED overlapped; - IOCPEVENT event; - std::shared_ptr socket; - std::uint32_t transferredbytes; - WSABUF wsabuf; - std::uint32_t bufsize; - IOCP* IOCPInstance; -#ifdef __linux__ - std::shared_ptr> sendQueue; -#endif - - IOCPPASSINDATA(std::uint32_t bufsize) { - std::memset(&overlapped, 0, sizeof(overlapped)); - event = IOCPEVENT::QUIT; - socket = nullptr; - transferredbytes = 0; - this->bufsize = bufsize; - IOCPInstance = nullptr; - - wsabuf.buf = new char[bufsize]; - wsabuf.len = bufsize; - } - - /*IOCPPASSINDATA(const IOCPPASSINDATA& other) { - if (this != &other) { - std::memset(&overlapped, 0, sizeof(overlapped)); - event = other.event; - socket = other.socket; - ssl = other.ssl; - transferredbytes = other.transferredbytes; - bufsize = other.bufsize; - IOCPInstance = other.IOCPInstance; -#ifdef __linux__ - sendQueue = other.sendQueue; -#endif - wsabuf.buf = new char[other.bufsize]; - wsabuf.len = other.bufsize; - std::memcpy(wsabuf.buf, other.wsabuf.buf, other.wsabuf.len); - } - }*/ - - ~IOCPPASSINDATA() { - if (wsabuf.buf != nullptr) delete[] wsabuf.buf; - wsabuf.buf = nullptr; - } - - /*IOCPPASSINDATA& operator=(const IOCPPASSINDATA& other) { - if (this != &other) { - std::memset(&overlapped, 0, sizeof(overlapped)); - event = other.event; - socket = other.socket; - ssl = other.ssl; - transferredbytes = other.transferredbytes; - bufsize = other.bufsize; - IOCPInstance = other.IOCPInstance; -#ifdef __linux__ - sendQueue = other.sendQueue; -#endif - if (wsabuf.buf != nullptr) delete[] wsabuf.buf; - wsabuf.buf = new char[other.bufsize]; - wsabuf.len = other.bufsize; - std::memcpy(wsabuf.buf, other.wsabuf.buf, other.wsabuf.len); - } - return *this; - }*/ - - IOCPPASSINDATA(const IOCPPASSINDATA& other) = delete; - IOCPPASSINDATA& operator=(const IOCPPASSINDATA&) = delete; -}; +std::list DEFAULT_RECVALL_CALLBACK(utils::ThreadPool* th, + IOCPPASSINDATA* data); class IOCP { public: @@ -108,15 +38,26 @@ class IOCP { void destruct(); - void registerTCPSocket(Socket& sock, std::uint32_t bufsize); - void registerUDPSocket(IOCPPASSINDATA* data, Address recv_addr); + void registerSocket(std::shared_ptr sock); - int recv(Socket& sock, std::vector& data); + std::future> recvFull( + std::shared_ptr sock, std::uint32_t bufsize); + + std::future> recv( + std::shared_ptr sock, std::uint32_t bufsize, + std::function(utils::ThreadPool*, IOCPPASSINDATA*)> + callback = DEFAULT_RECVALL_CALLBACK); // data는 한 가지 소켓에 보내는 패킷만 담아야 합니다 - int send(Socket& sock, std::vector& data); + int send(std::shared_ptr sock, std::vector& data); int GetRecvedBytes(SOCKET sock); + std::shared_ptr> GetSendQueue(SOCKET sock); + std::shared_ptr, std::uint32_t>>> + GetRecvQueue(SOCKET sock); + std::shared_ptr GetSendQueueMutex(SOCKET sock); + std::shared_ptr GetRecvQueueMutex(SOCKET sock); + private: #ifdef _WIN32 void iocpWatcher_(utils::ThreadPool* IOCPThread); @@ -124,12 +65,6 @@ class IOCP { #endif - std::shared_ptr> GetSendQueue_(SOCKET sock); - std::shared_ptr, std::uint32_t>>> - GetRecvQueue_(SOCKET sock); - std::shared_ptr GetSendQueueMutex_(SOCKET sock); - std::shared_ptr GetRecvQueueMutex_(SOCKET sock); - void packet_sender_(SOCKET sock); utils::ThreadPool* IOCPThread_; @@ -182,4 +117,56 @@ class IOCP { #endif }; +enum class IOCPEVENT { QUIT, READ, WRITE }; + +struct IOCPPASSINDATA { + OVERLAPPED overlapped; + IOCPEVENT event; + std::shared_ptr socket; + std::uint32_t transferredbytes; + WSABUF wsabuf; + IOCP* IOCPInstance; + std::packaged_task(utils::ThreadPool*, IOCPPASSINDATA*)> + callback; +#ifdef __linux__ + std::shared_ptr> sendQueue; +#endif + IOCPPASSINDATA(std::shared_ptr socket, std::uint32_t bufsize, + IOCP* IOCPInstance) + : event(IOCPEVENT::QUIT), + socket(socket), + transferredbytes(0), + IOCPInstance(IOCPInstance) { + std::memset(&overlapped, 0, sizeof(overlapped)); + + wsabuf.buf = new char[bufsize]; + wsabuf.len = bufsize; + } + + IOCPPASSINDATA( + std::shared_ptr socket, std::uint32_t bufsize, IOCP* IOCPInstance, + std::packaged_task(utils::ThreadPool*, IOCPPASSINDATA*)> + callback_) + : event(IOCPEVENT::QUIT), + socket(socket), + transferredbytes(0), + IOCPInstance(IOCPInstance), + callback(std::move(callback_)) { + std::memset(&overlapped, 0, sizeof(overlapped)); + + wsabuf.buf = new char[bufsize]; + wsabuf.len = bufsize; + } + + ~IOCPPASSINDATA() { + if (wsabuf.buf != nullptr) delete[] wsabuf.buf; + wsabuf.buf = nullptr; + } + + IOCPPASSINDATA(const IOCPPASSINDATA& other) = delete; + IOCPPASSINDATA& operator=(const IOCPPASSINDATA&) = delete; + IOCPPASSINDATA(IOCPPASSINDATA&&) = default; + IOCPPASSINDATA& operator=(IOCPPASSINDATA&&) = default; +}; + } // namespace Network diff --git a/include/socket/packet.h b/include/socket/packet.h index ea3297c..d12c051 100644 --- a/include/socket/packet.h +++ b/include/socket/packet.h @@ -16,18 +16,21 @@ enum class Opcode : std::uint16_t { struct Header { Opcode opcode; + double timestamp; std::uint32_t body_length; std::vector Serialize() { - std::vector serialize(6); + std::vector serialize(14); ::memcpy(serialize.data(), &opcode, 2); - ::memcpy(serialize.data() + 2, &body_length, 4); + ::memcpy(serialize.data() + 2, ×tamp, 8); + ::memcpy(serialize.data() + 10, &body_length, 4); return serialize; } void Deserialize(std::vector& data) { ::memcpy(&opcode, data.data(), 2); - ::memcpy(&body_length, data.data() + 2, 4); + ::memcpy(×tamp, data.data() + 2, 8); + ::memcpy(&body_length, data.data() + 10, 4); } }; diff --git a/include/socket/socket.h b/include/socket/socket.h index 017f64f..5456777 100644 --- a/include/socket/socket.h +++ b/include/socket/socket.h @@ -26,8 +26,9 @@ class Socket { int sendto(const void* __buf, size_t __n, int __flags, struct Address __addr); Socket(const Socket&); - Socket(Socket&&) noexcept; Socket& operator=(const Socket&); + + Socket(Socket&&) noexcept; Socket& operator=(Socket&&) noexcept; struct Address bindAddr = {}; diff --git a/include/socket/tcp_socket.h b/include/socket/tcp_socket.h index 0f3f3ae..357ba0f 100644 --- a/include/socket/tcp_socket.h +++ b/include/socket/tcp_socket.h @@ -9,8 +9,7 @@ class TCPSocket : public Socket { using Socket::Socket; int init(int domain); int listen(int __n); - void accept(TCPSocket& newSock, Address& addr); - int connect(Network::Address& serveraddr); + void accept(std::shared_ptr& newSock, Address& addr); int recv(void* __restrict __buf, size_t __n, int __flags); int send(const void* __buf, size_t __n, int __flags); }; diff --git a/include/utils/snowflake.h b/include/utils/snowflake.h index 1ff4a8c..05f3b7a 100644 --- a/include/utils/snowflake.h +++ b/include/utils/snowflake.h @@ -18,14 +18,13 @@ struct Snowflake { } std::vector Serialize() { - std::vector serialized; - serialized.insert(serialized.end(), &snowflake, - &snowflake + sizeof(snowflake)); + std::vector serialized(8); + ::memcpy(serialized.data(), &snowflake, 8); return serialized; } }; -Snowflake GenerateID(std::uint16_t instance); +Snowflake GenerateID(std::uint8_t instance); } // namespace Chattr diff --git a/include/utils/utils.h b/include/utils/utils.h new file mode 100644 index 0000000..e5f2d9c --- /dev/null +++ b/include/utils/utils.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include + +namespace utils { + +std::vector CvtListToVector(std::list data); + +} // namespace std diff --git a/include/vulkan_engine/asset/object/model.h b/include/vulkan_engine/asset/object/model.h index 8c55ca6..a47aa1b 100644 --- a/include/vulkan_engine/asset/object/model.h +++ b/include/vulkan_engine/asset/object/model.h @@ -5,20 +5,25 @@ #include #include "material.h" +#include "utils/snowflake.h" #include "vulkan_engine/vulkan/buffer_handle.h" #include "vulkan_engine/vulkan/vertex.h" -#include "utils/snowflake.h" extern std::uint8_t CLIENTID; namespace veng { struct Model { - Model() : graphics_(nullptr) {} - Model(class Graphics* graphics) : graphics_(graphics) {} + Model() : ID(utils::GenerateID(CLIENTID)), graphics_(nullptr) { + } + Model(class Graphics* graphics) + : ID(utils::GenerateID(CLIENTID)), graphics_(graphics) { + } ~Model(); Model(const Model& other) - : asset_name(other.asset_name), + : ID(utils::GenerateID(CLIENTID)), + name(/*"_" + */other.name), + asset_name(other.asset_name), vertices(other.vertices), vertex_buffer(other.vertex_buffer), indices(other.indices), @@ -39,14 +44,14 @@ struct Model { OnColision(other.OnColision), visible(other.visible), colision(other.colision), - networkReplicated(other.networkReplicated) { - name = "_" + other.name; - ID = utils::GenerateID(CLIENTID); + networkReplicated(other.networkReplicated), + lastUpdatedTime(other.lastUpdatedTime) { graphics_ = nullptr; } Model(Model&& other) - : name(other.name), + : ID(other.ID), + name(other.name), asset_name(other.asset_name), vertices(std::move(other.vertices)), vertex_buffer(std::move(other.vertex_buffer)), @@ -68,9 +73,8 @@ struct Model { OnColision(other.OnColision), visible(other.visible), colision(other.colision), - networkReplicated(other.networkReplicated) - { - ID = other.ID; + networkReplicated(other.networkReplicated), + lastUpdatedTime(other.lastUpdatedTime) { ::memset(&other.ID, 0, 8); graphics_ = other.graphics_; @@ -104,6 +108,7 @@ struct Model { visible = other.visible; colision = other.colision; networkReplicated = other.networkReplicated; + lastUpdatedTime = other.lastUpdatedTime; graphics_ = other.graphics_; other.graphics_ = nullptr; @@ -141,13 +146,14 @@ struct Model { glm::vec3 original_offset = glm::vec3(0.f); - Model* owner = this; + std::weak_ptr owner; std::float_t radius = 0.f; std::float_t lifespan = -1.f; - std::function OnColision = nullptr; + std::function self, std::shared_ptr other)> + OnColision = nullptr; bool visible = true; bool colision = false; @@ -156,6 +162,10 @@ struct Model { bool needsUpdate = true; + double lastUpdatedTime = 0.f; // 서버 기준 업데이트된 시간임 + + std::mutex modding; + private: class Graphics* graphics_; }; diff --git a/include/vulkan_engine/vulkan/engine.h b/include/vulkan_engine/vulkan/engine.h index 23ab29f..bd2d275 100644 --- a/include/vulkan_engine/vulkan/engine.h +++ b/include/vulkan_engine/vulkan/engine.h @@ -20,9 +20,9 @@ class Engine { const Model* GetStaticModel(std::string name); // 수명을 무제한으로 놓고 싶으면 lifespan을 -1으로 설정하면 됨 - Model* SpawnLifedModel(std::string asset_name, std::string name, + std::shared_ptr SpawnLifedModel(std::string asset_name, std::string name, std::float_t lifespan); - Model* GetSpawnedObject(std::string name); + std::shared_ptr GetSpawnedObject(std::string name); void Update(); void NetUpdate(std::shared_ptr sock); @@ -53,7 +53,7 @@ class Engine { std::unordered_map model_assets_; - std::unordered_map models_; + std::unordered_map> models_; }; } // namespace veng diff --git a/include/vulkan_engine/vulkan/graphics.h b/include/vulkan_engine/vulkan/graphics.h index 60de666..1e57e26 100644 --- a/include/vulkan_engine/vulkan/graphics.h +++ b/include/vulkan_engine/vulkan/graphics.h @@ -33,7 +33,7 @@ class Graphics final { void RenderBuffer(BufferHandle handle, std::uint32_t vertex_count); void RenderIndexedBuffer(BufferHandle vertex_buffer, BufferHandle index_buffer, std::uint32_t count); - void RenderModel(struct Model* model); + void RenderModel(std::shared_ptr model); void EndFrame(); BufferHandle CreateVertexBuffer(gsl::span vertices); diff --git a/include/vulkan_engine/vulkan/physics.h b/include/vulkan_engine/vulkan/physics.h index 3214b91..d1a24ac 100644 --- a/include/vulkan_engine/vulkan/physics.h +++ b/include/vulkan_engine/vulkan/physics.h @@ -7,7 +7,8 @@ namespace veng { class Physics { public: - void invokeOnColisionEvent(gsl::not_null thread_pool, gsl::span models); + void invokeOnColisionEvent(gsl::not_null thread_pool, + std::vector> models); bool RayTrace(const glm::vec3& rayOrigin, const glm::vec3& rayDir, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2,