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 <filesystem>
#include <fstream>
#include <thread>
#include <chrono>
#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';