mirror of
https://git.code.sf.net/p/quake/newtree
synced 2024-11-22 12:11:34 +00:00
75ecbe3032
the client sends the prespawn, spawn, and begin commands in the correct order. This stops several interesting cheats in TF as well as the posibility of avoiding the map checksum.
525 lines
14 KiB
C
525 lines
14 KiB
C
/*
|
|
server.h
|
|
|
|
(description)
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
$Id$
|
|
*/
|
|
// server.h
|
|
|
|
#ifndef _SERVER_H
|
|
#define _SERVER_H
|
|
|
|
#include "gcc_attr.h"
|
|
#include "commdef.h"
|
|
#include "net.h"
|
|
#include "cvar.h"
|
|
#include "protocol.h"
|
|
#include "model.h"
|
|
#include "progs.h"
|
|
#include "sizebuf.h"
|
|
#include "info.h"
|
|
#include "quakeio.h"
|
|
|
|
#define QW_SERVER
|
|
|
|
#define MAX_MASTERS 8 // max recipients for heartbeat packets
|
|
|
|
#define MAX_SIGNON_BUFFERS 8
|
|
|
|
typedef enum {
|
|
ss_dead, // no map loaded
|
|
ss_loading, // spawning level edicts
|
|
ss_active // actively running
|
|
} server_state_t;
|
|
// some qc commands are only valid before the server has finished
|
|
// initializing (precache commands, static sounds / objects, etc)
|
|
|
|
typedef struct
|
|
{
|
|
qboolean active; // false when server is going down
|
|
server_state_t state; // precache commands are only valid during load
|
|
|
|
double time;
|
|
|
|
int lastcheck; // used by PF_checkclient
|
|
double lastchecktime; // for monster ai
|
|
|
|
qboolean paused; // are we paused?
|
|
|
|
//check player/eyes models for hacks
|
|
unsigned int model_player_checksum;
|
|
unsigned int eyes_player_checksum;
|
|
|
|
char name[64]; // map name
|
|
char modelname[MAX_QPATH]; // maps/<name>.bsp, for model_precache[0]
|
|
struct model_s *worldmodel;
|
|
char *model_precache[MAX_MODELS]; // NULL terminated
|
|
char *sound_precache[MAX_SOUNDS]; // NULL terminated
|
|
char *lightstyles[MAX_LIGHTSTYLES];
|
|
struct model_s *models[MAX_MODELS];
|
|
|
|
int num_edicts; // increases towards 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
|
|
|
|
byte *pvs, *phs; // fully expanded and decompressed
|
|
|
|
// added to every client's unreliable buffer each frame, then cleared
|
|
sizebuf_t datagram;
|
|
byte datagram_buf[MAX_DATAGRAM];
|
|
|
|
// added to every client's reliable buffer each frame, then cleared
|
|
sizebuf_t reliable_datagram;
|
|
byte reliable_datagram_buf[MAX_MSGLEN];
|
|
|
|
// the multicast buffer is used to send a message to a set of clients
|
|
sizebuf_t multicast;
|
|
byte multicast_buf[MAX_MSGLEN];
|
|
|
|
// the master buffer is used for building log packets
|
|
sizebuf_t master;
|
|
byte master_buf[MAX_DATAGRAM];
|
|
|
|
// the signon buffer will be sent to each client as they connect
|
|
// includes the entity baselines, the static entities, etc
|
|
// large levels will have >MAX_DATAGRAM sized signons, so
|
|
// multiple signon messages are kept
|
|
sizebuf_t signon;
|
|
int num_signon_buffers;
|
|
int signon_buffer_size[MAX_SIGNON_BUFFERS];
|
|
byte signon_buffers[MAX_SIGNON_BUFFERS][MAX_DATAGRAM];
|
|
} server_t;
|
|
|
|
#define NUM_SPAWN_PARMS 16
|
|
|
|
typedef enum
|
|
{
|
|
cs_free, // can be reused for a new connection
|
|
cs_zombie, // client has been disconnected, but don't reuse
|
|
// connection for a couple seconds
|
|
cs_connected, // has been assigned to a client_t, but not in game yet
|
|
cs_prespawned, // has sent both prespawn and spawn commands
|
|
cs_spawned // client is fully in game (issued begin command)
|
|
} sv_client_state_t;
|
|
|
|
typedef struct
|
|
{
|
|
// received from client
|
|
|
|
// reply
|
|
double senttime;
|
|
float ping_time;
|
|
packet_entities_t entities;
|
|
} client_frame_t;
|
|
|
|
#define MAX_BACK_BUFFERS 4
|
|
#define MAX_STUFFTEXT 512
|
|
|
|
typedef struct client_s
|
|
{
|
|
sv_client_state_t state;
|
|
|
|
int spectator; // non-interactive
|
|
|
|
qboolean sendinfo; // at end of frame, send info to all
|
|
// this prevents malicious multiple broadcasts
|
|
float lastnametime; // time of last name change
|
|
int lastnamecount; // time of last name change
|
|
unsigned int checksum; // checksum for calcs
|
|
qboolean drop; // lose this guy next opportunity
|
|
int lossage; // loss percentage
|
|
|
|
int userid; // identifying number
|
|
char userinfo[MAX_INFO_STRING]; // infostring
|
|
|
|
usercmd_t lastcmd; // for filling in big drops and partial predictions
|
|
double localtime; // of last message
|
|
int oldbuttons;
|
|
|
|
float maxspeed; // localized maxspeed
|
|
float entgravity; // localized ent gravity
|
|
|
|
edict_t *edict; // EDICT_NUM(clientnum+1)
|
|
char name[32]; // for printing to other people
|
|
// extracted from userinfo
|
|
int messagelevel; // for filtering printed messages
|
|
|
|
// the datagram is written to after every frame, but only cleared
|
|
// when it is sent out to the client. overflow is tolerated.
|
|
sizebuf_t datagram;
|
|
byte datagram_buf[MAX_DATAGRAM];
|
|
|
|
// back buffers for client reliable data
|
|
sizebuf_t backbuf;
|
|
int num_backbuf;
|
|
int backbuf_size[MAX_BACK_BUFFERS];
|
|
byte backbuf_data[MAX_BACK_BUFFERS][MAX_MSGLEN];
|
|
|
|
byte stufftext_buf[MAX_STUFFTEXT];
|
|
|
|
double connection_started; // or time of disconnect for zombies
|
|
qboolean send_message; // set on frames a datagram arived on
|
|
|
|
// spawn parms are carried from level to level
|
|
float spawn_parms[NUM_SPAWN_PARMS];
|
|
|
|
// client known data for deltas
|
|
int old_frags;
|
|
|
|
int stats[MAX_CL_STATS];
|
|
|
|
client_frame_t frames[UPDATE_BACKUP]; // updates can be deltad from here
|
|
|
|
QFile *download; // file being downloaded
|
|
int downloadsize; // total bytes
|
|
int downloadcount; // bytes sent
|
|
|
|
int spec_track; // entnum of player tracking
|
|
|
|
double whensaid[10]; // JACK: For floodprots
|
|
int whensaidhead; // Head value for floodprots
|
|
double lockedtill;
|
|
|
|
qboolean upgradewarn; // did we warn him?
|
|
|
|
QFile *upload;
|
|
char uploadfn[MAX_QPATH];
|
|
netadr_t snap_from;
|
|
qboolean remote_snap;
|
|
|
|
//===== NETWORK ============
|
|
int chokecount;
|
|
int delta_sequence; // -1 = no compression
|
|
netchan_t netchan;
|
|
int msecs, msec_cheating;
|
|
double last_check;
|
|
float stdver; // QSG standards version
|
|
} client_t;
|
|
|
|
// a client can leave the server in one of four ways:
|
|
// dropping properly by quiting or disconnecting
|
|
// timing out if no valid messages are received for timeout->value seconds
|
|
// getting kicked off by the server operator
|
|
// a program error, like an overflowed reliable buffer
|
|
|
|
//=============================================================================
|
|
|
|
|
|
#define STATFRAMES 100
|
|
typedef struct
|
|
{
|
|
double active;
|
|
double idle;
|
|
int count;
|
|
int packets;
|
|
|
|
double latched_active;
|
|
double latched_idle;
|
|
int latched_packets;
|
|
} svstats_t;
|
|
|
|
// MAX_CHALLENGES is made large to prevent a denial
|
|
// of service attack that could cycle all of them
|
|
// out before legitimate users connected
|
|
#define MAX_CHALLENGES 1024
|
|
|
|
typedef struct
|
|
{
|
|
netadr_t adr;
|
|
int challenge;
|
|
int time;
|
|
} challenge_t;
|
|
|
|
typedef struct
|
|
{
|
|
int spawncount; // number of servers spawned since start,
|
|
// used to check late spawns
|
|
client_t clients[MAX_CLIENTS];
|
|
int num_clients;
|
|
int serverflags; // episode completion information
|
|
|
|
double last_heartbeat;
|
|
int heartbeat_sequence;
|
|
svstats_t stats;
|
|
|
|
char info[MAX_SERVERINFO_STRING];
|
|
|
|
// log messages are used so that fraglog processes can get stats
|
|
int logsequence; // the message currently being filled
|
|
double logtime; // time of last swap
|
|
sizebuf_t log[2];
|
|
byte log_buf[2][MAX_DATAGRAM];
|
|
|
|
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
|
|
} server_static_t;
|
|
|
|
//=============================================================================
|
|
// DoSflood protection
|
|
//=============================================================================
|
|
typedef struct
|
|
{
|
|
netadr_t adr;
|
|
double issued;
|
|
int floodcount;
|
|
int cmdcount;
|
|
double firstseen;
|
|
} flood_t;
|
|
|
|
typedef enum
|
|
{
|
|
FLOOD_PING,
|
|
FLOOD_LOG,
|
|
FLOOD_CONNECT,
|
|
FLOOD_STATUS,
|
|
FLOOD_RCON,
|
|
FLOOD_BAN
|
|
} flood_enum_t;
|
|
|
|
#define DOSFLOODCMDS 6
|
|
#define DOSFLOODIP 64 // remember latest 64 IP's for each cmd.
|
|
|
|
//=============================================================================
|
|
|
|
// 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
|
|
#define MOVETYPE_PPUSH 13 // no clip to world, push and crush
|
|
|
|
// 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
|
|
|
|
#define MULTICAST_ALL 0
|
|
#define MULTICAST_PHS 1
|
|
#define MULTICAST_PVS 2
|
|
|
|
#define MULTICAST_ALL_R 3
|
|
#define MULTICAST_PHS_R 4
|
|
#define MULTICAST_PVS_R 5
|
|
|
|
//============================================================================
|
|
// FIXME: declare exported variables in their own relevant .h
|
|
|
|
extern cvar_t *sv_mintic, *sv_maxtic;
|
|
extern cvar_t *sv_maxspeed;
|
|
|
|
extern netadr_t master_adr[MAX_MASTERS]; // address of the master server
|
|
|
|
extern cvar_t *spawn;
|
|
extern cvar_t *teamplay;
|
|
extern cvar_t *deathmatch;
|
|
extern cvar_t *fraglimit;
|
|
extern cvar_t *timelimit;
|
|
|
|
extern server_static_t svs; // persistant server info
|
|
extern char *svs_info; // evil memory saving hack :)
|
|
extern server_t sv; // local server
|
|
|
|
extern client_t *host_client;
|
|
|
|
extern edict_t *sv_player;
|
|
|
|
extern char localmodels[MAX_MODELS][5]; // inline model names for precache
|
|
|
|
extern char localinfo[MAX_LOCALINFO_STRING+1];
|
|
|
|
extern int host_hunklevel;
|
|
extern QFile *sv_logfile;
|
|
extern QFile *sv_fraglogfile;
|
|
|
|
extern double sv_frametime;
|
|
|
|
extern progs_t sv_pr_state;
|
|
|
|
//===========================================================
|
|
// FIXME: declare exported functions in their own relevant .h
|
|
|
|
void SV_Error (char *error, ...) __attribute__((format(printf,1,2)));
|
|
void SV_Init (void);
|
|
void SV_Progs_Init (void);
|
|
void SV_Progs_Init_Cvars (void);
|
|
void SV_LoadProgs (void);
|
|
|
|
void Con_Printf (char *fmt, ...) __attribute__((format(printf,1,2)));
|
|
void Con_DPrintf (char *fmt, ...) __attribute__((format(printf,1,2)));
|
|
|
|
//
|
|
// sv_main.c
|
|
//
|
|
void SV_Shutdown (void);
|
|
void SV_Frame (float time);
|
|
void SV_FinalMessage (char *message);
|
|
void SV_DropClient (client_t *drop);
|
|
int SV_CalcPing (client_t *cl);
|
|
void SV_FullClientUpdate (client_t *client, sizebuf_t *buf);
|
|
|
|
int SV_ModelIndex (char *name);
|
|
|
|
qboolean SV_CheckBottom (edict_t *ent);
|
|
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink);
|
|
|
|
void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg);
|
|
|
|
struct progs_s;
|
|
void SV_MoveToGoal (struct progs_s *pr);
|
|
|
|
void SV_SaveSpawnparms (void);
|
|
|
|
void SV_Physics_Client (edict_t *ent);
|
|
|
|
void SV_ExecuteUserCommand (char *s);
|
|
void SV_InitOperatorCommands (void);
|
|
|
|
void SV_SendServerinfo (client_t *client);
|
|
void SV_ExtractFromUserinfo (client_t *cl);
|
|
|
|
|
|
void Master_Heartbeat (void);
|
|
void Master_Packet (void);
|
|
|
|
//
|
|
// sv_init.c
|
|
//
|
|
void SV_SpawnServer (char *server);
|
|
void SV_FlushSignon (void);
|
|
|
|
|
|
//
|
|
// sv_phys.c
|
|
//
|
|
void SV_ProgStartFrame (void);
|
|
void SV_Physics (void);
|
|
void SV_CheckVelocity (edict_t *ent);
|
|
void SV_AddGravity (edict_t *ent, float scale);
|
|
qboolean SV_RunThink (edict_t *ent);
|
|
void SV_Physics_Toss (edict_t *ent);
|
|
void SV_RunNewmis (void);
|
|
void SV_Impact (edict_t *e1, edict_t *e2);
|
|
void SV_SetMoveVars(void);
|
|
|
|
//
|
|
// sv_send.c
|
|
//
|
|
void SV_SendClientMessages (void);
|
|
|
|
void SV_Multicast (vec3_t origin, int to);
|
|
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
|
|
float attenuation);
|
|
void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...) __attribute__((format(printf,3,4)));
|
|
void SV_BroadcastPrintf (int level, char *fmt, ...) __attribute__((format(printf,2,3)));
|
|
void SV_BroadcastCommand (char *fmt, ...) __attribute__((format(printf,1,2)));
|
|
void SV_SendMessagesToAll (void);
|
|
void SV_FindModelNumbers (void);
|
|
|
|
//
|
|
// sv_user.c
|
|
//
|
|
void SV_ExecuteClientMessage (client_t *cl);
|
|
void SV_UserInit (void);
|
|
void SV_TogglePause (const char *msg);
|
|
|
|
//
|
|
// svonly.c
|
|
//
|
|
typedef enum {RD_NONE, RD_CLIENT, RD_PACKET} redirect_t;
|
|
void SV_BeginRedirect (redirect_t rd);
|
|
void SV_EndRedirect (void);
|
|
|
|
//
|
|
// sv_ccmds.c
|
|
//
|
|
void SV_Status_f (void);
|
|
|
|
//
|
|
// sv_ents.c
|
|
//
|
|
void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg);
|
|
|
|
//
|
|
// sv_nchan.c
|
|
//
|
|
void ClientReliableCheckBlock(client_t *cl, int maxsize);
|
|
void ClientReliable_FinishWrite(client_t *cl);
|
|
void ClientReliableWrite_Begin(client_t *cl, int c, int maxsize);
|
|
void ClientReliableWrite_Angle(client_t *cl, float f);
|
|
void ClientReliableWrite_Angle16(client_t *cl, float f);
|
|
void ClientReliableWrite_Byte(client_t *cl, int c);
|
|
void ClientReliableWrite_Char(client_t *cl, int c);
|
|
void ClientReliableWrite_Float(client_t *cl, float f);
|
|
void ClientReliableWrite_Coord(client_t *cl, float f);
|
|
void ClientReliableWrite_Long(client_t *cl, int c);
|
|
void ClientReliableWrite_Short(client_t *cl, int c);
|
|
void ClientReliableWrite_String(client_t *cl, char *s);
|
|
void ClientReliableWrite_SZ(client_t *cl, void *data, int len);
|
|
|
|
#endif // _SERVER_H
|