#pragma once #include #include #include // inputs bitmask #define INPUT_FORWARD (1 << 0) #define INPUT_BACK (1 << 1) #define INPUT_LEFT (1 << 2) #define INPUT_RIGHT (1 << 3) #define INPUT_JUMP (1 << 4) #define INPUT_SPRINT (1 << 5) #define HZ 20.0 #define NETWORK_RATE (1.0 / HZ) #define TICK_RATE (1.0 / HZ) #define MAX_PLAYERS 16 #define MAX_VIEW_NPCS 32 #define MAX_NPCS 2000 typedef struct { float x; float y; float z; } Vec3; typedef enum { PACKET_CLIENT_INPUT, PACKET_SERVER_SNAPSHOT, PACKET_PLAYER_JOINED, PACKET_PLAYER_LEFT, PACKET_HANDSHAKE, PACKET_HANDSHAKE_RESPONSE, PACKET_WORLD_EVENT, PACKET_PING, PACKET_PONG } PacketType; typedef struct { PacketType type; double sentTime; } PingPacket; // client → server typedef struct { PacketType type; int playerId; int inputs; float yaw; float dt; int characterClass; // 0=warrior, 1=mage etc } ClientPacket; typedef struct { PacketType type; int playerId; char name[32]; int characterClass; // 0=warrior, 1=mage etc Vec3 position; } PlayerJoinedPacket; // server → client (full world snapshot) typedef struct { PacketType type; int playerCount; struct { int id; Vec3 position; Vec3 velocity; // add this float yaw; int animationState; bool onGround; } players[MAX_PLAYERS]; int npcCount; struct { int id; Vec3 position; float rotation; int state; // IDLE, WALKING, COMBAT int health; int scale; int model; } npcs[MAX_VIEW_NPCS]; int eventCount; struct { int objectId; int eventType; // OBJECT_REMOVED, DOOR_OPENED etc Vec3 position; } events[8]; } ServerSnapshot; typedef struct { PacketType type; char name[32]; int characterClass; // 0=warrior, 1=mage etc } HandshakePacket; typedef struct { PacketType type; int playerId; float spawnX; float spawnY; float spawnZ; } HandshakeResponsePacket; static inline float Vec3Distance(Vec3 a, Vec3 b) { float dx = a.x - b.x; float dy = a.y - b.y; float dz = a.z - b.z; return sqrtf(dx*dx + dy*dy + dz*dz); } static inline double GetWallTime() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec + ts.tv_nsec / 1e9; }