Fix SendAll recursion and finalize v2.0.6

This commit is contained in:
Michael Howard 2026-04-23 18:23:37 -05:00
parent 69ba3372f6
commit be2148a415
3 changed files with 72 additions and 50 deletions

Binary file not shown.

Binary file not shown.

View File

@ -11,6 +11,8 @@
#include <time.h> #include <time.h>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <thread>
#include <chrono>
#include "rlgl.h" #include "rlgl.h"
#define CHUNK_SIZE 32 #define CHUNK_SIZE 32
@ -18,7 +20,7 @@
#define PI 3.1415926535f #define PI 3.1415926535f
#endif #endif
#define CHUNK_HEIGHT 128 #define CHUNK_HEIGHT 128
#define RENDER_DISTANCE 1 // 3x3 chunks visible for performance #define RENDER_DISTANCE 2
enum BlockType { enum BlockType {
AIR = 0, GRASS = 1, DIRT = 2, COBBLESTONE = 3, LOG = 4, LEAVES = 5, PLANK = 6, 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; 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 RecvAll(Socket s, char* buf, int len) {
int total = 0; int total = 0;
while (total < len) { while (total < len) {
int r = recv(s, buf + total, len - total, 0); int r = recv(s, buf + total, len - total, 0);
if (r <= 0) { if (r <= 0) {
#ifdef _WIN32 #ifdef _WIN32
if (r < 0 && WSAGetLastError() == WSAEWOULDBLOCK) continue; if (r < 0 && WSAGetLastError() == WSAEWOULDBLOCK) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
#else #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 #endif
return r; return r;
} }
@ -277,11 +268,41 @@ int RecvAll(Socket s, char* buf, int len) {
return total; 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) { void SetBlock(int x, int y, int z, int type) {
if (y < 0 || y >= CHUNK_HEIGHT) return; if (y < 0 || y >= CHUNK_HEIGHT) return;
int cx = (int)floorf((float)x / CHUNK_SIZE); int cx = (int)floorf((float)x / CHUNK_SIZE);
int cz = (int)floorf((float)z / CHUNK_SIZE); int cz = (int)floorf((float)z / CHUNK_SIZE);
ChunkPos key = { cx, cz }; ChunkPos key = { cx, cz };
if (worldChunks.find(key) == worldChunks.end()) {
GenerateChunk(cx, cz);
}
if (worldChunks.find(key) != worldChunks.end()) { if (worldChunks.find(key) != worldChunks.end()) {
int lx = x - (cx * CHUNK_SIZE); int lx = x - (cx * CHUNK_SIZE);
int lz = z - (cz * 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) }; PacketHeader head = { (uint8_t)PACKET_HANDSHAKE, (uint32_t)sizeof(PacketHandshake) };
PacketHandshake hand; PacketHandshake hand;
strncpy(hand.name, playerName.c_str(), 31); strncpy(hand.name, playerName.c_str(), 31);
send(clientSocket, (char*)&head, sizeof(head), 0); SendAll(clientSocket, (char*)&head, sizeof(head));
send(clientSocket, (char*)&hand, sizeof(hand), 0); SendAll(clientSocket, (char*)&hand, sizeof(hand));
} }
} }
@ -1010,8 +1031,8 @@ int main(void)
strncpy(nChat.message, (leaver + " left the game").c_str(), 127); strncpy(nChat.message, (leaver + " left the game").c_str(), 127);
for (auto& s : clientSockets) { for (auto& s : clientSockets) {
if (s != sock) { if (s != sock) {
send(s, (char*)&nHead, sizeof(nHead), 0); SendAll(s, (char*)&nHead, sizeof(nHead));
send(s, (char*)&nChat, sizeof(nChat), 0); SendAll(s, (char*)&nChat, sizeof(nChat));
} }
} }
closesocket(sock); closesocket(sock);
@ -1041,37 +1062,38 @@ int main(void)
strncpy(nChat.name, "Server", 31); strncpy(nChat.name, "Server", 31);
strncpy(nChat.message, (std::string(hand.name) + " joined the game").c_str(), 127); strncpy(nChat.message, (std::string(hand.name) + " joined the game").c_str(), 127);
for (auto& s : clientSockets) { for (auto& s : clientSockets) {
send(s, (char*)&nHead, sizeof(nHead), 0); SendAll(s, (char*)&nHead, sizeof(nHead));
send(s, (char*)&nChat, sizeof(nChat), 0); SendAll(s, (char*)&nChat, sizeof(nChat));
} }
PacketHeader sHead = { (uint8_t)PACKET_SEED_SYNC, (uint32_t)sizeof(PacketSeedSync) }; PacketHeader sHead = { (uint8_t)PACKET_SEED_SYNC, (uint32_t)sizeof(PacketSeedSync) };
PacketSeedSync sData = { (int)globalSeedHash }; PacketSeedSync sData = { (int)globalSeedHash };
send(sock, (char*)&sHead, sizeof(sHead), 0); SendAll(sock, (char*)&sHead, sizeof(sHead));
send(sock, (char*)&sData, sizeof(sData), 0); SendAll(sock, (char*)&sData, sizeof(sData));
PacketHeader tHead = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) }; PacketHeader tHead = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) };
PacketTimeSync tData = { gameTime }; PacketTimeSync tData = { gameTime };
send(sock, (char*)&tHead, sizeof(tHead), 0); SendAll(sock, (char*)&tHead, sizeof(tHead));
send(sock, (char*)&tData, sizeof(tData), 0); SendAll(sock, (char*)&tData, sizeof(tData));
for (auto& existing : remotePlayers) { for (auto& existing : remotePlayers) {
if (existing.sock != sock) { if (existing.sock != sock) {
PacketHeader pHead = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; 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 }; PacketPlayerUpdate pData = { existing.position.x, existing.position.y, existing.position.z, existing.yaw, existing.id };
send(sock, (char*)&pHead, sizeof(pHead), 0); SendAll(sock, (char*)&pHead, sizeof(pHead));
send(sock, (char*)&pData, sizeof(pData), 0); SendAll(sock, (char*)&pData, sizeof(pData));
} }
} }
PacketHeader hHead = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; 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 }; PacketPlayerUpdate hData = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 };
send(sock, (char*)&hHead, sizeof(hHead), 0); SendAll(sock, (char*)&hHead, sizeof(hHead));
send(sock, (char*)&hData, sizeof(hData), 0); SendAll(sock, (char*)&hData, sizeof(hData));
} }
} }
} else if (head.type == PACKET_PLAYER_UPDATE) { } else if (head.type == PACKET_PLAYER_UPDATE) {
PacketPlayerUpdate pu; PacketPlayerUpdate pu;
if (RecvAll(sock, (char*)&pu, sizeof(pu)) <= 0) break; if (RecvAll(sock, (char*)&pu, sizeof(pu)) <= 0) break;
if (isServer) pu.playerID = (uint32_t)sock;
bool found = false; bool found = false;
for (auto& rp : remotePlayers) { for (auto& rp : remotePlayers) {
if (rp.id == pu.playerID) { if (rp.id == pu.playerID) {
@ -1093,8 +1115,8 @@ int main(void)
pu.playerID = (uint32_t)sock; pu.playerID = (uint32_t)sock;
for (auto& other : clientSockets) { for (auto& other : clientSockets) {
if (other != sock) { if (other != sock) {
send(other, (char*)&head, sizeof(head), 0); SendAll(other, (char*)&head, sizeof(head));
send(other, (char*)&pu, sizeof(pu), 0); SendAll(other, (char*)&pu, sizeof(pu));
} }
} }
} }
@ -1105,8 +1127,8 @@ int main(void)
if (isServer) { if (isServer) {
for (auto& other : clientSockets) { for (auto& other : clientSockets) {
if (other != sock) { if (other != sock) {
send(other, (char*)&head, sizeof(head), 0); SendAll(other, (char*)&head, sizeof(head));
send(other, (char*)&bc, sizeof(bc), 0); SendAll(other, (char*)&bc, sizeof(bc));
} }
} }
} }
@ -1129,8 +1151,8 @@ int main(void)
if (isServer) { if (isServer) {
for (auto& other : clientSockets) { for (auto& other : clientSockets) {
if (other != sock) { if (other != sock) {
send(other, (char*)&head, sizeof(head), 0); SendAll(other, (char*)&head, sizeof(head));
send(other, (char*)&pc, sizeof(pc), 0); SendAll(other, (char*)&pc, sizeof(pc));
} }
} }
} }
@ -1151,8 +1173,8 @@ int main(void)
if (netTimer > 0.05f) { // 20Hz update if (netTimer > 0.05f) { // 20Hz update
PacketHeader head = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; 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 }; PacketPlayerUpdate pu = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 };
send(clientSocket, (char*)&head, sizeof(head), 0); SendAll(clientSocket, (char*)&head, sizeof(head));
send(clientSocket, (char*)&pu, sizeof(pu), 0); SendAll(clientSocket, (char*)&pu, sizeof(pu));
netTimer = 0.0f; netTimer = 0.0f;
} }
} }
@ -1175,8 +1197,8 @@ int main(void)
PacketHeader head = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) }; PacketHeader head = { (uint8_t)PACKET_TIME_SYNC, (uint32_t)sizeof(PacketTimeSync) };
PacketTimeSync ts = { gameTime }; PacketTimeSync ts = { gameTime };
for (auto& s : clientSockets) { for (auto& s : clientSockets) {
send(s, (char*)&head, sizeof(head), 0); SendAll(s, (char*)&head, sizeof(head));
send(s, (char*)&ts, sizeof(ts), 0); SendAll(s, (char*)&ts, sizeof(ts));
} }
timeSyncTimer = 0.0f; timeSyncTimer = 0.0f;
} }
@ -1187,8 +1209,8 @@ int main(void)
PacketHeader head = { (uint8_t)PACKET_PLAYER_UPDATE, (uint32_t)sizeof(PacketPlayerUpdate) }; 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 }; PacketPlayerUpdate pu = { camera3D.position.x, camera3D.position.y - 1.6f, camera3D.position.z, camYaw, 0 };
for (auto& s : clientSockets) { for (auto& s : clientSockets) {
send(s, (char*)&head, sizeof(head), 0); SendAll(s, (char*)&head, sizeof(head));
send(s, (char*)&pu, sizeof(pu), 0); SendAll(s, (char*)&pu, sizeof(pu));
} }
hostNetTimer = 0.0f; hostNetTimer = 0.0f;
} }
@ -1295,14 +1317,14 @@ int main(void)
strncpy(pc.name, playerName.c_str(), 31); strncpy(pc.name, playerName.c_str(), 31);
strncpy(pc.message, chatInput, 127); strncpy(pc.message, chatInput, 127);
if (clientSocket != INVALID_SOCKET_VAL) { if (clientSocket != INVALID_SOCKET_VAL) {
send(clientSocket, (char*)&head, sizeof(head), 0); SendAll(clientSocket, (char*)&head, sizeof(head));
send(clientSocket, (char*)&pc, sizeof(pc), 0); SendAll(clientSocket, (char*)&pc, sizeof(pc));
} }
if (serverSocket != INVALID_SOCKET_VAL) { if (serverSocket != INVALID_SOCKET_VAL) {
chatLog.push_back({ std::string(playerName) + ": " + chatInput, 5.0f }); chatLog.push_back({ std::string(playerName) + ": " + chatInput, 5.0f });
for (auto& s : clientSockets) { for (auto& s : clientSockets) {
send(s, (char*)&head, sizeof(head), 0); SendAll(s, (char*)&head, sizeof(head));
send(s, (char*)&pc, sizeof(pc), 0); SendAll(s, (char*)&pc, sizeof(pc));
} }
} }
chatInput[0] = '\0'; chatInput[0] = '\0';