- #include "quakedef.h"
+ #ifndef CL_PARSE_H
+ #define CL_PARSE_H
- void CL_ParseBaseline (entity_t *ent, int large);
+ #include "qtypes.h"
+ #include "cvar.h"
++struct entity_s;
+
-extern cvar_t qport;
++extern struct cvar_s qport;
+
+ void CL_Parse_Init(void);
+ void CL_Parse_Shutdown(void);
+ void CL_ParseServerMessage(void);
+ void CL_Parse_DumpPacket(void);
+ void CL_Parse_ErrorCleanUp(void);
+ void QW_CL_StartUpload(unsigned char *data, int size);
+ void CL_KeepaliveMessage(qbool readmessages); // call this during loading of large content
++void CL_ParseBaseline (struct entity_s *ent, int large);
+void CL_ParseClientdata (void);
+void CL_ParseStatic (int large);
+void CL_ParseStaticSound (int large);
+void CL_ParseEffect (void);
+void CL_ParseEffect2 (void);
+void CL_ParseServerInfo (void);
+qbool CL_ExaminePrintString(const char *text);
+void CL_ParseStartSoundPacket(int largesoundindex);
+void CL_ParseTempEntity(void);
+void QW_CL_UpdateUserInfo(void);
+void QW_CL_SetInfo(void);
+void QW_CL_ServerInfo(void);
+void QW_CL_ParseDownload(void);
+void QW_CL_ParseModelList(void);
+void QW_CL_ParseNails(void);
+void CL_UpdateItemsAndWeapon(void);
+void QW_CL_ParseSoundList(void);
+void CL_SignonReply (void);
+void CL_NetworkTimeReceived(double newtime);
+void CL_ParseDownload(void);
+void CL_ParseTrailParticles(void);
+void CL_ParsePointParticles(void);
- void CL_ParsePointParticles1(void);
++void CL_ParsePointParticles1(void);
+
+ #endif
--- /dev/null
- dp_model_t *model = Mod_ForName(s, false, false, s[0] == '*' ? cl.model_name[1] : NULL);
+#include "cl_protocol_basenq.h"
+
+static void Netmsg_svc_showlmp (protocol_t *protocol) // [string] iconlabel [string] lmpfile [short] x [short] y
+{
+ if (gamemode == GAME_TENEBRAE)
+ {
+ // particle effect
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ (void) MSG_ReadByte(&cl_message);
+ MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+ }
+ else
+ SHOWLMP_decodeshow();
+}
+
+static void Netmsg_svc_hidelmp (protocol_t *protocol) // [string] iconlabel
+{
+ if (gamemode == GAME_TENEBRAE)
+ {
+ // repeating particle effect
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ protocol->ReadCoord(&cl_message);
+ (void) MSG_ReadByte(&cl_message);
+ MSG_ReadLong(&cl_message);
+ MSG_ReadLong(&cl_message);
+ MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+ }
+ else
+ SHOWLMP_decodehide();
+}
+
+static void Netmsg_svc_skybox (protocol_t *protocol) // [string] skyname
+{
+ R_SetSkyBox(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)));
+}
+
+static void Netmsg_svc_downloaddata (protocol_t *protocol) // 50 // [int] start [short] size [variable length] data
+{
+ CL_ParseDownload();
+}
+
+static void Netmsg_svc_updatestatubyte (protocol_t *protocol) // 51 // [byte] stat [byte] value
+{
+ int i = MSG_ReadByte(&cl_message);
+ if (i < 0 || i >= MAX_CL_STATS)
+ Host_Error ("svc_updatestat: %i is invalid", i);
+ cl.stats[i] = MSG_ReadByte(&cl_message);
+}
+
+static void Netmsg_svc_effect (protocol_t *protocol) // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
+{
+ CL_ParseEffect ();
+}
+
+static void Netmsg_svc_effect2 (protocol_t *protocol) // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
+{
+ CL_ParseEffect2 ();
+}
+
+// FIXME: Lazy
+static void Netmsg_svc_precache (protocol_t *protocol) // 54 // short soundindex instead of byte
+{
+ if (protocol->num == PROTOCOL_DARKPLACES1 || protocol->num == PROTOCOL_DARKPLACES2 || protocol->num == PROTOCOL_DARKPLACES3)
+ {
+ // was svc_sound2 in protocols 1, 2, 3, removed in 4, 5, changed to svc_precache in 6
+ CL_ParseStartSoundPacket(true);
+ }
+ else
+ {
+ // was svc_sound2 in protocols 1, 2, 3, removed in 4, 5, changed to svc_precache in 6
+ int i = (unsigned short)MSG_ReadShort(&cl_message);
+ char *s = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring));
+ if (i < 32768)
+ {
+ if (i >= 1 && i < MAX_MODELS)
+ {
++ model_t *model = Mod_ForName(s, false, false, s[0] == '*' ? cl.model_name[1] : NULL);
+ if (!model)
+ Con_DPrintf("svc_precache: Mod_ForName(\"%s\") failed\n", s);
+ cl.model_precache[i] = model;
+ }
+ else
+ Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_MODELS);
+ }
+ else
+ {
+ i -= 32768;
+ if (i >= 1 && i < MAX_SOUNDS)
+ {
+ sfx_t *sfx = S_PrecacheSound (s, true, true);
+ if (!sfx && snd_initialized.integer)
+ Con_DPrintf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s);
+ cl.sound_precache[i] = sfx;
+ }
+ else
+ Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_SOUNDS);
+ }
+ }
+}
+
+static void Netmsg_svc_spawnbaseline2 (protocol_t *protocol) // 55 // short modelindex instead of byte
+{
+ int i = (unsigned short) MSG_ReadShort(&cl_message);
+ if (i < 0 || i >= MAX_EDICTS)
+ Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
+ if (i >= cl.max_entities)
+ CL_ExpandEntities(i);
+ CL_ParseBaseline (cl.entities + i, true);
+}
+
+static void Netmsg_svc_spawnstatic2 (protocol_t *protocol) // 56 // short modelindex instead of byte
+{
+ CL_ParseStatic (true);
+}
+
+static void Netmsg_svc_entities (protocol_t *protocol) // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
+{
+ if (cls.signon == SIGNONS - 1)
+ {
+ // first update is the final signon stage
+ cls.signon = SIGNONS;
+ CL_SignonReply ();
+ }
+
+ protocol->ReadFrame();
+}
+
+static void Netmsg_svc_csqcentities (protocol_t *protocol) // 58 // [short] entnum [variable length] entitydata ... [short] 0x0000
+{
+ CSQC_ReadEntities();
+}
+
+static void Netmsg_svc_spawnstaticsound2 (protocol_t *protocol) // 59 // [coord3] [short] samp [byte] vol [byte] aten
+{
+ CL_ParseStaticSound (true);
+}
+
+static void Netmsg_svc_trailparticles (protocol_t *protocol) // 60 // [short] entnum [short] effectnum [vector] start [vector] end
+{
+ CL_ParseTrailParticles();
+}
+
+static void Netmsg_svc_pointparticles (protocol_t *protocol) // 61 // [short] effectnum [vector] start [vector] velocity [short] count
+{
+ CL_ParsePointParticles();
+}
+
+static void Netmsg_svc_pointparticles1 (protocol_t *protocol) // 62 // [short] effectnum [vector] start, same as Netmsg_svc_pointparticles except velocity is zero and count is 1
+{
+ CL_ParsePointParticles1();
+}
+#define NETMSG_DPEXT_SVC \
+ NETMSG_BASENQ_SVC, \
+ {"svc_showlmp", Netmsg_svc_showlmp}, \
+ {"svc_hidelmp", Netmsg_svc_hidelmp}, \
+ {"svc_skybox", Netmsg_svc_skybox}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"", NULL}, \
+ {"svc_downloaddata", Netmsg_svc_downloaddata}, \
+ {"svc_updatestatubyte", Netmsg_svc_updatestatubyte}, \
+ {"svc_effect", Netmsg_svc_effect}, \
+ {"svc_effect2", Netmsg_svc_effect2}, \
+ {"svc_sound2", Netmsg_svc_precache}, \
+ {"svc_spawnbaseline2", Netmsg_svc_spawnbaseline2}, \
+ {"svc_spawnstatic2", Netmsg_svc_spawnstatic2}, \
+ {"svc_entities", Netmsg_svc_entities}, \
+ {"svc_csqcentities", Netmsg_svc_csqcentities}, \
+ {"svc_spawnstaticsound2", Netmsg_svc_spawnstaticsound2}, \
+ {"svc_trailparticles", Netmsg_svc_trailparticles}, \
+ {"svc_pointparticles", Netmsg_svc_pointparticles}, \
+ {"svc_pointparticles1", Netmsg_svc_pointparticles1}
#ifndef NET_H
#define NET_H
+ #include <stdarg.h>
+ #include "qtypes.h"
+ #include "crypto.h"
#include "lhnet.h"
-#include "common.h"
+#include "protocol.h"
+ struct cmd_state_s;
++struct sizebuf_s;
#define NET_HEADERSIZE (2 * sizeof(unsigned int))
extern char cl_readstring[MAX_INPUTLINE];
extern char sv_readstring[MAX_INPUTLINE];
- extern cvar_t sv_public;
+ extern struct cvar_s sv_public;
- extern cvar_t net_fakelag;
+ extern struct cvar_s net_fakelag;
- extern cvar_t cl_netport;
- extern cvar_t sv_netport;
- extern cvar_t net_address;
- extern cvar_t net_address_ipv6;
- extern cvar_t net_usesizelimit;
- extern cvar_t net_burstreserve;
+ extern struct cvar_s cl_netport;
+ extern struct cvar_s sv_netport;
+ extern struct cvar_s net_address;
+ extern struct cvar_s net_address_ipv6;
+ extern struct cvar_s net_usesizelimit;
+ extern struct cvar_s net_burstreserve;
qbool NetConn_CanSend(netconn_t *conn);
- int NetConn_Transmit(netconn_t *conn, sizebuf_t *data, protocol_t *protocol, int rate, int burstsize, qbool quakesignon_suppressreliables);
-int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, int burstsize, qbool quakesignon_suppressreliables);
++int NetConn_Transmit(netconn_t *conn, struct sizebuf_s *data, protocol_t *protocol, int rate, int burstsize, qbool quakesignon_suppressreliables);
qbool NetConn_HaveClientPorts(void);
qbool NetConn_HaveServerPorts(void);
void NetConn_CloseClientPorts(void);
#ifndef PROTOCOL_H
#define PROTOCOL_H
-// protocolversion_t is defined in common.h
-enum protocolversion_e;
+ #include <stddef.h>
+ #include "qtypes.h"
+ #include "qdefs.h"
+ #include "qstats.h"
+ struct mempool_s;
+ struct sizebuf_s;
-enum protocolversion_e Protocol_EnumForName(const char *s);
-const char *Protocol_NameForEnum(enum protocolversion_e p);
-enum protocolversion_e Protocol_EnumForNumber(int n);
-int Protocol_NumberForEnum(enum protocolversion_e p);
+
+enum
+{
+ PROTOCOL_UNKNOWN,
+ PROTOCOL_QUAKE = 15, ///< quake (aka netquake/normalquake/nq) protocol
+ PROTOCOL_QUAKEDP = 15, ///< darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as no extended features are used
+ PROTOCOL_QUAKEWORLD = 28, ///< quakeworld protocol
+ PROTOCOL_DARKPLACES1 = 96, ///< uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta compression method
+ PROTOCOL_DARKPLACES2 = 97, ///< various changes
+ PROTOCOL_NEHAHRAMOVIE = 250, ///< Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but only ever used by neh_gl.exe), this is potentially backwards compatible with quake protocol as long as no extended features are used (but in actuality the neh_gl.exe which wrote this protocol ALWAYS wrote the extended information)
+ PROTOCOL_DARKPLACES3 = 3500, ///< uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snapshot updates on a QuakeWorld-like protocol, but it is broken and impossible to fix
+ PROTOCOL_DARKPLACES4 = 3501, ///< various changes
+ PROTOCOL_DARKPLACES5 = 3502, ///< uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at http://www.garagegames.com/articles/networking1/
+ PROTOCOL_DARKPLACES6 = 3503, ///< various changes
+ PROTOCOL_DARKPLACES7 = 3504, ///< added QuakeWorld-style movement protocol to allow more consistent prediction
+ PROTOCOL_NEHAHRABJP = 10000, ///< same as QUAKEDP but with 16bit modelindex
+ PROTOCOL_NEHAHRABJP2 = 10001, ///< same as NEHAHRABJP but with 16bit soundindex
+ PROTOCOL_NEHAHRABJP3 = 10002 ///< same as NEHAHRABJP2 but with some changes
+};
+
+typedef struct protocol_netmsg_s protocol_netmsg_t;
+typedef struct protocol_s protocol_t;
+
+struct protocol_s
+{
+ const char *name;
+ const int num;
+
+ const int max_edicts;
+
+ void (*WriteCoord)(sizebuf_t *, float);
+ void (*WriteAngle)(sizebuf_t *, float);
+ void (*WriteVector)(sizebuf_t *, const vec3_t);
+ float (*ReadCoord)(sizebuf_t *);
+ float (*ReadAngle)(sizebuf_t *);
+ void (*ReadVector)(sizebuf_t *, vec3_t);
+
+ void (*ReadFrame)(void);
+
+ // TODO: Other info?
+ struct protocol_netmsg_s *svc;
+ struct protocol_netmsg_s *clc;
+};
+
+struct protocol_netmsg_s
+{
+ const int size;
+ struct
+ {
+ const char *name;
+ void (*func)(struct protocol_s *);
+ } msg[256];
+};
+
+typedef struct protocol_s protocol_t;
+typedef struct protocol_netmsg_s protocol_netmsg_t;
+
+extern protocol_t protocol_netquake;
+extern protocol_t protocol_quakedp;
+extern protocol_t protocol_quakeworld;
+extern protocol_t protocol_dpp1;
+extern protocol_t protocol_dpp2;
+extern protocol_t protocol_dpp3;
+extern protocol_t protocol_dpp4;
+extern protocol_t protocol_dpp5;
+extern protocol_t protocol_dpp6;
+extern protocol_t protocol_dpp7;
+extern protocol_t protocol_nehahramovie;
+extern protocol_t protocol_nehahrabjp;
+extern protocol_t protocol_nehahrabjp2;
+extern protocol_t protocol_nehahrabjp3;
+
+extern protocol_netmsg_t netmsg_nq_svc;
+extern protocol_netmsg_t netmsg_qw_svc;
+extern protocol_netmsg_t netmsg_dpext_svc;
+extern protocol_netmsg_t netmsg_base_clc;
+
+#define PF_PREDICTION (1<<0)
+#define PF_MOVE_CROUCH (1<<1)
+
+protocol_t *Protocol_ForName(const char *name);
+protocol_t *Protocol_ForNumber(int num);
void Protocol_Names(char *buffer, size_t buffersize);
#define ENTITYSIZEPROFILING_START(msg, num, flags) \