// server.h

typedef struct {
    int maxclients;
    int maxclientslimit;
    struct client_s *clients;	// [maxclients]
    int serverflags;		// episode completion information
    qboolean changelevel_issued;	// cleared when at SV_SpawnServer
} server_static_t;

//=============================================================================

typedef enum { ss_loading, ss_active } server_state_t;

typedef struct {
    qboolean active;		// false if only a net client

    qboolean paused;
    qboolean loadgame;		// handle connections specially

    double time;

    int lastcheck;		// used by PF_checkclient
    double lastchecktime;

    char name[64];		// map name
    char modelname[64];		// maps/<name>.bsp, for model_precache[0]
    struct model_s *worldmodel;
    char *model_precache[MAX_MODELS];	// NULL terminated
    struct model_s *models[MAX_MODELS];
    char *sound_precache[MAX_SOUNDS];	// NULL terminated
    char *lightstyles[MAX_LIGHTSTYLES];
    int num_edicts;
    int max_edicts;
    edict_t *edicts;		// can NOT be array indexed, because
    // edict_t is variable sized, but can
    // be used to reference the world ent
    server_state_t state;	// some actions are only valid during load

    sizebuf_t datagram;
    byte datagram_buf[MAX_DATAGRAM];

    sizebuf_t reliable_datagram;	// copied to all clients at end of frame
    byte reliable_datagram_buf[MAX_DATAGRAM];

    sizebuf_t signon;
    byte signon_buf[8192];
} server_t;


#define	NUM_PING_TIMES		16
#define	NUM_SPAWN_PARMS		16

typedef struct client_s {
    qboolean active;		// false = client is free
    qboolean spawned;		// false = don't send datagrams
    qboolean dropasap;		// has been told to go to another level
    qboolean privileged;	// can execute any host command
    qboolean sendsignon;	// only valid before spawned

    double last_message;	// reliable messages must be sent
    // periodically

    struct qsocket_s *netconnection;	// communications handle

    usercmd_t cmd;		// movement
    vec3_t wishdir;		// intended motion calced from cmd

    sizebuf_t message;		// can be added to at any time,
    // copied and clear once per frame
    byte msgbuf[MAX_MSGLEN];
    edict_t *edict;		// EDICT_NUM(clientnum+1)
    char name[32];		// for printing to other people
    int colors;

    float ping_times[NUM_PING_TIMES];
    int num_pings;		// ping_times[num_pings%NUM_PING_TIMES]

// spawn parms are carried from level to level
    float spawn_parms[NUM_SPAWN_PARMS];

// client known data for deltas 
    int old_frags;
} client_t;


//=============================================================================

// edict->movetype values
#define	MOVETYPE_NONE			0	// never moves
#define	MOVETYPE_ANGLENOCLIP	1
#define	MOVETYPE_ANGLECLIP		2
#define	MOVETYPE_WALK			3	// gravity
#define	MOVETYPE_STEP			4	// gravity, special edge handling
#define	MOVETYPE_FLY			5
#define	MOVETYPE_TOSS			6	// gravity
#define	MOVETYPE_PUSH			7	// no clip to world, push and crush
#define	MOVETYPE_NOCLIP			8
#define	MOVETYPE_FLYMISSILE		9	// extra size to monsters
#define	MOVETYPE_BOUNCE			10

// edict->solid values
#define	SOLID_NOT				0	// no interaction with other objects
#define	SOLID_TRIGGER			1	// touch on edge, but not blocking
#define	SOLID_BBOX				2	// touch on edge, block
#define	SOLID_SLIDEBOX			3	// touch on edge, but not an onground
#define	SOLID_BSP				4	// bsp clip, touch on edge, block

// edict->deadflag values
#define	DEAD_NO					0
#define	DEAD_DYING				1
#define	DEAD_DEAD				2

#define	DAMAGE_NO				0
#define	DAMAGE_YES				1
#define	DAMAGE_AIM				2

// edict->flags
#define	FL_FLY					1
#define	FL_SWIM					2
#define	FL_GLIMPSE				4
#define	FL_CLIENT				8
#define	FL_INWATER				16
#define	FL_MONSTER				32
#define	FL_GODMODE				64
#define	FL_NOTARGET				128
#define	FL_ITEM					256
#define	FL_ONGROUND				512
#define	FL_PARTIALGROUND		1024	// not all corners are valid
#define	FL_WATERJUMP			2048	// player jumping out of water

// entity effects

#define	EF_BRIGHTFIELD			1
#define	EF_MUZZLEFLASH 			2
#define	EF_BRIGHTLIGHT 			4
#define	EF_DIMLIGHT 			8


#define	SPAWNFLAG_NOT_EASY			256
#define	SPAWNFLAG_NOT_MEDIUM		512
#define	SPAWNFLAG_NOT_HARD			1024
#define	SPAWNFLAG_NOT_DEATHMATCH	2048

//============================================================================

extern cvar_t teamplay;
extern cvar_t skill;
extern cvar_t deathmatch;
extern cvar_t coop;
extern cvar_t fraglimit;
extern cvar_t timelimit;

extern server_static_t svs;	// persistant server info
extern server_t sv;		// local server

extern client_t *host_client;

extern jmp_buf host_abortserver;

extern double host_time;

extern edict_t *sv_player;

//===========================================================

void SV_Init(void);

void SV_StartParticle(vec3_t org, vec3_t dir, int color, int count);
void SV_StartSound(edict_t * entity, int channel, char *sample, int volume,
		   float attenuation);

void SV_DropClient(qboolean crash);

void SV_SendClientMessages(void);
void SV_ClearDatagram(void);

int SV_ModelIndex(char *name);

void SV_SetIdealPitch(void);

void SV_AddUpdates(void);

void SV_ClientThink(void);
void SV_AddClientToServer(struct qsocket_s *ret);

void SV_ClientPrintf(char *fmt, ...);
void SV_BroadcastPrintf(char *fmt, ...);

void SV_Physics(void);

qboolean SV_CheckBottom(edict_t * ent);
qboolean SV_movestep(edict_t * ent, vec3_t move, qboolean relink);

void SV_WriteClientdataToMessage(edict_t * ent, sizebuf_t * msg);

void SV_MoveToGoal(void);

void SV_CheckForNewClients(void);
void SV_RunClients(void);
void SV_SaveSpawnparms();
void SV_SpawnServer(char *server);
