//each server that we are connected to has it's own state. //it should be easy enough to use one thread per server. //mvd info is forwarded to other proxies instantly //qwd stuff is buffered and delayed. :( //this means that when a new proxy connects, we have to send initial state as well as a chunk of pending state, expect to need to send new data before the proxy even has all the init stuff. We may need to raise MAX_PROXY_BUFFER to be larger than on the server #ifdef _WIN32 #include #pragma comment (lib, "wsock32.lib") #define qerrno WSAGetLastError() #define EWOULDBLOCK WSAEWOULDBLOCK #ifndef _DEBUG #define static //it breaks my symbol lookups. :( #endif #elif defined(__CYGWIN__) #include #include #include #include #include #include #include #ifndef SOCKET #define SOCKET int #endif #ifndef INVALID_SOCKET #define INVALID_SOCKET -1 #endif #define qerrno errno #define ioctlsocket ioctl #define closesocket close #else #error "Please insert required headers here" //try the cygwin ones #endif #include #define VERSION "0.01" //this will be added to the serverinfo #define PROX_DEFAULTLISTENPORT 27501 #define PROX_DEFAULTSERVER "localhost:27500" #define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here. #define MAX_USERINFO 192 #define MAX_CLIENTS 32 #define MAX_STATS 32 #define MAX_LIST 256 #define MAX_MODELS MAX_LIST #define MAX_SOUNDS MAX_LIST #define MAX_ENTITIES 512 #define MAX_STATICSOUNDS 64 #define MAX_LIGHTSTYLES 64 #define MAX_PROXY_BUFFER (1<<14) //must be power-of-two #define PREFERED_PROXY_BUFFER 1500 //the ammount of data we try to leave in our input buffer (must be large enough to contain any single mvd frame) #define ENTS_PER_FRAME 512 //max number of entities per frame. #define ENTITY_FRAMES 64 //number of frames to remember for deltaing typedef enum {false, true} qboolean; typedef unsigned char netadr_t[64]; #define MAX_MSGLEN 1400 #define MAX_BACKBUF_SIZE 1000 //this is smaller so we don't loose entities when lagging typedef struct { unsigned int readpos; unsigned int cursize; unsigned int maxsize; char *data; unsigned int startpos; qboolean overflowed; qboolean allowoverflow; } netmsg_t; typedef struct { SOCKET sock; netadr_t remote_address; unsigned short qport; unsigned int last_received; unsigned int cleartime; int reliable_length; qboolean drop; netmsg_t message; char message_buf[MAX_MSGLEN]; //reliable message being built char reliable_buf[MAX_MSGLEN]; //reliable message that we're making sure arrives. float rate; unsigned int incoming_acknowledged; unsigned int last_reliable_sequence; unsigned int incoming_reliable_acknowledged; unsigned int incoming_reliable_sequence; unsigned int reliable_sequence; unsigned int incoming_sequence; unsigned int outgoing_sequence; } netchan_t; typedef struct { #define MAX_QPATH 64 char name[MAX_QPATH]; } filename_t; typedef struct { unsigned char frame; unsigned char modelindex; unsigned char colormap; unsigned char skinnum; short origin[3]; unsigned char angles[3]; unsigned char effects; } entity_state_t; typedef struct { unsigned char frame; unsigned char modelindex; unsigned char skinnum; short origin[3]; unsigned short angles[3]; unsigned char effects; unsigned char weaponframe; } player_state_t; typedef struct { unsigned int stats[MAX_STATS]; char userinfo[MAX_USERINFO]; int ping; int frags; float entertime; qboolean active:1; qboolean gibbed:1; qboolean dead:1; player_state_t current; player_state_t old; } playerinfo_t; typedef struct { entity_state_t ents[ENTS_PER_FRAME]; //ouchie ouchie! unsigned short entnum[ENTS_PER_FRAME]; int numents; } packet_entities_t; #define MAX_BACK_BUFFERS 16 typedef struct viewer_s { qboolean drop; netchan_t netchan; qboolean maysend; qboolean chokeme; qboolean thinksitsconnected; int delta_frame; netmsg_t backbuf[MAX_BACK_BUFFERS]; //note data is malloced! int backbuffered; unsigned int currentstats[MAX_STATS]; unsigned int trackplayer; packet_entities_t frame[ENTITY_FRAMES]; struct viewer_s *next; float origin[3]; } viewer_t; typedef struct oproxy_s { qboolean flushing; qboolean drop; SOCKET sock; unsigned char buffer[MAX_PROXY_BUFFER]; unsigned int buffersize; //use cyclic buffering. unsigned int bufferpos; struct oproxy_s *next; } oproxy_t; typedef struct { short origin[3]; unsigned char soundindex; unsigned char volume; unsigned char attenuation; } staticsound_t; typedef struct sv_s { netadr_t serveraddress; unsigned char buffer[MAX_PROXY_BUFFER]; //this doesn't cycle. int buffersize; //it memmoves down unsigned int parsetime; int servercount; char gamedir[MAX_QPATH]; char mapname[256]; struct { float gravity; float maxspeed; float spectatormaxspeed; float accelerate; float airaccelerate; float waterfriction; float entgrav; float stopspeed; float wateraccelerate; float friction; } movevars; int cdtrack; entity_state_t baseline[MAX_ENTITIES]; entity_state_t curents[MAX_ENTITIES]; entity_state_t oldents[MAX_ENTITIES]; unsigned int entupdatetime[MAX_ENTITIES]; //to stop lerping when it's an old entity (bodies, stationary grenades, ...) int maxents; staticsound_t staticsound[MAX_STATICSOUNDS]; int staticsound_count; filename_t lightstyle[MAX_LIGHTSTYLES]; char serverinfo[MAX_SERVERINFO_STRING]; playerinfo_t players[MAX_CLIENTS]; filename_t modellist[MAX_MODELS]; filename_t soundlist[MAX_SOUNDS]; int modelindex_spike; // qw is wierd. FILE *file; unsigned int filelength; SOCKET sourcesock; SOCKET listenmvd; //tcp + mvd protocol SOCKET qwdsocket; //udp + quakeworld protocols viewer_t *viewers; oproxy_t *proxies; qboolean parsingconnectiondata; //so reject any new connects for now unsigned int curtime; unsigned int oldpackettime; unsigned int nextpackettime; int tcplistenportnum; int qwlistenportnum; char server[MAX_QPATH]; //options: qboolean chokeonnotupdated; qboolean lateforward; } sv_t; typedef struct { sv_t server; } qtv_t; unsigned char ReadByte(netmsg_t *b); unsigned short ReadShort(netmsg_t *b); unsigned int ReadLong(netmsg_t *b); float ReadFloat(netmsg_t *b); void ReadString(netmsg_t *b, char *string, int maxlen); #define clc_bad 0 #define clc_nop 1 //define clc_doublemove 2 #define clc_move 3 // [[usercmd_t] #define clc_stringcmd 4 // [string] message #define clc_delta 5 // [byte] sequence number, requests delta compression of message #define clc_tmove 6 // teleport request, spectator only #define clc_upload 7 // teleport request, spectator only #define svc_bad 0 #define svc_nop 1 //#define svc_disconnect 2 #define svc_updatestat 3 // [qbyte] [qbyte] //#define svc_version 4 // [long] server version //#define svc_setview 5 // [short] entity number #define svc_sound 6 // //#define svc_time 7 // [float] server time #define svc_print 8 // [qbyte] id [string] null terminated string #define svc_stufftext 9 // [string] stuffed into client's console buffer // the string should be \n terminated #define svc_setangle 10 // [angle3] set the view angle to this absolute value #define svc_serverdata 11 // [long] protocol ... #define svc_lightstyle 12 // [qbyte] [string] //#define svc_updatename 13 // [qbyte] [string] #define svc_updatefrags 14 // [qbyte] [short] //#define svc_clientdata 15 // //#define svc_stopsound 16 // //#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte] //#define svc_particle 18 // [vec3] #define svc_damage 19 //#define svc_spawnstatic 20 //#define svc_spawnstatic2 21 #define svc_spawnbaseline 22 #define svc_temp_entity 23 // variable //#define svc_setpause 24 // [qbyte] on / off //#define svc_signonnum 25 // [qbyte] used for the signon sequence #define svc_centerprint 26 // [string] to put in center of the screen //#define svc_killedmonster 27 //#define svc_foundsecret 28 #define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten //#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle //#define svc_finale 31 // [string] text #define svc_cdtrack 32 // [qbyte] track //#define svc_sellscreen 33 //#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt? #define svc_smallkick 34 // set client punchangle to 2 #define svc_bigkick 35 // set client punchangle to 4 #define svc_updateping 36 // [qbyte] [short] #define svc_updateentertime 37 // [qbyte] [float] #define svc_updatestatlong 38 // [qbyte] [long] #define svc_muzzleflash 39 // [short] entity #define svc_updateuserinfo 40 // [qbyte] slot [long] uid // [string] userinfo #define svc_download 41 // [short] size [size bytes] #define svc_playerinfo 42 // variable //#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 #define svc_chokecount 44 // [qbyte] packets choked #define svc_modellist 45 // [strings] #define svc_soundlist 46 // [strings] #define svc_packetentities 47 // [...] #define svc_deltapacketentities 48 // [...] //#define svc_maxspeed 49 // maxspeed change, for prediction //#define svc_entgravity 50 // gravity change, for prediction //#define svc_setinfo 51 // setinfo on a client #define svc_serverinfo 52 // serverinfo #define svc_updatepl 53 // [qbyte] [qbyte] //#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 #define dem_cmd 0 #define dem_read 1 #define dem_set 2 #define dem_multiple 3 #define dem_single 4 #define dem_stats 5 #define dem_all 6 #define dem_mask 7 #define PROTOCOL_VERSION 28 //flags on entities #define U_ORIGIN1 (1<<9) #define U_ORIGIN2 (1<<10) #define U_ORIGIN3 (1<<11) #define U_ANGLE2 (1<<12) #define U_FRAME (1<<13) #define U_REMOVE (1<<14) // REMOVE this entity, don't add it #define U_MOREBITS (1<<15) // if MOREBITS is set, these additional flags are read in next #define U_ANGLE1 (1<<0) #define U_ANGLE3 (1<<1) #define U_MODEL (1<<2) #define U_COLORMAP (1<<3) #define U_SKIN (1<<4) #define U_EFFECTS (1<<5) #define U_SOLID (1<<6) // the entity should be solid for prediction //flags on players #define PF_MSEC (1<<0) #define PF_COMMAND (1<<1) #define PF_VELOCITY1 (1<<2) #define PF_VELOCITY2 (1<<3) #define PF_VELOCITY3 (1<<4) #define PF_MODEL (1<<5) #define PF_SKINNUM (1<<6) #define PF_EFFECTS (1<<7) #define PF_WEAPONFRAME (1<<8) // only sent for view player #define PF_DEAD (1<<9) // don't block movement any more #define PF_GIB (1<<10) // offset the view height differently void InitNetMsg(netmsg_t *b, char *buffer, int bufferlength); unsigned char ReadByte(netmsg_t *b); unsigned short ReadShort(netmsg_t *b); unsigned int ReadLong(netmsg_t *b); float ReadFloat(netmsg_t *b); void ReadString(netmsg_t *b, char *string, int maxlen); void WriteByte(netmsg_t *b, unsigned char c); void WriteShort(netmsg_t *b, unsigned short l); void WriteLong(netmsg_t *b, unsigned int l); void WriteFloat(netmsg_t *b, float f); void WriteString2(netmsg_t *b, const char *str); void WriteString(netmsg_t *b, const char *str); void WriteData(netmsg_t *b, const char *data, int length); void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask); void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd); SOCKET QW_InitUDPSocket(int port); void QW_UpdateUDPStuff(sv_t *qtv);