diff --git a/build-linux/MorriCraft b/build-linux/MorriCraft index 1fb781f..31f472c 100755 Binary files a/build-linux/MorriCraft and b/build-linux/MorriCraft differ diff --git a/build-windows/MorriCraft.exe b/build-windows/MorriCraft.exe index c8dacc2..24a5b64 100755 Binary files a/build-windows/MorriCraft.exe and b/build-windows/MorriCraft.exe differ diff --git a/src/main.cpp b/src/main.cpp index 115296d..d56e694 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "rlgl.h" #define CHUNK_SIZE 32 @@ -18,7 +20,7 @@ #define PI 3.1415926535f #endif #define CHUNK_HEIGHT 128 -#define RENDER_DISTANCE 1 // 3x3 chunks visible for performance +#define RENDER_DISTANCE 2 enum BlockType { AIR = 0, GRASS = 1, DIRT = 2, COBBLESTONE = 3, LOG = 4, LEAVES = 5, PLANK = 6, @@ -243,32 +245,21 @@ void RebuildChunkRenderList(Chunk* chunk, int cx, int cz) { chunk->dirty = false; } -void NetSetBlock(int x, int y, int z, int type) { - SetBlock(x, y, z, type); - PacketHeader head = { (uint8_t)PACKET_BLOCK_CHANGE, (uint32_t)sizeof(PacketBlockChange) }; - PacketBlockChange bc = { x, y, z, type }; - - if (clientSocket != INVALID_SOCKET_VAL) { - send(clientSocket, (char*)&head, sizeof(head), 0); - send(clientSocket, (char*)&bc, sizeof(bc), 0); - } - if (serverSocket != INVALID_SOCKET_VAL) { - for (auto& s : clientSockets) { - send(s, (char*)&head, sizeof(head), 0); - send(s, (char*)&bc, sizeof(bc), 0); - } - } -} - int RecvAll(Socket s, char* buf, int len) { int total = 0; while (total < len) { int r = recv(s, buf + total, len - total, 0); if (r <= 0) { #ifdef _WIN32 - if (r < 0 && WSAGetLastError() == WSAEWOULDBLOCK) continue; + if (r < 0 && WSAGetLastError() == WSAEWOULDBLOCK) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + continue; + } #else - if (r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) continue; + if (r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + continue; + } #endif return r; } @@ -277,11 +268,41 @@ int RecvAll(Socket s, char* buf, int len) { return total; } +int SendAll(Socket s, const char* buf, int len) { + int total = 0; + while (total < len) { + int r = send(s, buf + total, len - total, 0); + if (r <= 0) return r; + total += r; + } + return total; +} + +void NetSetBlock(int x, int y, int z, int type) { + SetBlock(x, y, z, type); + PacketHeader head = { (uint8_t)PACKET_BLOCK_CHANGE, (uint32_t)sizeof(PacketBlockChange) }; + PacketBlockChange bc = { x, y, z, type }; + + if (clientSocket != INVALID_SOCKET_VAL) { + SendAll(clientSocket, (char*)&head, sizeof(head)); + SendAll(clientSocket, (char*)&bc, sizeof(bc)); + } + if (serverSocket != INVALID_SOCKET_VAL) { + for (auto& s : clientSockets) { + SendAll(s, (char*)&head, sizeof(head)); + SendAll(s, (char*)&bc, sizeof(bc)); + } + } +} + void SetBlock(int x, int y, int z, int type) { if (y < 0 || y >= CHUNK_HEIGHT) return; int cx = (int)floorf((float)x / CHUNK_SIZE); int cz = (int)floorf((float)z / CHUNK_SIZE); ChunkPos key = { cx, cz }; + if (worldChunks.find(key) == worldChunks.end()) { + GenerateChunk(cx, cz); + } if (worldChunks.find(key) != worldChunks.end()) { int lx = x - (cx * CHUNK_SIZE); int lz = z - (cz * CHUNK_SIZE); @@ -977,8 +998,8 @@ int main(void) PacketHeader head = { (uint8_t)PACKET_HANDSHAKE, (uint32_t)sizeof(PacketHandshake) }; PacketHandshake hand; strncpy(hand.name, playerName.c_str(), 31); - send(clientSocket, (char*)&head, sizeof(head), 0); - send(clientSocket, (char*)&hand, sizeof(hand), 0); + SendAll(clientSocket, (char*)&head, sizeof(head)); + SendAll(clientSocket, (char*)&hand, sizeof(hand)); } } @@ -1010,8 +1031,8 @@ int main(void) 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); + SendAll(s, (char*)&nHead, sizeof(nHead)); + SendAll(s, (char*)&nChat, sizeof(nChat)); } } closesocket(sock); @@ -1041,37 +1062,38 @@ int main(void) 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); + SendAll(s, (char*)&nHead, sizeof(nHead)); + SendAll(s, (char*)&nChat, sizeof(nChat)); } 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); + SendAll(sock, (char*)&sHead, sizeof(sHead)); + SendAll(sock, (char*)&sData, sizeof(sData)); 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); + SendAll(sock, (char*)&tHead, sizeof(tHead)); + SendAll(sock, (char*)&tData, sizeof(tData)); 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); + SendAll(sock, (char*)&pHead, sizeof(pHead)); + SendAll(sock, (char*)&pData, sizeof(pData)); } } 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); + SendAll(sock, (char*)&hHead, sizeof(hHead)); + SendAll(sock, (char*)&hData, sizeof(hData)); } } } else if (head.type == PACKET_PLAYER_UPDATE) { PacketPlayerUpdate pu; if (RecvAll(sock, (char*)&pu, sizeof(pu)) <= 0) break; + if (isServer) pu.playerID = (uint32_t)sock; bool found = false; for (auto& rp : remotePlayers) { if (rp.id == pu.playerID) { @@ -1093,8 +1115,8 @@ int main(void) pu.playerID = (uint32_t)sock; for (auto& other : clientSockets) { if (other != sock) { - send(other, (char*)&head, sizeof(head), 0); - send(other, (char*)&pu, sizeof(pu), 0); + SendAll(other, (char*)&head, sizeof(head)); + SendAll(other, (char*)&pu, sizeof(pu)); } } } @@ -1105,8 +1127,8 @@ int main(void) if (isServer) { for (auto& other : clientSockets) { if (other != sock) { - send(other, (char*)&head, sizeof(head), 0); - send(other, (char*)&bc, sizeof(bc), 0); + SendAll(other, (char*)&head, sizeof(head)); + SendAll(other, (char*)&bc, sizeof(bc)); } } } @@ -1129,8 +1151,8 @@ int main(void) if (isServer) { for (auto& other : clientSockets) { if (other != sock) { - send(other, (char*)&head, sizeof(head), 0); - send(other, (char*)&pc, sizeof(pc), 0); + SendAll(other, (char*)&head, sizeof(head)); + SendAll(other, (char*)&pc, sizeof(pc)); } } } @@ -1151,8 +1173,8 @@ int main(void) if (netTimer > 0.05f) { // 20Hz update PacketHeader head = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; PacketPlayerUpdate pu = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 }; - send(clientSocket, (char*)&head, sizeof(head), 0); - send(clientSocket, (char*)&pu, sizeof(pu), 0); + SendAll(clientSocket, (char*)&head, sizeof(head)); + SendAll(clientSocket, (char*)&pu, sizeof(pu)); netTimer = 0.0f; } } @@ -1175,8 +1197,8 @@ int main(void) PacketHeader head = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) }; PacketTimeSync ts = { gameTime }; for (auto& s : clientSockets) { - send(s, (char*)&head, sizeof(head), 0); - send(s, (char*)&ts, sizeof(ts), 0); + SendAll(s, (char*)&head, sizeof(head)); + SendAll(s, (char*)&ts, sizeof(ts)); } timeSyncTimer = 0.0f; } @@ -1187,8 +1209,8 @@ int main(void) PacketHeader head = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; PacketPlayerUpdate pu = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 }; for (auto& s : clientSockets) { - send(s, (char*)&head, sizeof(head), 0); - send(s, (char*)&pu, sizeof(pu), 0); + SendAll(s, (char*)&head, sizeof(head)); + SendAll(s, (char*)&pu, sizeof(pu)); } hostNetTimer = 0.0f; } @@ -1295,14 +1317,14 @@ int main(void) strncpy(pc.name, playerName.c_str(), 31); strncpy(pc.message, chatInput, 127); if (clientSocket != INVALID_SOCKET_VAL) { - send(clientSocket, (char*)&head, sizeof(head), 0); - send(clientSocket, (char*)&pc, sizeof(pc), 0); + SendAll(clientSocket, (char*)&head, sizeof(head)); + SendAll(clientSocket, (char*)&pc, sizeof(pc)); } if (serverSocket != INVALID_SOCKET_VAL) { chatLog.push_back({ std::string(playerName) + ": " + chatInput, 5.0f }); for (auto& s : clientSockets) { - send(s, (char*)&head, sizeof(head), 0); - send(s, (char*)&pc, sizeof(pc), 0); + SendAll(s, (char*)&head, sizeof(head)); + SendAll(s, (char*)&pc, sizeof(pc)); } } chatInput[0] = '\0';