diff --git a/build-linux/MorriCraft b/build-linux/MorriCraft index 852898f..308c391 100755 Binary files a/build-linux/MorriCraft and b/build-linux/MorriCraft differ diff --git a/build-linux/assets/version.txt b/build-linux/assets/version.txt index 46b105a..f3b15f3 100644 --- a/build-linux/assets/version.txt +++ b/build-linux/assets/version.txt @@ -1 +1 @@ -v2.0.0 +v2.0.2 diff --git a/build-windows/MorriCraft.exe b/build-windows/MorriCraft.exe index 7e12624..7007bf4 100755 Binary files a/build-windows/MorriCraft.exe and b/build-windows/MorriCraft.exe differ diff --git a/build-windows/assets/version.txt b/build-windows/assets/version.txt index 46b105a..f3b15f3 100644 --- a/build-windows/assets/version.txt +++ b/build-windows/assets/version.txt @@ -1 +1 @@ -v2.0.0 +v2.0.2 diff --git a/src/main.cpp b/src/main.cpp index 743059b..101109e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -733,7 +733,7 @@ int main(void) // By default, windows have minimize, maximize, and close buttons on the top bar. SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT); - InitWindow(screenWidth, screenHeight, "MorriCraft v2.0.2"); + InitWindow(screenWidth, screenHeight, "MorriCraft v2.0.3"); LoadConfig(); SetExitKey(KEY_NULL); // Prevent ESC from closing the window @@ -966,57 +966,91 @@ int main(void) // Handle incoming data auto handleIncoming = [&](Socket sock, bool isServer, int clientIdx = -1) { - PacketHeader head; - int bytes = recv(sock, (char*)&head, sizeof(head), 0); - if (bytes > 0) { + while (true) { + // Use a quick non-blocking check to see if more data is available + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + struct timeval tv = {0, 0}; + if (select((int)sock + 1, &readfds, NULL, NULL, &tv) <= 0) break; + + PacketHeader head; + int bytes = recv(sock, (char*)&head, sizeof(head), 0); + if (bytes <= 0) { + if (isServer && clientIdx != -1) { + std::string leaver = "A player"; + for (auto it = remotePlayers.begin(); it != remotePlayers.end(); ++it) { + if (it->sock == sock) { + leaver = it->name; + remotePlayers.erase(it); + break; + } + } + chatLog.push_back({ leaver + " left the game", 5.0f }); + PacketHeader nHead = { (uint8_t)PACKET_CHAT, (uint32_t)sizeof(PacketChat) }; + PacketChat nChat; + strncpy(nChat.name, "Server", 31); + strncpy(nChat.message, (leaver + " left the game").c_str(), 127); + for (auto& s : clientSockets) { + if (s != sock) { + send(s, (char*)&nHead, sizeof(nHead), 0); + send(s, (char*)&nChat, sizeof(nChat), 0); + } + } + closesocket(sock); + clientSockets.erase(clientSockets.begin() + clientIdx); + } + break; + } + if (head.type == PACKET_HANDSHAKE) { PacketHandshake hand; recv(sock, (char*)&hand, sizeof(hand), 0); if (isServer) { - uint32_t newID = (uint32_t)sock; - RemotePlayer rp; - rp.sock = sock; - rp.id = newID; - rp.name = hand.name; - rp.position = (Vector3){0,0,0}; - remotePlayers.push_back(rp); - - // Notify others - chatLog.push_back({ std::string(hand.name) + " joined the game", 5.0f }); - PacketHeader nHead = { (uint8_t)PACKET_CHAT, (uint32_t)sizeof(PacketChat) }; - PacketChat nChat; - strncpy(nChat.name, "Server", 31); - strncpy(nChat.message, (std::string(hand.name) + " joined the game").c_str(), 127); - for (auto& s : clientSockets) { - send(s, (char*)&nHead, sizeof(nHead), 0); - send(s, (char*)&nChat, sizeof(nChat), 0); - } - - // Send seed and time to new client - PacketHeader sHead = { (uint8_t)PACKET_SEED_SYNC, (uint32_t)sizeof(PacketSeedSync) }; - PacketSeedSync sData = { (int)globalSeedHash }; - send(sock, (char*)&sHead, sizeof(sHead), 0); - send(sock, (char*)&sData, sizeof(sData), 0); - - PacketHeader tHead = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) }; - PacketTimeSync tData = { gameTime }; - send(sock, (char*)&tHead, sizeof(tHead), 0); - send(sock, (char*)&tData, sizeof(tData), 0); - - // Send existing players to new client - for (auto& rp : remotePlayers) { - if (rp.sock != sock) { - PacketHeader pHead = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; - PacketPlayerUpdate pData = { rp.position.x, rp.position.y, rp.position.z, rp.yaw, rp.id }; - send(sock, (char*)&pHead, sizeof(pHead), 0); - send(sock, (char*)&pData, sizeof(pData), 0); + bool duplicate = false; + for (auto& rp : remotePlayers) { if (rp.sock == sock) { duplicate = true; break; } } + if (!duplicate) { + uint32_t newID = (uint32_t)sock; + RemotePlayer rp; + rp.sock = sock; + rp.id = newID; + rp.name = hand.name; + rp.position = (Vector3){0,0,0}; + remotePlayers.push_back(rp); + + chatLog.push_back({ std::string(hand.name) + " joined the game", 5.0f }); + PacketHeader nHead = { (uint8_t)PACKET_CHAT, (uint32_t)sizeof(PacketChat) }; + PacketChat nChat; + strncpy(nChat.name, "Server", 31); + strncpy(nChat.message, (std::string(hand.name) + " joined the game").c_str(), 127); + for (auto& s : clientSockets) { + send(s, (char*)&nHead, sizeof(nHead), 0); + send(s, (char*)&nChat, sizeof(nChat), 0); } + + PacketHeader sHead = { (uint8_t)PACKET_SEED_SYNC, (uint32_t)sizeof(PacketSeedSync) }; + PacketSeedSync sData = { (int)globalSeedHash }; + send(sock, (char*)&sHead, sizeof(sHead), 0); + send(sock, (char*)&sData, sizeof(sData), 0); + + PacketHeader tHead = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) }; + PacketTimeSync tData = { gameTime }; + send(sock, (char*)&tHead, sizeof(tHead), 0); + send(sock, (char*)&tData, sizeof(tData), 0); + + for (auto& existing : remotePlayers) { + if (existing.sock != sock) { + PacketHeader pHead = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; + PacketPlayerUpdate pData = { existing.position.x, existing.position.y, existing.position.z, existing.yaw, existing.id }; + send(sock, (char*)&pHead, sizeof(pHead), 0); + send(sock, (char*)&pData, sizeof(pData), 0); + } + } + PacketHeader hHead = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; + PacketPlayerUpdate hData = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 }; + send(sock, (char*)&hHead, sizeof(hHead), 0); + send(sock, (char*)&hData, sizeof(hData), 0); } - // Send HOST to new client (Host ID is always 0) - PacketHeader hHead = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; - PacketPlayerUpdate hData = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 }; - send(sock, (char*)&hHead, sizeof(hHead), 0); - send(sock, (char*)&hData, sizeof(hData), 0); } } else if (head.type == PACKET_PLAYER_UPDATE) { PacketPlayerUpdate pu; @@ -1039,7 +1073,7 @@ int main(void) remotePlayers.push_back(rp); } if (isServer) { - pu.playerID = (uint32_t)sock; // Ensure ID is correct + pu.playerID = (uint32_t)sock; for (auto& other : clientSockets) { if (other != sock) { send(other, (char*)&head, sizeof(head), 0); @@ -1068,7 +1102,6 @@ int main(void) recv(sock, (char*)&ss, sizeof(ss), 0); if (!isServer) { globalSeedHash = ss.seed; - // Regerate world if seed changed for (auto& pair : worldChunks) delete pair.second; worldChunks.clear(); } @@ -1084,31 +1117,11 @@ int main(void) } } } - } - } else if (bytes == 0 || (bytes < 0 && SOCKET_ERROR_VAL != -1)) { - // Disconnect handling - if (isServer && clientIdx != -1) { - std::string leaver = "A player"; - for (auto it = remotePlayers.begin(); it != remotePlayers.end(); ++it) { - if (it->sock == sock) { - leaver = it->name; - remotePlayers.erase(it); - break; - } + } else { + if (head.size > 0 && head.size < 2048) { + std::vector discard(head.size); + recv(sock, discard.data(), head.size, 0); } - chatLog.push_back({ leaver + " left the game", 5.0f }); - PacketHeader nHead = { (uint8_t)PACKET_CHAT, (uint32_t)sizeof(PacketChat) }; - PacketChat nChat; - strncpy(nChat.name, "Server", 31); - strncpy(nChat.message, (leaver + " left the game").c_str(), 127); - for (auto& s : clientSockets) { - if (s != sock) { - send(s, (char*)&nHead, sizeof(nHead), 0); - send(s, (char*)&nChat, sizeof(nChat), 0); - } - } - closesocket(sock); - clientSockets.erase(clientSockets.begin() + clientIdx); } } }; @@ -1697,8 +1710,8 @@ int main(void) DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE); EndMode2D(); - // Show Version Number (v2.0.2) in Red - DrawTextEx(customFont, "v2.0.2", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED); + // Show Version Number (v2.0.3) in Red + DrawTextEx(customFont, "v2.0.3", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED); // --- PLAYER NAME POPUP (IF MISSING) --- if (playerName == "") {