diff --git a/Client/src/asteroid/begin_play.cpp b/Client/src/asteroid/begin_play.cpp index 3e60a29..d587f49 100644 --- a/Client/src/asteroid/begin_play.cpp +++ b/Client/src/asteroid/begin_play.cpp @@ -2,8 +2,14 @@ #include "vulkan_engine/vulkan/engine.h" + void BeginPlay(veng::Engine& engine) { - veng::Model* const player = engine.SpawnModel("player", "player"); + std::random_device rd; + std::mt19937 gen = std::mt19937(rd()); + 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) { @@ -15,16 +21,17 @@ void BeginPlay(veng::Engine& engine) { other->colision = false; other->visible = false; + other->shouldBeDestroyed = true; }; veng::Model* const player_flame = - engine.SpawnModel("player_flame", "player_flame"); + engine.SpawnLifedModel("player_flame", "player_flame", -1); player_flame->scale = player->scale; player_flame->colision = false; player_flame->networkReplicated = false; spdlog::info("player addr: {}", (void*)player); - veng::Model* const other_player = engine.SpawnModel("player", "other_player"); + 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; @@ -37,34 +44,35 @@ void BeginPlay(veng::Engine& engine) { other->colision = false; other->visible = false; + other->shouldBeDestroyed = true; }; spdlog::info("other player addr: {}", (void*)other_player); - veng::Model* const camera_lag = engine.SpawnModel("", "camera_lag"); + veng::Model* const camera_lag = engine.SpawnLifedModel("", "camera_lag", -1); camera_lag->colision = false; camera_lag->position = player->position; - veng::Model* const background = engine.SpawnModel("", "background"); + 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 = - engine.SpawnModel("background", "background0"); + engine.SpawnLifedModel("background", "background0", -1); background0->scale = background->scale; background0->networkReplicated = false; veng::Model* const background1 = - engine.SpawnModel("background", "background1"); + engine.SpawnLifedModel("background", "background1", -1); background1->scale = background->scale; background1->networkReplicated = false; veng::Model* const background2 = - engine.SpawnModel("background", "background2"); + engine.SpawnLifedModel("background", "background2", -1); background2->scale = background->scale; background2->networkReplicated = false; veng::Model* const background3 = - engine.SpawnModel("background", "background3"); + engine.SpawnLifedModel("background", "background3", -1); background3->scale = background->scale; background3->networkReplicated = false; } diff --git a/Client/src/asteroid/main.cpp b/Client/src/asteroid/main.cpp index 86d5461..9154b38 100644 --- a/Client/src/asteroid/main.cpp +++ b/Client/src/asteroid/main.cpp @@ -28,26 +28,29 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { addr.set(AF_INET6, "::1", 9010); - Network::Socket sock; Network::TCPSocket TCPSock; TCPSock.init(AF_INET6); - sock = TCPSock; - if (sock.connect(addr) == INVALID_SOCKET) { + if (TCPSock.connect(addr) == INVALID_SOCKET) { spdlog::error("connect()"); std::exit(EXIT_FAILURE); } - iocp.registerTCPSocket(sock, 16 * 1024); + iocp.registerTCPSocket(TCPSock, 16 * 1024); - while (iocp.GetRecvedBytes(sock.sock) < 6); + while (iocp.GetRecvedBytes(TCPSock.sock) < 6); std::vector header_serialized(6); - iocp.recv(sock, header_serialized); + iocp.recv(TCPSock, header_serialized); Packet::Header header; header.Deserialize(header_serialized); - while (iocp.GetRecvedBytes(sock.sock) < header.body_length); + while (iocp.GetRecvedBytes(TCPSock.sock) < header.body_length); std::vector data(header.body_length); - iocp.recv(sock, data); + 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); + const veng::GlfwInitialization _glfw; veng::Window window("Vulkan Engine", {800, 600}); @@ -70,7 +73,7 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) { glfwPollEvents(); engine.Update(); - engine.NetUpdate(std::make_shared(sock)); + engine.NetUpdate(std::make_shared(TCPSock)); } return EXIT_SUCCESS; diff --git a/Client/src/asteroid/tick.cpp b/Client/src/asteroid/tick.cpp index 3a2bf7e..3a3d90d 100644 --- a/Client/src/asteroid/tick.cpp +++ b/Client/src/asteroid/tick.cpp @@ -31,17 +31,27 @@ void Tick(veng::Engine& engine, std::float_t delta_time) { (-stiffness * displacement - damping * camera_lag->linear_velocity) * delta_time; + camera_lag->linear_velocity = glm::vec3(0); + camera_lag->position = player->position; + engine.view = glm::lookAt( glm::vec3(camera_lag->position.x, camera_lag->position.y, -5.f), camera_lag->position, glm::vec3(0.f, -1.f, 0.f)); + static bool w_laststate = false; if (glfwGetKey(engine.vulkan_graphics->window->GetHandle(), GLFW_KEY_W) == GLFW_PRESS) { player->linear_acceleration = glm::normalize(forward) * 10.f; player_flame->visible = true; + player->needsUpdate = true; + w_laststate = true; } else { player->linear_acceleration = forward * .0f; player_flame->visible = false; + if (w_laststate) { + player->needsUpdate = true; + w_laststate = false; + } } if (bullet_cooldown > std::numeric_limits::epsilon()) { @@ -60,21 +70,33 @@ void Tick(veng::Engine& engine, std::float_t delta_time) { bullet->owner = player; bullet->scale = player->scale; bullet->colision = true; + bullet->networkReplicated = true; + bullet->needsUpdate = true; spdlog::info("bullet address: {}", (void*)bullet); } } + + static bool ad_laststate = false; if (glfwGetKey(engine.vulkan_graphics->window->GetHandle(), GLFW_KEY_A) == GLFW_PRESS) { right = player->rotation * glm::vec3(0, 0, 1); player->angular_velocity = right * 6.f; + 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; } else { right = player->rotation * glm::vec3(0, 0, 1); player->angular_velocity = right * 0.f; + if (ad_laststate) { + player->needsUpdate = true; + ad_laststate = false; + } } player_flame->rotation = player->rotation; diff --git a/Server/src/server.cpp b/Server/src/server.cpp index f7b3e10..600b389 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -1,5 +1,6 @@ -#include - +#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" @@ -15,19 +16,37 @@ std::uint8_t CLIENTID = 0; std::unordered_map MODELS; std::mutex MODELS_MUTEX; -std::vector CLIENTS; +std::vector> 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) { - while (iocp->GetRecvedBytes(NewSock.sock) < 6); + Network::TCPSocket* NewSock, Network::Address NewAddr) { + if (NewSock->sock == 0) return; std::vector recv_data(6); - iocp->recv(NewSock, recv_data); + recv_fully(iocp, *NewSock, recv_data); Packet::Header header; header.Deserialize(recv_data); recv_data.resize(header.body_length); - while (iocp->GetRecvedBytes(NewSock.sock) < header.body_length); - iocp->recv(NewSock, recv_data); + recv_fully(iocp, *NewSock, recv_data); switch (header.opcode) { case Packet::Opcode::UPDATEMODEL: { @@ -35,24 +54,97 @@ void EchoClient(utils::ThreadPool* tp, Network::IOCP* iocp, model.Deserialize(recv_data); std::lock_guard lock(MODELS_MUTEX); - if (MODELS.find(model.ID) == MODELS.end()) - spdlog::info("model received: {}", model.ID.snowflake); - MODELS[model.ID] = std::move(model); - } - break; + 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"); } - // iocp->send(NewSock, recv_data); - tp->enqueueJob(EchoClient, iocp, NewSock, NewAddr); } +void ClientRefresher(utils::ThreadPool* tp, Network::IOCP* iocp) { + static auto last_all_updated = glfwGetTime(); + static auto last_frame_time_ = glfwGetTime(); + auto current_time = glfwGetTime(); + bool needs_all_update = false; + if (current_time - last_all_updated >= 100) { + needs_all_update = true; + last_all_updated = glfwGetTime(); + } + auto delta_time = current_time - last_frame_time_; + last_frame_time_ = current_time; + + for (auto it = CLIENTS.begin(); it != CLIENTS.end();) { + if (it->first.sock == 0) { + it = CLIENTS.erase(it); + } else { + ++it; + } + } + + 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; + } + + for (auto& client : CLIENTS) { + if (client.first.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)); + auto model_serialized = model.second.Serialize(); + Packet::Header header; + header.opcode = Packet::Opcode::UPDATEMODEL; + 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 (client.first.send(send_data.data(), send_data.size(), 0) == -1) { + client.first.sock = 0; + } + spdlog::info("updated: {}", model.second.name); + } + } + + 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, 2); + utils::setDefaultLogger(spdlog::level::level_enum::debug, "log.log", + 1024 * 1024, 2); #endif utils::ThreadPool tp(0); Network::IOCP iocp; @@ -75,6 +167,8 @@ int main(int argc, char* argv[]) { std::exit(EXIT_FAILURE); } + tp.enqueueJob(ClientRefresher, &iocp); + while (true) { Network::TCPSocket NewSock; Network::Address NewAddr; @@ -86,15 +180,22 @@ int main(int argc, char* argv[]) { Packet::Header header; header.opcode = Packet::Opcode::CLIENTID; - header.body_length = 8; + header.body_length = 9; auto packet = header.Serialize(); - packet.resize(packet.size() + 8); + packet.resize(packet.size() + 9); std::lock_guard lock(CLIENTS_MUTEX); - CLIENTS.push_back(NewSock); std::uint8_t client_id = CLIENTS.size() - 1; ::memcpy(packet.data() + 6, &client_id, 1); - iocp.send(NewSock, packet); - tp.enqueueJob(EchoClient, &iocp, NewSock, NewAddr); + 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); } } diff --git a/impl/socket/iocp.cpp b/impl/socket/iocp.cpp index 8d6c82e..d83c23e 100644 --- a/impl/socket/iocp.cpp +++ b/impl/socket/iocp.cpp @@ -255,6 +255,8 @@ void IOCP::iocpWatcher_(utils::ThreadPool* IOCPThread) { ::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( diff --git a/impl/socket/socket.cpp b/impl/socket/socket.cpp index 816388c..e3716fc 100644 --- a/impl/socket/socket.cpp +++ b/impl/socket/socket.cpp @@ -28,6 +28,7 @@ void Socket::destruct() { ::close(sock); #endif valid_ = false; + sock = 0; } Socket::operator SOCKET() { diff --git a/impl/vulkan_engine/asset/object/model.cpp b/impl/vulkan_engine/asset/object/model.cpp index 2e192ab..5790bc8 100644 --- a/impl/vulkan_engine/asset/object/model.cpp +++ b/impl/vulkan_engine/asset/object/model.cpp @@ -18,16 +18,31 @@ void Append(std::vector& buffer, const T& value) { buffer.insert(buffer.end(), data, data + sizeof(T)); } +void Append(std::vector& buffer, const std::string& value) { + size_t length = value.size(); + Append(buffer, length); + buffer.insert(buffer.end(), value.begin(), value.end()); +} + template void Read(const std::vector& buffer, size_t& offset, T& out) { std::memcpy(&out, buffer.data() + offset, sizeof(T)); offset += sizeof(T); } +void Read(const std::vector& buffer, size_t& offset, std::string& out) { + size_t length = 0; + Read(buffer, offset, length); + out.assign(buffer.data() + offset, length); + offset += length; +} + std::vector Model::Serialize() { std::vector buffer; Append(buffer, ID); + Append(buffer, name); + Append(buffer, asset_name); Append(buffer, position); Append(buffer, linear_velocity); @@ -54,6 +69,8 @@ void Model::Deserialize(std::vector data) { size_t offset = 0; Read(data, offset, ID); + Read(data, offset, name); + Read(data, offset, asset_name); Read(data, offset, position); Read(data, offset, linear_velocity); diff --git a/impl/vulkan_engine/vulkan/engine.cpp b/impl/vulkan_engine/vulkan/engine.cpp index 9ddbe3e..4da34ee 100644 --- a/impl/vulkan_engine/vulkan/engine.cpp +++ b/impl/vulkan_engine/vulkan/engine.cpp @@ -36,40 +36,12 @@ const Model* Engine::GetStaticModel(std::string name) { return nullptr; } -Model* Engine::SpawnModel(std::string asset_name, std::string name) { - if (asset_name == "") { - Model model_to_spawn(nullptr); - model_to_spawn.visible = false; - models_[name] = std::move(model_to_spawn); - return &models_[name]; - } - - if (models_.find(name) == models_.end()) { - Model model_to_spawn(*GetStaticModel(asset_name)); - models_[name] = std::move(model_to_spawn); - return &models_[name]; - } - - std::uint32_t i = 0; - for (i = 0; i < std::numeric_limits::max();) { - if (models_.find(name + std::to_string(i)) == models_.end()) { - Model model_to_spawn(*GetStaticModel(asset_name)); - models_[name + std::to_string(i)] = std::move(model_to_spawn); - break; - } - i++; - } - - if (i == std::numeric_limits::max() - 1) - return nullptr; - else - return &models_[name + std::to_string(i)]; -} - Model* 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); @@ -78,6 +50,8 @@ Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, if (models_.find(name) == models_.end()) { Model model_to_spawn(*GetStaticModel(asset_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]; @@ -87,6 +61,8 @@ Model* Engine::SpawnLifedModel(std::string asset_name, std::string name, for (i = 0; i < std::numeric_limits::max();) { if (models_.find(name + std::to_string(i)) == models_.end()) { Model model_to_spawn(*GetStaticModel(asset_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); break; @@ -152,6 +128,11 @@ void Engine::Update() { continue; } + if (model.shouldBeDestroyed) { + it = models_.erase(it); + continue; + } + model.lifespan -= delta_time; models.push_back(&model); @@ -178,6 +159,7 @@ void Engine::NetworkUpload(std::shared_ptr sock) { std::vector data; for (auto& it : models_) { if (!it.second.networkReplicated) continue; + if (!it.second.needsUpdate) continue; Packet::Header header; header.opcode = Packet::Opcode::UPDATEMODEL; @@ -187,19 +169,123 @@ void Engine::NetworkUpload(std::shared_ptr sock) { data.insert(data.end(), header_serialized.begin(), header_serialized.end()); data.insert(data.end(), model.begin(), model.end()); + it.second.needsUpdate = false; } 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; +} + +void recv_fully(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; + 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 Engine::ResponseToServerAndRefresh(std::shared_ptr sock) { - while (iocp_->GetRecvedBytes(sock->sock) < 6); + if (sock->sock == 0) return; std::vector recv_data(6); - iocp_->recv(*sock, recv_data); + if (recv_partial(iocp_, *sock, recv_data) == 0) return; Packet::Header header; header.Deserialize(recv_data); recv_data.resize(header.body_length); - while (iocp_->GetRecvedBytes(sock->sock) < header.body_length); - iocp_->recv(*sock, recv_data); + recv_fully(iocp_, *sock, recv_data); + + switch (header.opcode) { + case Packet::Opcode::UPDATEMODEL: { + veng::Model model; + 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); + found = true; + break; + } + } + + 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; + + 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->original_offset = model.original_offset; + spawnedModel->radius = model.radius; + spawnedModel->lifespan = model.lifespan; + + spawnedModel->visible = model.visible; + spawnedModel->colision = model.colision; + spawnedModel->networkReplicated = false; + spdlog::info("model spawned: {}", model.ID.snowflake); + } + } break; + default: + spdlog::error("unknown data type"); + } } } // namespace veng diff --git a/include/socket/socket.h b/include/socket/socket.h index 2c8c650..017f64f 100644 --- a/include/socket/socket.h +++ b/include/socket/socket.h @@ -39,7 +39,7 @@ class Socket { std::mutex readMutex; std::mutex writeMutex; - protected: +private: bool valid_ = false; }; diff --git a/include/vulkan_engine/asset/object/model.h b/include/vulkan_engine/asset/object/model.h index 472621e..8c55ca6 100644 --- a/include/vulkan_engine/asset/object/model.h +++ b/include/vulkan_engine/asset/object/model.h @@ -18,7 +18,8 @@ struct Model { ~Model(); Model(const Model& other) - : vertices(other.vertices), + : asset_name(other.asset_name), + vertices(other.vertices), vertex_buffer(other.vertex_buffer), indices(other.indices), index_buffer(other.index_buffer), @@ -39,12 +40,15 @@ struct Model { visible(other.visible), colision(other.colision), networkReplicated(other.networkReplicated) { + name = "_" + other.name; ID = utils::GenerateID(CLIENTID); graphics_ = nullptr; } Model(Model&& other) - : vertices(std::move(other.vertices)), + : name(other.name), + asset_name(other.asset_name), + vertices(std::move(other.vertices)), vertex_buffer(std::move(other.vertex_buffer)), indices(std::move(other.indices)), index_buffer(std::move(other.index_buffer)), @@ -77,6 +81,8 @@ struct Model { if (this != &other) { ID = other.ID; ::memset(&other.ID, 0, 8); + name = other.name; + asset_name = other.asset_name; vertices = std::move(other.vertices); vertex_buffer = std::move(other.vertex_buffer); indices = std::move(other.indices); @@ -105,6 +111,8 @@ struct Model { return *this; } utils::Snowflake ID; + std::string name; + std::string asset_name; std::vector Serialize(); void Deserialize(std::vector data); @@ -144,6 +152,9 @@ struct Model { bool visible = true; bool colision = false; bool networkReplicated = true; + bool shouldBeDestroyed = false; + + bool needsUpdate = true; private: class Graphics* graphics_; diff --git a/include/vulkan_engine/vulkan/engine.h b/include/vulkan_engine/vulkan/engine.h index 505c3c5..23ab29f 100644 --- a/include/vulkan_engine/vulkan/engine.h +++ b/include/vulkan_engine/vulkan/engine.h @@ -19,7 +19,7 @@ class Engine { void LoadModelAsset(std::string path, std::string name); const Model* GetStaticModel(std::string name); - Model* SpawnModel(std::string asset_name, std::string name); + // 수명을 무제한으로 놓고 싶으면 lifespan을 -1으로 설정하면 됨 Model* SpawnLifedModel(std::string asset_name, std::string name, std::float_t lifespan); Model* GetSpawnedObject(std::string name);