From 339d478659f48318ffc0e942e4dc3be81806211f Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 30 Nov 2005 01:20:53 +0000 Subject: [PATCH] I wonder how much this will break. Ahh well. It works for me, and I need to go to bed. Well, plugins should be able to read/write files through the engine. audio decoding plugin interface is in (might be changed later). TCPConnect is in. msg_filter and scr_centersbar. some recording fixes too. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1634 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 1 + engine/client/cl_demo.c | 3 + engine/client/cl_ents.c | 37 ++- engine/client/cl_input.c | 2 +- engine/client/cl_main.c | 247 ++++++++++++++++--- engine/client/cl_parse.c | 31 ++- engine/client/cl_screen.c | 4 +- engine/client/client.h | 10 + engine/client/clq3_parse.c | 1 - engine/client/image.c | 14 +- engine/client/m_mp3.c | 29 ++- engine/client/m_options.c | 1 + engine/client/net_master.c | 3 - engine/client/pr_csqc.c | 2 +- engine/client/quakedef.h | 2 + engine/client/renderer.c | 14 +- engine/client/sbar.c | 29 ++- engine/client/snd_dma.c | 1 + engine/client/snd_mem.c | 198 ++++++++++----- engine/client/snd_ov.c | 77 ++---- engine/client/sys_win.c | 2 +- engine/client/view.c | 20 +- engine/client/zqtp.c | 15 -- engine/common/bothdefs.h | 4 + engine/common/cmd.c | 6 + engine/common/common.c | 49 ++++ engine/common/common.h | 3 + engine/common/fs.c | 3 + engine/common/net.h | 3 + engine/common/net_wins.c | 458 +++++++++++++++++++++++++++++++---- engine/common/netinc.h | 81 ++++--- engine/common/plugin.c | 135 ++++++++++- engine/common/pmove.c | 1 + engine/common/protocol.h | 4 +- engine/common/qvm.c | 2 + engine/ftequake/ftequake.dsp | 19 +- engine/gl/gl_alias.c | 17 +- engine/gl/gl_draw.c | 38 ++- engine/gl/gl_model.c | 2 +- engine/gl/gl_ppl.c | 1 + engine/gl/gl_rsurf.c | 1 + engine/gl/gl_screen.c | 4 +- engine/gl/gl_vidnt.c | 8 +- engine/gl/gl_warp.c | 6 +- engine/http/iweb.h | 2 +- engine/qclib/execloop.h | 2 +- engine/qclib/qcc_pr_lex.c | 2 - engine/server/q3g_public.h | 2 +- engine/server/server.h | 20 ++ engine/server/sv_ccmds.c | 40 +-- engine/server/sv_main.c | 3 + engine/server/sv_send.c | 20 +- engine/server/sv_user.c | 2 +- 53 files changed, 1235 insertions(+), 446 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index 8b4ff2628..6e64c994b 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -116,6 +116,7 @@ CLIENT_OBJS = $(CLIENT_ASM_OBJS) \ cl_cam.o \ cl_screen.o \ cl_ui.o \ + cl_ignore.o \ cl_cg.o \ clq3_parse.o \ pr_csqc.o \ diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index f7b38afa2..61f0b83db 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1105,7 +1105,10 @@ void CL_PlayDemo_f (void) Con_Printf ("Playing demo from %s.\n", name); if (!Q_strcasecmp(name + strlen(name) - 3, "mvd")) + { cls.demoplayback = DPB_MVD; + cls.findtrack = true; + } else cls.demoplayback = DPB_QUAKEWORLD; cls.state = ca_demostart; diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 8011794eb..3d05e62a1 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -256,7 +256,6 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean #ifdef PROTOCOLEXTENSIONS int morebits=0; #endif - vec3_t move; // set everything to the state we are delta'ing from *to = *from; @@ -436,12 +435,15 @@ void CL_ParsePacketEntities (qboolean delta) int word, newnum, oldnum; qboolean full; int from; -/* - cl.oldgametime = cl.gametime; - cl.oldgametimemark = cl.gametimemark; - cl.gametime = realtime; - cl.gametimemark = realtime; -*/ + + if (!(cls.fteprotocolextensions & PEXT_ACCURATETIMINGS)) + { + cl.oldgametime = cl.gametime; + cl.oldgametimemark = cl.gametimemark; + cl.gametime = realtime; + cl.gametimemark = realtime; + } + newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; newp = &cl.frames[newpacket].packet_entities; cl.frames[newpacket].invalid = false; @@ -1182,7 +1184,6 @@ void CL_RotateAroundTag(entity_t *ent, int num, int tagent, int tagnum) entity_state_t *ps; float *org=NULL, *ang=NULL; vec3_t axis[3]; - vec3_t destorg; float transform[12], parent[12], result[12], old[12], temp[12]; int model = 0; //these two are only initialised because msvc sucks at detecting usage. @@ -1442,13 +1443,10 @@ void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entities_t * packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp) { packet_entities_t *packnew, *packold; - entity_state_t *snew, *sold; int i; static float oldoldtime; //, spnum; - *servertime -= 0.1; - if (nolerp) { //force our emulated time to as late as we can. //this will disable all position interpolation @@ -1513,12 +1511,11 @@ void CL_LinkPacketEntities (void) packet_entities_t *pack; entity_state_t *state; lerpents_t *le; - float f; model_t *model; vec3_t old_origin; float autorotate; int i; - int oldpnum, newpnum; + int newpnum; //, spnum; dlight_t *dl; vec3_t angles; @@ -1679,8 +1676,6 @@ void CL_LinkPacketEntities (void) } else { - float a1, a2; - for (i=0 ; i<3 ; i++) { angles[i] = le->angles[i]; @@ -2295,15 +2290,15 @@ void CL_ParsePlayerinfo (void) memcpy(state, prevstate, sizeof(player_state_t)); info->prevcount = cl.parsecount; -/* if (cls.findtrack && info->stats[STAT_HEALTH] > 0) + if (cls.findtrack && info->stats[STAT_HEALTH] > 0) { - extern int ideal_track; - autocam = CAM_TRACK; - Cam_Lock(num); - ideal_track = num; +// extern int ideal_track; + autocam[0] = CAM_TRACK; + Cam_Lock(0, num); +// ideal_track = num; cls.findtrack = false; } -*/ + flags = MSG_ReadShort (); state->flags = MVD_TranslateFlags(flags); diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index bd700718e..3736ff79e 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -856,7 +856,7 @@ void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...) va_end (argptr); -// Con_Printf("Queing stringcmd %s\n", string); + Con_DPrintf("Queing stringcmd %s\n", string); #ifdef Q3CLIENT if (cls.protocol == CP_QUAKE3) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 7b33207c6..301ac1460 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -119,6 +119,7 @@ cvar_t cl_item_bobbing = {"cl_model_bobbing", "0"}; cvar_t requiredownloads = {"requiredownloads","1", NULL, CVAR_ARCHIVE}; cvar_t cl_standardchat = {"cl_standardchat", "0"}; +cvar_t msg_filter = {"msg_filter", "0"}; //0 for neither, 1 for mm1, 2 for mm2, 3 for both cvar_t cl_standardmsg = {"cl_standardmsg", "0"}; cvar_t cl_parsewhitetext = {"cl_parsewhitetext", "0"}; @@ -259,44 +260,11 @@ void CL_ConnectToDarkPlaces(char *challenge, netadr_t adr) cl.splitclients = 0; } -/* -======================= -CL_SendConnectPacket - -called by CL_Connect_f and CL_CheckResend -====================== -*/ -void CL_SendConnectPacket ( #ifdef PROTOCOL_VERSION_FTE - int ftepext, -#endif - int compressioncrc - /*, ...*/) //dmw new parms +unsigned int CL_SupportedFTEExtensions(void) { - netadr_t adr; - char data[2048]; - char playerinfo2[MAX_INFO_STRING]; - double t1, t2; -#ifdef PROTOCOL_VERSION_FTE - int fteprotextsupported=0; -#endif - int clients; - int c; + unsigned int fteprotextsupported = 0; -// JACK: Fixed bug where DNS lookups would cause two connects real fast -// Now, adds lookup time to the connect time. -// Should I add it to realtime instead?!?! - - if (cls.state != ca_disconnected) - return; - - if (cl_nopext.value) //imagine it's an unenhanced server - { - ftepext = 0; - compressioncrc = 0; - } - -#ifdef PROTOCOL_VERSION_FTE #ifdef PEXT_SCALE //dmw - protocol extensions fteprotextsupported |= PEXT_SCALE; #endif @@ -312,6 +280,9 @@ void CL_SendConnectPacket ( #ifdef PEXT_BULLETENS fteprotextsupported |= PEXT_BULLETENS; #endif +#ifdef PEXT_ACCURATETIMINGS + fteprotextsupported |= PEXT_ACCURATETIMINGS; +#endif #ifdef PEXT_ZLIBDL fteprotextsupported |= PEXT_ZLIBDL; #endif @@ -370,10 +341,54 @@ void CL_SendConnectPacket ( fteprotextsupported |= PEXT_DPFLAGS; #endif + return fteprotextsupported; +} +#endif + +/* +======================= +CL_SendConnectPacket + +called by CL_Connect_f and CL_CheckResend +====================== +*/ +void CL_SendConnectPacket ( +#ifdef PROTOCOL_VERSION_FTE + int ftepext, +#endif + int compressioncrc + /*, ...*/) //dmw new parms +{ + netadr_t adr; + char data[2048]; + char playerinfo2[MAX_INFO_STRING]; + double t1, t2; +#ifdef PROTOCOL_VERSION_FTE + int fteprotextsupported=0; +#endif + int clients; + int c; + +// JACK: Fixed bug where DNS lookups would cause two connects real fast +// Now, adds lookup time to the connect time. +// Should I add it to realtime instead?!?! + + if (cls.state != ca_disconnected) + return; + + if (cl_nopext.value) //imagine it's an unenhanced server + { + ftepext = 0; + compressioncrc = 0; + } + +#ifdef PROTOCOL_VERSION_FTE + fteprotextsupported = CL_SupportedFTEExtensions(); + fteprotextsupported &= ftepext; #ifdef Q2CLIENT - if (cls.protocol == CP_QUAKE2) + if (cls.protocol != CP_QUAKEWORLD) fteprotextsupported = 0; #endif @@ -732,6 +747,75 @@ void CLNQ_Connect_f (void) } #endif +#ifdef TCPCONNECT +void CL_TCPConnect_f (void) +{ + char buffer[6]; + int newsocket; + int len; + int _true = true; + + float giveuptime; + + char *server; + + if (Cmd_Argc() != 2) + { + Con_TPrintf (TLC_SYNTAX_CONNECT); + return; + } + + server = Cmd_Argv (1); + + CL_Disconnect_f (); + + Q_strncpyz (cls.servername, server, sizeof(cls.servername)); + + NET_StringToAdr(cls.servername, &cls.sockettcpdest); + + if (cls.sockettcp != INVALID_SOCKET) + closesocket (cls.sockettcp); + cls.sockettcp = INVALID_SOCKET; + cls.tcpinlen = 0; + + newsocket = TCP_OpenStream(cls.sockettcpdest); + if (newsocket == INVALID_SOCKET) + { + //failed + Con_Printf("Failed to connect, server is either down, firewalled, or on a different port\n"); + return; + } + + Con_Printf("Waiting for confirmation of server (10 secs)\n"); + + giveuptime = Sys_DoubleTime() + 10; + + while(giveuptime > Sys_DoubleTime()) + { + len = recv(newsocket, buffer, sizeof(buffer), 0); + if (!strncmp(buffer, "qizmo\n", 6)) + { + cls.sockettcp = newsocket; + break; + } + SCR_UpdateScreen(); + } + + if (cls.sockettcp == INVALID_SOCKET) + { + Con_Printf("Timeout - wrong server type\n"); + closesocket(newsocket); + return; + } + Con_Printf("Confirmed\n"); + + send(cls.sockettcp, buffer, sizeof(buffer), 0); + setsockopt(cls.sockettcp, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); + + CL_BeginServerConnect(); +} +#endif + /* ===================== CL_Rcon_f @@ -1012,6 +1096,15 @@ void CL_Disconnect (void) cls.protocol = CP_UNKNOWN; cl.servercount = 0; + cls.findtrack = false; + +#ifdef TCPCONNECT + if (cls.sockettcp != INVALID_SOCKET) + { + closesocket(cls.sockettcp); + cls.sockettcp = INVALID_SOCKET; + } +#endif } #undef serverrunning @@ -1406,6 +1499,32 @@ void CL_SetInfo_f (void) if (!stricmp(Cmd_Argv(1), pmodel_name) || !strcmp(Cmd_Argv(1), emodel_name)) return; + if (Cmd_Argv(1)[0] == '*') + { + int i; + if (!strcmp(Cmd_Argv(1), "*")) + if (!strcmp(Cmd_Argv(2), "")) + { //clear it out + char *k; + for(i=0;;) + { + k = Info_KeyForNumber(cls.userinfo, i); + if (!*k) + break; //no more. + else if (*k == '*') + i++; //can't remove * keys + else if ((var = Cvar_FindVar(k)) && var->flags&CVAR_SERVERINFO) + i++; //this one is a cvar. + else + Info_RemoveKey(cls.userinfo, k); //we can remove this one though, so yay. + } + + return; + } + Con_TPrintf (TL_STARKEYPROTECTED); + return; + } + var = Cvar_FindVar(Cmd_Argv(1)); if (var && (var->flags & CVAR_USERINFO)) { //get the cvar code to set it. the server might have locked it. @@ -1425,6 +1544,13 @@ void CL_SetInfo_f (void) } } +void CL_SaveInfo(FILE *f) +{ + fwrite("\n", 1, 1, f); + fwrite("setinfo * \"\"\n", 13, 1, f); + Info_WriteToFile(f, cls.userinfo, "setinfo", CVAR_USERINFO); +} + /* ==================== CL_Packet_f @@ -1491,7 +1617,17 @@ void CL_Packet_f (void) } *out = 0; +#ifdef TCPCONNECT + { + int tcpsock; //extra code to stop the packet command from sending to the server via tcp + tcpsock = cls.sockettcp; + cls.sockettcp = -1; + NET_SendPacket (NS_CLIENT, out-send, send, adr); + cls.sockettcp = tcpsock; + } +#else NET_SendPacket (NS_CLIENT, out-send, send, adr); +#endif } @@ -2462,6 +2598,7 @@ void CL_Init (void) Cvar_Register (&requiredownloads, cl_controlgroup); Cvar_Register (&cl_standardchat, cl_controlgroup); + Cvar_Register (&msg_filter, cl_controlgroup); Cvar_Register (&cl_standardmsg, cl_controlgroup); Cvar_Register (&cl_parsewhitetext, cl_controlgroup); Cvar_Register (&cl_nopext, cl_controlgroup); @@ -2501,6 +2638,9 @@ void CL_Init (void) Cmd_AddCommand ("quit", CL_Quit_f); Cmd_AddCommand ("connect", CL_Connect_f); +#ifdef TCPCONNECT + Cmd_AddCommand ("tcpconnect", CL_TCPConnect_f); +#endif #ifdef NQPROT Cmd_AddCommand ("nqconnect", CLNQ_Connect_f); #endif @@ -2552,6 +2692,8 @@ void CL_Init (void) #ifdef _WINDOWS Cmd_AddCommand ("windows", CL_Windows_f); #endif + + Ignore_Init(); } @@ -2716,7 +2858,9 @@ void Host_Frame (double time) #if defined(WINAVI) && !defined(NOMEDIA) if (cls.demoplayback && recordingdemo && recordavi_frametime>0.01) - time = recordavi_frametime; + { + realframetime = time = recordavi_frametime; + } #endif if (cls.demoplayback && cl_demospeed.value>0) @@ -2928,6 +3072,31 @@ void Host_FixupModelNames(void) simple_crypt(soundlist_name, sizeof(soundlist_name) - 1); } + + +#ifdef Q3CLIENT +void CL_ReadCDKey(void) +{ //q3 cdkey + //you don't need one, just use a server without sv_strictauth set to 0. + char *buffer; + buffer = COM_LoadTempFile("q3key"); + if (buffer) //a cdkey is meant to be 16 chars + { + cvar_t *var; + char *chr; + for (chr = buffer; *chr; chr++) + { + if (*(unsigned char*)chr < ' ') + { + *chr = '\0'; //don't get more than one line. + break; + } + } + var = Cvar_Get("cl_cdkey", buffer, CVAR_LATCH, "Q3 compatability"); + } +} +#endif + //============================================================================ @@ -3015,6 +3184,10 @@ void Host_Init (quakeparms_t *parms) Master_SetupSockets(); #endif +#ifdef Q3CLIENT + CL_ReadCDKey(); +#endif + // Con_Printf ("Exe: "__TIME__" "__DATE__"\n"); Con_TPrintf (TL_HEAPSIZE, parms->memsize/ (1024*1024.0)); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 360945e74..c8310345e 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // cl_parse.c -- parse a message received from the server #include "quakedef.h" +#include "cl_ignore.h" void CL_GetNumberedEntityInfo (int num, float *org, float *ang); void CLNQ_ParseDarkPlaces5Entities(void); @@ -184,7 +185,7 @@ char *svc_nqstrings[] = "dpsvc_spawnstaticsound2" }; -extern cvar_t requiredownloads, cl_standardchat; +extern cvar_t requiredownloads, cl_standardchat, msg_filter; int oldparsecountmod; int parsecountmod; double parsecounttime; @@ -2495,11 +2496,11 @@ void CL_NewTranslation (int slot) int i, j; int top, bottom; qbyte *dest, *source; + int local; #endif char *s; player_info_t *player; - int local; if (slot >= MAX_CLIENTS) Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS"); @@ -2720,12 +2721,11 @@ void CL_SetStat (int pnum, int stat, int value) if (stat == STAT_VIEWHEIGHT && cls.z_ext & Z_EXT_VIEWHEIGHT) cl.viewheight[pnum] = value; - if (stat == STAT_TIME && cls.z_ext & Z_EXT_SERVERTIME) + if (stat == STAT_TIME && (cls.fteprotocolextensions & PEXT_ACCURATETIMINGS)) { cl.oldgametime = cl.gametime; cl.oldgametimemark = cl.gametimemark; -// cl.servertime_works = true; cl.gametime = value * 0.001; cl.gametimemark = realtime; } @@ -3049,6 +3049,7 @@ char *CL_ParseChat(char *text, player_info_t **player) char *p; extern cvar_t cl_parsewhitetext; char *s; + int check_flood; flags = TP_CategorizeMessage (text, &offset, player); @@ -3094,6 +3095,16 @@ char *CL_ParseChat(char *text, player_info_t **player) if (flags == 2 && !TP_FilterMessage(text + offset)) return NULL; + + if ((int)msg_filter.value & flags) + return NULL; //filter chat + + check_flood = Ignore_Check_Flood(s, flags, offset); + if (check_flood == IGNORE_NO_ADD) + return NULL; + else if (check_flood == NO_IGNORE_ADD) + Ignore_Flood_Add(s); + } suppress_talksound = false; @@ -4145,8 +4156,9 @@ int MSG_ReadShortPQ (char **s) } void CLNQ_ParseProQuakeMessage (char *s) { - int cmd, i, j; - int team, frags, shirt, ping; + int cmd; + int ping; +// int team, shirt, frags, i, j; s++; cmd = *s++; @@ -4215,13 +4227,6 @@ void CLNQ_ParseProQuakeMessage (char *s) Host_Error ("CL_ParseProQuakeMessage: pqc_ping_times > MAX_CLIENTS"); cl.players[ping / 4096].ping = ping & 4095; } -// cl.last_ping_time = cl.time; - /* - Con_Printf("pqc_ping_times "); - for (i = 0 ; i < cl.maxclients ; i++) - Con_Printf("%4d ", cl.scores[i].ping); - Con_Printf("\n"); - */ break; } } diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 804315f21..83eae2496 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -800,7 +800,7 @@ void SCR_CalcRefdef (void) } size /= 100.0; - if (!cl_sbar.value && full) + if (cl_sbar.value!=1 && full) h = vid.height; else h = vid.height - sb_lines; @@ -813,7 +813,7 @@ void SCR_CalcRefdef (void) } r_refdef.vrect.height = vid.height * size; - if (cl_sbar.value || !full) { + if (cl_sbar.value==1 || !full) { if (r_refdef.vrect.height > vid.height - sb_lines) r_refdef.vrect.height = vid.height - sb_lines; } else if (r_refdef.vrect.height > vid.height) diff --git a/engine/client/client.h b/engine/client/client.h index 239956938..61dd4b4a4 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -143,6 +143,8 @@ typedef struct player_info_s int ping; qbyte pl; + qboolean ignored; + // skin information int topcolor; int bottomcolor; @@ -299,6 +301,7 @@ typedef struct } protocol; qboolean resendinfo; + qboolean findtrack; int framecount; @@ -316,6 +319,13 @@ typedef struct int socketip6; int socketipx; +#ifdef TCPCONNECT + int sockettcp; + netadr_t sockettcpdest; + unsigned char tcpinbuffer[1500]; + int tcpinlen; +#endif + enum {DL_NONE, DL_QW, DL_QWCHUNKS, DL_Q3, DL_QWPENDING, DL_HTTP, DL_FTP} downloadmethod; FILE *downloadqw; // file transfer from server char downloadtempname[MAX_OSPATH]; diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 5f0b4903d..dd52797f3 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -972,7 +972,6 @@ void CLQ3_SendAuthPacket(netadr_t gameserver) //this should be the right code, but it doesn't work. if (gameserver.type == NA_IP) { - char keydata[64]; char *key = Cvar_Get("cl_cdkey", "", 0, "Quake3 auth")->string; netadr_t authaddr; #define AUTHORIZE_SERVER_NAME "authorize.quake3arena.com:27952" diff --git a/engine/client/image.c b/engine/client/image.c index 9b9b64ded..12e462193 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -726,16 +726,16 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i #if defined(_WIN32) -#define JPEG_API VARGS -#include "jpeglib.h" -#include "jerror.h" -#pragma comment(lib, "../libs/jpeg.lib") + #define JPEG_API VARGS + #include "jpeglib.h" + #include "jerror.h" + #pragma comment(lib, "../libs/jpeg.lib") #else -//#include -#include -#include +// #include + #include + #include #endif diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 405afc310..67746c5b2 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -1113,7 +1113,7 @@ qboolean Media_ShowFilm(void) unsigned char *pa=roqfilm->y[0]; unsigned char *pb=roqfilm->u[0]; unsigned char *pc=roqfilm->v[0]; - int pix=0; + int pixel=0; int num_columns=(roqfilm->width)>>1; int y; int x; @@ -1141,19 +1141,19 @@ qboolean Media_ShowFilm(void) b = 116130 * u; t=r+y1; - framedata[pix] =(unsigned char) LIMIT(t); + framedata[pixel] =(unsigned char) LIMIT(t); t=g+y1; - framedata[pix+1] =(unsigned char) LIMIT(t); + framedata[pixel+1] =(unsigned char) LIMIT(t); t=b+y1; - framedata[pix+2] =(unsigned char) LIMIT(t); + framedata[pixel+2] =(unsigned char) LIMIT(t); t=r+y2; - framedata[pix+4] =(unsigned char) LIMIT(t); + framedata[pixel+4] =(unsigned char) LIMIT(t); t=g+y2; - framedata[pix+5] =(unsigned char) LIMIT(t); + framedata[pixel+5] =(unsigned char) LIMIT(t); t=b+y2; - framedata[pix+6] =(unsigned char) LIMIT(t); - pix+=8; + framedata[pixel+6] =(unsigned char) LIMIT(t); + pixel+=8; } if(y & 0x01) { pb += num_columns; pc += num_columns; } @@ -1329,7 +1329,7 @@ void Media_RecordFrame (void) return; if (recordingdemo) - if (scr_con_current > 0) + if (scr_con_current > 0 || !cl.validsequence) { scr_con_current=0; key_dest = key_game; @@ -1354,6 +1354,8 @@ void Media_RecordFrame (void) } else*/ { + if (recordavi_videotime > realtime+1) + recordavi_videotime = realtime; //urm, wrapped?.. if (recordavi_videotime > realtime) goto skipframe; recordavi_videotime += recordavi_frametime; @@ -1381,7 +1383,7 @@ void Media_RecordFrame (void) case CT_SCREENSHOT: { char filename[MAX_OSPATH]; - sprintf(filename, "%s%i.%s", capturefilenameprefix, captureframe++, capturecodec.string); + sprintf(filename, "%s/%8.8i.%s", capturefilenameprefix, captureframe++, capturecodec.string); SCR_ScreenShot(filename); } break; @@ -1421,6 +1423,9 @@ void Media_RecordAudioFrame (short *sample_buffer, int samples) return; } + if (captureaudiosamples > recordavi_wave_format.nSamplesPerSec) + captureaudiosamples = 0; //doh, this WILL cause a bit of wierd sound... + memcpy(captureaudiomem+captureaudiosamples*2, sample_buffer, samples*2); captureaudiosamples+=samples/2; @@ -1504,7 +1509,7 @@ void Media_RecordFilm_f (void) recordavi_frametime = 1/capturerate.value; - if (fourcc) + if (*fourcc) { if (!strcmp(fourcc, "tga") || !strcmp(fourcc, "png") || @@ -1648,7 +1653,7 @@ void Media_RecordDemo_f(void) scr_con_current=0; key_dest = key_game; - if (recordavi_video_stream) + if (capturetype != CT_NONE) recordingdemo = true; } #else diff --git a/engine/client/m_options.c b/engine/client/m_options.c index eff1bb6cc..3b2c5052c 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -365,6 +365,7 @@ typedef struct { presetinfo_t preset[] = { {"r_presetname", {"286", "fast", "default", "nice", "realtime"}}, + {"gl_texturemode", {"nn", "ln", "ln", "ll", "ll"}}, {"r_particlesdesc", {"none", "highfps", "spikeset", "spikeset", "spikeset"}}, {"r_stains", {"0", "0", "1", "1", "1"}}, {"r_drawflat", {"1", "0", "0", "0", "0"}}, diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 821bd769f..1e7229e07 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -116,9 +116,6 @@ void Master_SetupSockets(void) pollsocketsIPX[i] = INVALID_SOCKET; } - -void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s); - void Master_HideServer(serverinfo_t *server) { int i, j; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 31bcdbeb1..0ad982b54 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -848,7 +848,7 @@ static void buildmatricies(void) ML_ModelViewMatrix(modelview, r_refdef.viewangles, r_refdef.vieworg); ML_ProjectionMatrix2(proj, r_refdef.fov_x, r_refdef.fov_y); Matrix4_Multiply(proj, modelview, mvp); - Matrix4x4_Invert_Simple(mvpi, mvp); //not actually used in this function. + Matrix4x4_Invert_Simple((matrix4x4_t*)mvpi, (matrix4x4_t*)mvp); //not actually used in this function. csqc_rebuildmatricies = false; } diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index b4bd8fed7..0284fc2b6 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -73,6 +73,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #pragma warning(3:4674) // dtor of thrown object is inaccessible #pragma warning(3:4705) // statement has no effect (example: a+1;) +#pragma warning(4:4013) // statement has no effect (example: a+1;) + #pragma warning( 4 : 4267) //truncation from const double to float #endif diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 8404c910a..8e628544f 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -85,6 +85,7 @@ static cvar_t vid_width = {"vid_width", "640", NULL, CVAR_ARCHIVE|CVAR_RENDERERL static cvar_t vid_height = {"vid_height", "480", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH}; static cvar_t vid_refreshrate = {"vid_displayfrequency", "0", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH}; +cvar_t gl_texturemode = {"gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST"}; cvar_t gl_motionblur = {"gl_motionblur", "0"}; cvar_t gl_motionblurscale = {"gl_motionblurscale", "1"}; cvar_t gl_fontedgeclamp = {"gl_fontedgeclamp", "0"}; //gl blends. Set this to 1 to stop the outside of your conchars from being visible @@ -148,6 +149,7 @@ cvar_t gl_mylumassuck = {"gl_mylumassuck", "0"}; cvar_t scr_sshot_type = {"scr_sshot_type", "jpg"}; +cvar_t scr_centersbar = {"scr_centersbar", "0"}; cvar_t scr_consize = {"scr_consize", "0.5"}; cvar_t scr_viewsize = {"viewsize","100", NULL, CVAR_ARCHIVE}; cvar_t scr_fov = {"fov","90", NULL, CVAR_ARCHIVE}; // 10 - 170 @@ -313,11 +315,11 @@ void GLRenderer_Init(void) #endif Cvar_Register (&gl_nobind, GLRENDEREROPTIONS); - Cvar_Register (&gl_max_size, GLRENDEREROPTIONS); Cvar_Register (&gl_picmip, GLRENDEREROPTIONS); Cvar_Register (&gl_picmip2d, GLRENDEREROPTIONS); Cvar_Register (&r_drawdisk, GLRENDEREROPTIONS); + Cvar_Register (&gl_texturemode, GLRENDEREROPTIONS); Cvar_Register (&gl_savecompressedtex, GLRENDEREROPTIONS); Cvar_Register (&gl_compress, GLRENDEREROPTIONS); Cvar_Register (&gl_driver, GLRENDEREROPTIONS); @@ -447,7 +449,6 @@ void Renderer_Init(void) Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP); Cvar_Register (&vid_renderer, VIDCOMMANDGROUP); - Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP); Cvar_Register (&vid_fullscreen, VIDCOMMANDGROUP); // Cvar_Register (&vid_stretch, VIDCOMMANDGROUP); Cvar_Register (&vid_bpp, VIDCOMMANDGROUP); @@ -471,21 +472,12 @@ void Renderer_Init(void) Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); - Cvar_Register(&scr_conspeed, SCREENOPTIONS); - Cvar_Register(&scr_centertime, SCREENOPTIONS); - Cvar_Register(&scr_showram, SCREENOPTIONS); - Cvar_Register(&scr_showturtle, SCREENOPTIONS); - Cvar_Register(&scr_showpause, SCREENOPTIONS); - Cvar_Register(&scr_printspeed, SCREENOPTIONS); - Cvar_Register(&scr_allowsnap, SCREENOPTIONS); Cvar_Register(&scr_chatmodecvar, SCREENOPTIONS); Cvar_Register (&scr_sshot_type, SCREENOPTIONS); //screen - Cvar_Register (&scr_fov, SCREENOPTIONS); - Cvar_Register (&scr_viewsize, SCREENOPTIONS); Cvar_Register (&scr_conspeed, SCREENOPTIONS); Cvar_Register (&scr_showram, SCREENOPTIONS); Cvar_Register (&scr_showturtle, SCREENOPTIONS); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 6f3c21575..34bded17b 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -1643,10 +1643,19 @@ void Sbar_Draw (void) } else { //single player sbar takes full screen + + extern cvar_t scr_centersbar; + sbar_rect.width = vid.width; sbar_rect.height = vid.height; sbar_rect.x = 0; sbar_rect.y = 0; + + if (scr_centersbar.value) + { + sbar_rect.x = (vid.width - 320)/2; + sbar_rect.width -= sbar_rect.x; + } } if (sbarfailed) //files failed to load. @@ -1668,7 +1677,7 @@ void Sbar_Draw (void) { if (!cl.spectator || autocam[pnum] == CAM_TRACK) Sbar_DrawInventory (pnum); - if (!headsup || sbar_rect.width<512) + if ((!headsup || sbar_rect.width<512) && cl.deathmatch) Sbar_DrawFrags (); } @@ -1732,25 +1741,19 @@ void Sbar_Draw (void) Sbar_TeamOverlay(); #ifdef RGLQUAKE - if (cl.splitclients) + if (cl_sbar.value == 1 || scr_viewsize.value<100) { if (sb_showscores || sb_showteamscores || deadcount == cl.splitclients) sb_updates = 0; // clear unused areas in gl - #if 0 - { - int x = (sbar_rect.width - 320)>>1; - // left - if (x > 0) { - Draw_TileClear (0, sbar_rect.height - sb_lines, x, sb_lines); - Draw_TileClear (x+320, sbar_rect.height - sb_lines, sbar_rect.width - x+320, sb_lines); - } + if (cl.splitclients==1 && sbar_rect.x>0) + { // left + Draw_TileClear (0, sbar_rect.height - sb_lines, sbar_rect.x, sb_lines); } - #endif - if (sbar_rect.width > 320 && !headsup) - Draw_TileClear (320, sbar_rect.height - sb_lines, sbar_rect.width - 320, sb_lines); + if (sbar_rect.x + 320 <= sbar_rect.width && !headsup) + Draw_TileClear (sbar_rect.x + 320, sbar_rect.height - sb_lines, sbar_rect.width - (320), sb_lines); } #endif diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index d8a8d9e66..6098f10e1 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -1114,6 +1114,7 @@ S_UpdateAmbientSounds =================== */ char *Media_NextTrack(void); +mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p); void S_UpdateAmbientSounds (soundcardinfo_t *sc) { mleaf_t *l; diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index 094d02e94..69a120abb 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -148,73 +148,15 @@ void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, qbyte *data) //============================================================================= -/* -============== -S_LoadSound -============== -*/ -#ifdef AVAIL_MP3 -sfxcache_t *S_LoadMP3Sound (sfx_t *s); -#endif -sfxcache_t *S_LoadOVSound (sfx_t *s); +typedef sfxcache_t *(*S_LoadSound_t) (sfx_t *s, qbyte *data, int datalen, int sndspeed); -sfxcache_t *S_LoadSound (sfx_t *s) +sfxcache_t *S_LoadWavSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) { - char namebuffer[256]; - qbyte *data; wavinfo_t info; int len; sfxcache_t *sc; - qbyte stackbuf[1*1024]; // avoid dirtying the cache heap -// see if still in memory - sc = Cache_Check (&s->cache); - if (sc) - return sc; - -#ifdef AVAIL_OGGVORBIS - //ogg vorbis support. The only bit actual code outside snd_ov.c (excluding def for the function call) - sc = S_LoadOVSound(s); // try and load a replacement ov instead. - if (sc) - return sc; -#endif - -#ifdef AVAIL_MP3 - //mp3 support. The only bit actual code outside snd_mp3.c (excluding def for the function call) - sc = S_LoadMP3Sound(s); // try and load a replacement mp3 instead. - if (sc) - return sc; -#endif - - -//Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); -// load it in - - if (*s->name == '*') - { - Q_strcpy(namebuffer, "players/male/"); //q2 - Q_strcat(namebuffer, s->name+1); //q2 - } - else if (s->name[0] == '.' && s->name[1] == '.' && s->name[2] == '/') - Q_strcpy(namebuffer, s->name+3); - else - { - Q_strcpy(namebuffer, "sound/"); - Q_strcat(namebuffer, s->name); - } - -// Con_Printf ("loading %s\n",namebuffer); - - data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); - - if (!data) - { - //FIXME: check to see if qued for download. - Con_Printf ("Couldn't load %s\n", namebuffer); - return NULL; - } - - info = GetWavinfo (s->name, data, com_filesize); + info = GetWavinfo (s->name, data, datalen); if (info.numchannels < 1 || info.numchannels > 2) { Con_Printf ("%s has an unsupported quantity of channels.\n",s->name); @@ -226,7 +168,9 @@ sfxcache_t *S_LoadSound (sfx_t *s) sc = Cache_Alloc ( &s->cache, len + sizeof(sfxcache_t), s->name); if (!sc) + { return NULL; + } sc->length = info.samples; sc->loopstart = info.loopstart; @@ -239,6 +183,138 @@ sfxcache_t *S_LoadSound (sfx_t *s) return sc; } +sfxcache_t *S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed); + +S_LoadSound_t AudioInputPlugins[8] = +{ + S_LoadWavSound + +#ifdef AVAIL_OGGVORBIS +// , S_LoadOVSound +#endif +}; + +qboolean S_RegisterSoundInputPlugin(S_LoadSound_t loadfnc) +{ + int i; + for (i = 0; i < sizeof(AudioInputPlugins)/sizeof(AudioInputPlugins[0]); i++) + { + if (!AudioInputPlugins[i]) + { + AudioInputPlugins[i] = loadfnc; + return true; + } + } + return false; +} + +/* +============== +S_LoadSound +============== +*/ +#ifdef AVAIL_MP3 +sfxcache_t *S_LoadMP3Sound (sfx_t *s); +#endif + +sfxcache_t *S_LoadSound (sfx_t *s) +{ + char stackbuf[65536]; + char namebuffer[256]; + qbyte *data; + sfxcache_t *sc; + int i; + + char *name = s->name; + +// see if still in memory + sc = Cache_Check (&s->cache); + if (sc) + return sc; + + s->decoder = NULL; + + +#ifdef AVAIL_MP3 + //mp3 support. The only bit actual code outside snd_mp3.c (excluding def for the function call) + sc = S_LoadMP3Sound(s); // try and load a replacement mp3 instead. + if (sc) + return sc; +#endif + + + + if (name[1] == ':' && name[2] == '\\') + { + FILE *f; +#ifndef _WIN32 //convert from windows to a suitable alternative. + char unixname[128]; + sprintf(unixname, "/mnt/%c/%s", name[0]-'A'+'a', name+3); + name = unixname; + while (*name) + { + if (*name == '\\') + *name = '/'; + name++; + } + name = unixname; +#endif + + if ((f = fopen(name, "rb"))) + { + com_filesize = COM_filelength(f); + data = Hunk_TempAlloc (com_filesize); + fread(data, 1, com_filesize, f); + fclose(f); + } + else + { + Con_SafePrintf ("Couldn't load %s\n", namebuffer); + return NULL; + } + } + else + { + //Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); + // load it in + + if (*name == '*') + { + Q_strcpy(namebuffer, "players/male/"); //q2 + Q_strcat(namebuffer, name+1); //q2 + } + else if (name[0] == '.' && name[1] == '.' && name[2] == '/') + Q_strcpy(namebuffer, name+3); + else + { + Q_strcpy(namebuffer, "sound/"); + Q_strcat(namebuffer, name); + } + + // Con_Printf ("loading %s\n",namebuffer); + + data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); + } + + if (!data) + { + //FIXME: check to see if qued for download. + Con_Printf ("Couldn't load %s\n", namebuffer); + return NULL; + } + + for (i = sizeof(AudioInputPlugins)/sizeof(AudioInputPlugins[0])-1; i >= 0; i--) + { + if (AudioInputPlugins[i]) + { + sc = AudioInputPlugins[i](s, data, com_filesize, snd_speed); + if (sc) + return sc; + } + } + return NULL; +} + /* diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index eb34af6e4..476c08b94 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -15,12 +15,12 @@ HINSTANCE oggvorbislibrary; void *oggvorbislibrary; #endif -int (*p_ov_open_callbacks) (void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks); -int (*p_ov_clear)(OggVorbis_File *vf); -vorbis_info *(*p_ov_info)(OggVorbis_File *vf,int link); -vorbis_comment *(*p_ov_comment) (OggVorbis_File *vf,int link); -ogg_int64_t (*p_ov_pcm_total)(OggVorbis_File *vf,int i); -long (*p_ov_read)(OggVorbis_File *vf,char *buffer,int length, +int (VARGS *p_ov_open_callbacks) (void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks); +int (VARGS *p_ov_clear)(OggVorbis_File *vf); +vorbis_info *(VARGS *p_ov_info)(OggVorbis_File *vf,int link); +vorbis_comment *(VARGS *p_ov_comment) (OggVorbis_File *vf,int link); +ogg_int64_t (VARGS *p_ov_pcm_total)(OggVorbis_File *vf,int i); +long (VARGS *p_ov_read)(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream); @@ -48,67 +48,18 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf qbyte *COM_LoadFile (char *path, int usehunk); -sfxcache_t *S_LoadOVSound (sfx_t *s) +sfxcache_t *S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) { char namebuffer[MAX_OSPATH]; char *name; ovdecoderbuffer_t *buffer; FILE *f; - char *data; qboolean telluser; int len; name = s->name; - if (name[0] == '#') - strcpy(namebuffer, &name[1]); - else - sprintf (namebuffer, "sound/%s", name); - - len = strlen(namebuffer); - telluser = strcmp(namebuffer+len-4, ".wav"); - if (!telluser) - strcpy(namebuffer+len-4, ".ogg"); - - //try opening from a quake path - data = COM_LoadMallocFile(namebuffer); - if (!data) - {//if that didn't work, try opening direct from exe - this is media after all. - - if (!telluser) - return NULL; //never go out of the quake path for a wav replacement. -#ifndef _WIN32 - char unixname[128]; - if (name[1] == ':' && name[2] == '\\') //convert from windows to a suitable alternative. - { - sprintf(unixname, "/mnt/%c/%s", name[0]-'A'+'a', name+3); - name = unixname; - while (*name) - { - if (*name == '\\') - *name = '/'; - name++; - } - name = unixname; - } -#endif - if ((f = fopen(name, "rb"))) - { - com_filesize = COM_filelength(f); - data = BZ_Malloc(com_filesize); - fread(data, 1, com_filesize, f); - fseek(f, 0, SEEK_SET); - fclose(f); - f = NULL; - } - else - { - Con_SafePrintf ("Couldn't load %s\n", namebuffer); - return NULL; - } - } - if (!s->decoder) s->decoder = Z_Malloc(sizeof(ovdecoderbuffer_t) + sizeof(sfxdecode_t)); buffer = (ovdecoderbuffer_t*)(s->decoder+1); @@ -120,7 +71,7 @@ sfxcache_t *S_LoadOVSound (sfx_t *s) s->decoder->decodemore = OV_DecodeSome; s->decoder->abort = OV_CancelDecoder; - if (!OV_StartDecode(data, com_filesize, buffer)) + if (!OV_StartDecode(data, datalen, buffer)) { if (buffer->mediaaswavdata) { @@ -152,11 +103,11 @@ int OV_DecodeSome(sfx_t *s, int minlength) ovdecoderbuffer_t *dec = s->decoder->buf; int bytesread; - Con_Printf("Minlength = %03i ", minlength); +// Con_Printf("Minlength = %03i ", minlength); if (dec->mediaaswavbuflen < dec->mediaaswavpos+minlength+11050) //expand if needed. { - Con_Printf("Expand buffer\n"); +// Con_Printf("Expand buffer\n"); dec->mediaaswavbuflen += minlength+22100; dec->mediaaswavdata = BZ_Realloc(dec->mediaaswavdata, dec->mediaaswavbuflen); s->cache.data = dec->mediaaswavdata; @@ -171,7 +122,7 @@ int OV_DecodeSome(sfx_t *s, int minlength) if (minlength < sc->length) { - Con_Printf("No need for decode\n"); +// Con_Printf("No need for decode\n"); //done enough for now, don't whizz through the lot return 0; } @@ -206,7 +157,7 @@ int OV_DecodeSome(sfx_t *s, int minlength) if (minlength<=sc->length) { - Con_Printf("Reached length\n"); +// Con_Printf("Reached length\n"); return 1; } } @@ -355,6 +306,10 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf (long)p_ov_pcm_total(&buffer->vf,-1)); Con_Printf("Encoded by: %s\n\n",p_ov_comment(&buffer->vf,-1)->vendor); */ } + + buffer->start = BZ_Malloc(length); + memcpy(buffer->start, start, length); + return true; } #endif diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 6f4558442..b7cdf305c 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -869,7 +869,7 @@ qboolean Sys_InitTerminal (void) if (!AllocConsole()) return false; SetConsoleCtrlHandler (HandlerRoutine, TRUE); - SetConsoleTitle (FULLENGINENAME, " dedicated server"); + SetConsoleTitle (FULLENGINENAME " dedicated server"); hinput = GetStdHandle (STD_INPUT_HANDLE); houtput = GetStdHandle (STD_OUTPUT_HANDLE); diff --git a/engine/client/view.c b/engine/client/view.c index ba1b8f2fe..2e3d6e7c8 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1243,6 +1243,7 @@ entity_t *CL_EntityNum(int num) float CalcFov (float fov_x, float width, float height); void SCR_VRectForPlayer(vrect_t *vrect, int pnum) { + extern int glwidth, glheight; #if MAX_SPLITS > 4 #pragma warning "Please change this function to cope with the new MAX_SPLITS value" #endif @@ -1263,10 +1264,20 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) case 2: //horizontal bands case 3: - vrect->width = vid.width; - vrect->height = vid.height/cl.splitclients; - vrect->x = 0; - vrect->y = 0 + vrect->height*pnum; + if (glwidth > glheight * 2) + { //over twice as wide as high, assume duel moniter, horizontal. + vrect->width = vid.width/cl.splitclients; + vrect->height = vid.height; + vrect->x = 0 + vrect->width*pnum; + vrect->y = 0; + } + else + { + vrect->width = vid.width; + vrect->height = vid.height/cl.splitclients; + vrect->x = 0; + vrect->y = 0 + vrect->height*pnum; + } break; @@ -1625,7 +1636,6 @@ void V_Init (void) Cvar_Register (&v_kickroll, VIEWVARS); Cvar_Register (&v_kickpitch, VIEWVARS); - Cvar_Register (&v_idlescale, VIEWVARS); Cvar_Register (&v_deathtilt, VIEWVARS); Cvar_Register (&scr_autoid, VIEWVARS); diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 38648fb38..6c4ee0a2b 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -92,21 +92,6 @@ static size_t strlcat (char *dst, const char *src, size_t size) } #endif -static void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...) -{ - va_list argptr; - - va_start (argptr, fmt); -#ifdef _WIN32 - _vsnprintf (dest, size, fmt, argptr); -#else - vsnprintf (dest, size, fmt, argptr); -#endif - va_end (argptr); - - dest[size-1] = 0; -} - //a list of all the cvars //this is down to the fact that I keep defining them but forgetting to register. :/ #define TP_CVARS \ diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index d13a6a9bc..5706b1bee 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -115,6 +115,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SVCHAT //serverside npc chatting. see sv_chat.c #define Q2SERVER //server can run a q2 game dll and switches to q2 network and everything else. #define Q2CLIENT //client can connect to q2 servers + #define Q3CLIENT + #define Q3SERVER #define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect') #define FISH //sw rendering only #define ZLIB //zip/pk3 support @@ -130,6 +132,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PPL //per pixel lighting (stencil shadowing) #define DDS //a sort of image file format. + #define TCPCONNECT //a tcpconnect command, that allows the player to connect to tcp-encapsulated qw protocols. + #define PLUGINS #define CSQC_DAT //support for csqc diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 2bb722738..8158f5be5 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -176,6 +176,9 @@ void Cbuf_AddText (const char *text, int level) { int l; + if (!strcmp(text, "cmd ")) + Con_Printf("cmd text\n"); + if (level > sizeof(cmd_text)/sizeof(cmd_text[0]) || level < 0) { Con_Printf("Bad execution level\n"); @@ -2721,6 +2724,7 @@ void Cmd_WriteConfig_f(void) fprintf(f, "// FTE config file\n\n"); #ifndef SERVERONLY Key_WriteBindings (f); + CL_SaveInfo(f); #else fprintf(f, "// Dedicated Server config\n\n"); #endif @@ -2732,6 +2736,8 @@ void Cmd_WriteConfig_f(void) Alias_WriteAliases (f); Cvar_WriteVariables (f, true); fclose(f); + + FS_FlushFSHash(); } #ifndef SERVERONLY diff --git a/engine/common/common.c b/engine/common/common.c index a20097dec..72297794d 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -154,6 +154,24 @@ void Q_strncpyz(char *d, const char *s, int n) *d='\0'; } +//windows/linux have inconsistant snprintf +//this is an attempt to get them consistant and safe +//size is the total size of the buffer +void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...) +{ + va_list argptr; + + va_start (argptr, fmt); +#ifdef _WIN32 + _vsnprintf (dest, size, fmt, argptr); +#else + vsnprintf (dest, size, fmt, argptr); +#endif + va_end (argptr); + + dest[size-1] = 0; +} + #if 0 void Q_memset (void *dest, int fill, int count) @@ -2725,6 +2743,37 @@ void Info_Print (char *s) } } +void Info_WriteToFile(FILE *f, char *info, char *commandname, int cvarflags) +{ + char *command; + char *value; + cvar_t *var; + + while(*info == '\\') + { + command = info+1; + value = strchr(command, '\\'); + info = strchr(value+1, '\\'); + if (!info) //eot.. + info = value+strlen(value); + + if (*command == '*') //unsettable, so don't write it for later setting. + continue; + + var = Cvar_FindVar(command); + if (var && var->flags & cvarflags) + continue; //this is saved via a cvar. + + fwrite(commandname, strlen(commandname), 1, f); + fwrite(" ", 1, 1, f); + fwrite(command, value-command, 1, f); + fwrite(" ", 1, 1, f); + fwrite(value+1, info-(value+1), 1, f); + fwrite("\n", 1, 1, f); + } +} + + static qbyte chktbl[1024 + 4] = { 0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01, 0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a, diff --git a/engine/common/common.h b/engine/common/common.h index d26f4f3ed..d7faa6ff1 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -183,6 +183,7 @@ int wildcmp(char *wild, char *string); //1 if match #define Q_strcmp(s1, s2) strcmp((s1), (s2)) #define Q_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) +void VARGS Q_snprintfz (char *dest, size_t size, char *fmt, ...); #define Q_strncpyS(d, s, n) do{const char *____in=(s);char *____out=(d);int ____i; for (____i=0;*(____in); ____i++){if (____i == (n))break;*____out++ = *____in++;}if (____i < (n))*____out='\0';}while(0) //only use this when it should be used. If undiciided, use N #define Q_strncpyN(d, s, n) do{if (n < 0)Sys_Error("Bad length in strncpyz");Q_strncpyS((d), (s), (n));((char *)(d))[n] = '\0';}while(0) //this'll stop me doing buffer overflows. (guarenteed to overflow if you tried the wrong size.) @@ -320,11 +321,13 @@ extern qboolean standard_quake; //fixme: remove #define MAX_INFO_KEY 64 char *Info_ValueForKey (char *s, const char *key); void Info_RemoveKey (char *s, const char *key); +char *Info_KeyForNumber (char *s, int num); void Info_RemovePrefixedKeys (char *start, char prefix); void Info_RemoveNonStarKeys (char *start); void Info_SetValueForKey (char *s, const char *key, const char *value, int maxsize); void Info_SetValueForStarKey (char *s, const char *key, const char *value, int maxsize); void Info_Print (char *s); +void Info_WriteToFile(FILE *f, char *info, char *commandname, int cvarflags); unsigned int Com_BlockChecksum (void *buffer, int length); void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf); diff --git a/engine/common/fs.c b/engine/common/fs.c index 70209456a..4de78a99e 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2158,6 +2158,9 @@ void COM_InitFilesystem (void) if (!COM_CheckParm("-usehome")) *com_homedir = '\0'; + if (COM_CheckParm("-nohome")) + *com_homedir = '\0'; + if (*com_homedir) { Con_Printf("Using home directory \"%s\"\n", com_homedir); diff --git a/engine/common/net.h b/engine/common/net.h index 3cc7959ef..950e1581c 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -52,6 +52,9 @@ struct sockaddr_qstorage extern netadr_t net_local_sv_ipadr; +extern netadr_t net_local_sv_ip6adr; +extern netadr_t net_local_sv_ipxadr; +extern netadr_t net_local_sv_tcpipadr; extern netadr_t net_local_cl_ipadr; extern netadr_t net_from; // address of who sent the packet extern sizebuf_t net_message; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index e39c0b60d..db19414fa 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -21,21 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. struct sockaddr; #include "quakedef.h" -#ifdef _WIN32 - -#ifdef _MSC_VER -#define USEIPX -#endif -#include "winquake.h" -#ifdef USEIPX -#include "wsipx.h" -#endif -#ifdef IPPROTO_IPV6 -#include "ws2tcpip.h" -#endif - -#endif - #include "netinc.h" netadr_t net_local_cl_ipadr; @@ -44,6 +29,7 @@ netadr_t net_local_cl_ipxadr; netadr_t net_local_sv_ipadr; netadr_t net_local_sv_ip6adr; netadr_t net_local_sv_ipxadr; +netadr_t net_local_sv_tcpipadr; netadr_t net_from; sizebuf_t net_message; @@ -79,8 +65,11 @@ void (*pfreeaddrinfo) (struct addrinfo*); #endif #endif +void NET_GetLocalAddress (int socket, netadr_t *out); +int TCP_OpenListenSocket (int port); extern cvar_t sv_public, sv_listen; +extern cvar_t sv_tcpport; @@ -100,7 +89,7 @@ typedef struct loopback_t loopbacks[2]; //============================================================================= -void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) +int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) { switch(a->type) { @@ -110,7 +99,7 @@ void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) *(int *)&((struct sockaddr_in*)s)->sin_addr = INADDR_BROADCAST; ((struct sockaddr_in*)s)->sin_port = a->port; - break; + return sizeof(struct sockaddr_in); case NA_IP: memset (s, 0, sizeof(struct sockaddr_in)); @@ -118,7 +107,7 @@ void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) *(int *)&((struct sockaddr_in*)s)->sin_addr = *(int *)&a->ip; ((struct sockaddr_in*)s)->sin_port = a->port; - break; + return sizeof(struct sockaddr_in); #ifdef IPPROTO_IPV6 case NA_BROADCAST_IP6: memset (s, 0, sizeof(struct sockaddr_in)); @@ -129,7 +118,7 @@ void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) ((struct sockaddr_in6*)s)->sin6_addr.s6_addr[1] = 0x02; ((struct sockaddr_in6*)s)->sin6_addr.s6_addr[15] = 0x01; ((struct sockaddr_in6*)s)->sin6_port = a->port; - break; + return sizeof(struct sockaddr_in6); case NA_IPV6: memset (s, 0, sizeof(struct sockaddr_in)); @@ -137,7 +126,7 @@ void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) memcpy(&((struct sockaddr_in6*)s)->sin6_addr, a->ip6, sizeof(struct in6_addr)); ((struct sockaddr_in6*)s)->sin6_port = a->port; - break; + return sizeof(struct sockaddr_in6); #endif #ifdef USEIPX case NA_IPX: @@ -145,17 +134,18 @@ void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) memcpy(((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4); memcpy(((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6); ((struct sockaddr_ipx *)s)->sa_socket = a->port; - break; + return sizeof(struct sockaddr_ipx); case NA_BROADCAST_IPX: memset (s, 0, sizeof(struct sockaddr_ipx)); ((struct sockaddr_ipx*)s)->sa_family = AF_IPX; memset(&((struct sockaddr_ipx*)s)->sa_netnum, 0, 4); memset(&((struct sockaddr_ipx*)s)->sa_nodenum, 0xff, 6); ((struct sockaddr_ipx*)s)->sa_socket = a->port; - break; + return sizeof(struct sockaddr_ipx); #endif default: Sys_Error("Bad type - needs fixing"); + return 0; } } @@ -281,7 +271,7 @@ char *NET_AdrToString (netadr_t a) #ifdef IPPROTO_IPV6 case NA_BROADCAST_IP6: case NA_IPV6: - sprintf (s, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%i", a.ip6[0], a.ip6[1], a.ip6[2], a.ip6[3], a.ip6[4], a.ip6[5], a.ip6[6], a.ip6[7], a.ip6[8], a.ip6[9], a.ip6[10], a.ip6[11], a.ip6[12], a.ip6[13], a.ip6[14], a.ip6[15], ntohs(a.port)); + sprintf (s, "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%i", a.ip6[0], a.ip6[1], a.ip6[2], a.ip6[3], a.ip6[4], a.ip6[5], a.ip6[6], a.ip6[7], a.ip6[8], a.ip6[9], a.ip6[10], a.ip6[11], a.ip6[12], a.ip6[13], a.ip6[14], a.ip6[15], ntohs(a.port)); break; #endif #ifdef USEIPX @@ -395,29 +385,42 @@ qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr) udp6hint.ai_socktype = SOCK_DGRAM; udp6hint.ai_protocol = IPPROTO_UDP; - port = s + strlen(s); - while(port >= s) + if (*s == '[') { - if (*port == ':') - break; - port--; - } - - if (port == s) - port = NULL; - if (port) - { - len = port - s; - if (len >= sizeof(dupbase)) - len = sizeof(dupbase)-1; - strncpy(dupbase, s, len); - dupbase[len] = '\0'; - error = pgetaddrinfo(dupbase, port+1, &udp6hint, &addrinfo); + port = strstr(s, "]:"); + if (!port) + error = EAI_NONAME; + else + { + error = pgetaddrinfo(s+1. port+2, &udp6hint, &addrinfo); + } } else - error = EAI_NONAME; - if (error) //failed, try string with no port. + { + port = s + strlen(s); + while(port >= s) + { + if (*port == ':') + break; + port--; + } + + if (port == s) + port = NULL; + if (port) + { + len = port - s; + if (len >= sizeof(dupbase)) + len = sizeof(dupbase)-1; + strncpy(dupbase, s, len); + dupbase[len] = '\0'; + error = pgetaddrinfo(dupbase, port+1, &udp6hint, &addrinfo); + } + else + error = EAI_NONAME; + if (error) //failed, try string with no port. error = pgetaddrinfo(s, NULL, &udp6hint, &addrinfo); //remember, this func will return any address family that could be using the udp protocol... (ip4 or ip6) + } if (error) { return false; @@ -674,11 +677,227 @@ qboolean NET_GetPacket (netsrc_t netsrc) if (net_message.cursize == sizeof(net_message_buffer) ) { Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (net_from)); - return false; + continue; } return ret; } + +#ifdef TCPCONNECT +#ifndef SERVERONLY + if (netsrc == NS_CLIENT) + { + if (cls.sockettcp != INVALID_SOCKET) + {//client receiving only via tcp + + ret = recv(cls.sockettcp, cls.tcpinbuffer+cls.tcpinlen, sizeof(cls.tcpinbuffer)-cls.tcpinlen, 0); + if (ret == -1) + { + err = qerrno; + + if (err == EWOULDBLOCK) + ret = 0; + else + { + if (err == ECONNABORTED || err == ECONNRESET) + { + closesocket(cls.sockettcp); + cls.sockettcp = INVALID_SOCKET; + Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. + + if (cls.state != ca_disconnected) + { + if (cls.lastarbiatarypackettime+5 < Sys_DoubleTime()) //too many mvdsv + Cbuf_AddText("disconnect\nreconnect\n", RESTRICT_LOCAL); //retry connecting. + else + Con_Printf("Packet was not delivered - server might be badly configured\n"); + return false; + } + return false; + } + + + closesocket(cls.sockettcp); + cls.sockettcp = INVALID_SOCKET; + Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err)); + return false; + } + } + cls.tcpinlen += ret; + + if (cls.tcpinlen < 2) + return false; + + net_message.cursize = BigShort(*(short*)cls.tcpinbuffer); + if (net_message.cursize >= sizeof(net_message_buffer) ) + { + closesocket(cls.sockettcp); + cls.sockettcp = INVALID_SOCKET; + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (net_from)); + return false; + } + if (net_message.cursize+2 > cls.tcpinlen) + { //not enough buffered to read a packet out of it. + return false; + } + + memcpy(net_message_buffer, cls.tcpinbuffer+2, net_message.cursize); + memmove(cls.tcpinbuffer, cls.tcpinbuffer+net_message.cursize+2, cls.tcpinlen - (net_message.cursize+2)); + cls.tcpinlen -= net_message.cursize+2; + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + net_from = cls.sockettcpdest; + + return true; + } + } +#endif +#ifndef CLIENTONLY + if (netsrc == NS_SERVER) + { + float timeval = Sys_DoubleTime(); + svtcpstream_t *st; + st = svs.tcpstreams; + + while (svs.tcpstreams && svs.tcpstreams->socketnum == INVALID_SOCKET) + { + st = svs.tcpstreams; + svs.tcpstreams = svs.tcpstreams->next; + BZ_Free(st); + } + + for (st = svs.tcpstreams; st; st = st->next) + {//client receiving only via tcp + + while (st->next && st->next->socketnum == INVALID_SOCKET) + { + svtcpstream_t *temp; + temp = st->next; + st->next = st->next->next; + BZ_Free(temp); + } + +//due to the above checks about invalid sockets, the socket is always open for st below. + + if (st->timeouttime < timeval) + goto closesvstream; + + ret = recv(st->socketnum, st->inbuffer+st->inlen, sizeof(st->inbuffer)-st->inlen, 0); + if (ret == 0) + goto closesvstream; + else if (ret == -1) + { + err = qerrno; + + if (err == EWOULDBLOCK) + ret = 0; + else + { + if (err == ECONNABORTED || err == ECONNRESET) + { + Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. + } + else + Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err)); + + closesvstream: + closesocket(st->socketnum); + st->socketnum = INVALID_SOCKET; + continue; + } + } + st->inlen += ret; + + if (st->waitingforprotocolconfirmation) + { + if (st->inlen < 6) + continue; + + if (strncmp(st->inbuffer, "qizmo\n", 6)) + { + Con_Printf ("Unknown TCP client\n"); + goto closesvstream; + } + + memmove(st->inbuffer, st->inbuffer+6, st->inlen - (6)); + st->inlen -= 6; + st->waitingforprotocolconfirmation = false; + } + + if (st->inlen < 2) + continue; + + net_message.cursize = BigShort(*(short*)st->inbuffer); + if (net_message.cursize >= sizeof(net_message_buffer) ) + { + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (net_from)); + goto closesvstream; + } + if (net_message.cursize+2 > st->inlen) + { //not enough buffered to read a packet out of it. + continue; + } + + memcpy(net_message_buffer, st->inbuffer+2, net_message.cursize); + memmove(st->inbuffer, st->inbuffer+net_message.cursize+2, st->inlen - (net_message.cursize+2)); + st->inlen -= net_message.cursize+2; + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + net_from = st->remoteaddr; + + return true; + } + + +#ifdef TCPCONNECT + if (sv_tcpport.modified) + { + if (svs.sockettcp == INVALID_SOCKET && sv_tcpport.value) + { + svs.sockettcp = TCP_OpenListenSocket(sv_tcpport.value); + if (svs.sockettcp != INVALID_SOCKET) + NET_GetLocalAddress (svs.sockettcp, &net_local_sv_tcpipadr); + else + Con_Printf("Failed to open TCP port %i\n", (int)sv_tcpport.value); + } + else + { + UDP_CloseSocket(svs.sockettcp); + svs.sockettcp = INVALID_SOCKET; + } + sv_tcpport.modified = false; + } +#endif + if (svs.sockettcp != INVALID_SOCKET) + { + int newsock; + newsock = accept(svs.sockettcp, (struct sockaddr*)&from, &fromlen); + if (newsock != INVALID_SOCKET) + { + int _true = true; + setsockopt(newsock, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); + + + + st = Z_Malloc(sizeof(svtcpstream_t)); + st->waitingforprotocolconfirmation = true; + st->next = svs.tcpstreams; + svs.tcpstreams = st; + st->socketnum = newsock; + st->inlen = 0; + SockadrToNetadr(&from, &st->remoteaddr); + send(newsock, "qizmo\n", 6, 0); + + st->timeouttime = timeval + 30; + } + } + } +#endif +#endif + + return false; } @@ -706,6 +925,28 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) Sys_Error("NET_SendPacket: bad netsrc"); socket = 0; #else + +#ifdef TCPCONNECT + svtcpstream_t *st; + for (st = svs.tcpstreams; st; st = st->next) + { + if (st->socketnum == INVALID_SOCKET) + continue; + + if (NET_CompareAdr(to, st->remoteaddr)) + { + unsigned short slen = BigShort((unsigned short)length); + send(st->socketnum, (char*)&slen, sizeof(slen), 0); + send(st->socketnum, data, length, 0); + + st->timeouttime = Sys_DoubleTime() + 20; + + return; + } + } +#endif + + #ifdef USEIPX if (to.type == NA_BROADCAST_IPX || to.type == NA_IPX) socket = svs.socketipx; @@ -725,6 +966,24 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) Sys_Error("NET_SendPacket: bad netsrc"); socket = 0; #else + +#ifdef TCPCONNECT + if (cls.sockettcp != -1) + { + if (NET_CompareAdr(to, cls.sockettcpdest)) + { //this goes to the server + //so send it via tcp + unsigned short slen = BigShort((unsigned short)length); + send(cls.sockettcp, (char*)&slen, sizeof(slen), 0); + send(cls.sockettcp, data, length, 0); + + return; + } + } +#endif + + + #ifdef USEIPX if (to.type == NA_BROADCAST_IPX || to.type == NA_IPX) socket = cls.socketipx; @@ -785,6 +1044,93 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) //============================================================================= +int TCP_OpenStream (netadr_t remoteaddr) +{ + unsigned long _true = true; + int newsocket; + int temp; + struct sockaddr_qstorage qs; + + temp = NetadrToSockadr(&remoteaddr, &qs); + + if ((newsocket = socket (((struct sockaddr_in*)&qs)->sin_family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) + return INVALID_SOCKET; + + if (connect(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET) + { + closesocket(newsocket); + return INVALID_SOCKET; + } + + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); + + + return newsocket; +} + +int TCP_OpenListenSocket (int port) +{ + int newsocket; + struct sockaddr_in address; + unsigned long _true = true; + int i; +int maxport = port + 100; + + if ((newsocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) + return INVALID_SOCKET; + + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + Sys_Error ("TCP_OpenListenSocket: ioctl FIONBIO: %s", strerror(qerrno)); + + address.sin_family = AF_INET; +//ZOID -- check for interface binding option + if ((i = COM_CheckParm("-ip")) != 0 && i < com_argc) { + address.sin_addr.s_addr = inet_addr(com_argv[i+1]); + Con_TPrintf(TL_NETBINDINTERFACE, + inet_ntoa(address.sin_addr)); + } else + address.sin_addr.s_addr = INADDR_ANY; + + for(;;) + { + if (port == PORT_ANY) + address.sin_port = 0; + else + address.sin_port = htons((short)port); + + if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + { + if (!port) + { + Con_Printf("Cannot bind tcp socket\n"); + closesocket(newsocket); + return INVALID_SOCKET; + } + port++; + if (port > maxport) + { + Con_Printf("Cannot bind tcp socket\n"); + closesocket(newsocket); + return INVALID_SOCKET; + } + } + else + break; + } + + if (listen(newsocket, 1) == INVALID_SOCKET) + { + Con_Printf("Cannot listen on tcp socket\n"); + closesocket(newsocket); + return INVALID_SOCKET; + } + + return newsocket; +} + + + int UDP_OpenSocket (int port, qboolean bcast) { int newsocket; @@ -1090,12 +1436,18 @@ void NET_Init (void) cls.socketip = INVALID_SOCKET; cls.socketip6 = INVALID_SOCKET; cls.socketipx = INVALID_SOCKET; +#ifdef TCPCONNECT + cls.sockettcp = INVALID_SOCKET; +#endif #endif #ifndef CLIENTONLY svs.socketip = INVALID_SOCKET; svs.socketip6 = INVALID_SOCKET; svs.socketipx = INVALID_SOCKET; +#ifdef TCPCONNECT + svs.sockettcp = INVALID_SOCKET; +#endif #endif } #ifndef SERVERONLY @@ -1104,11 +1456,18 @@ void NET_InitClient(void) int port; int p; port = PORT_CLIENT; + p = COM_CheckParm ("-port"); if (p && p < com_argc) { port = atoi(com_argv[p+1]); } + p = COM_CheckParm ("-clport"); + if (p && p < com_argc) + { + port = atoi(com_argv[p+1]); + } + // // open the single socket to be used for all communications // @@ -1157,6 +1516,14 @@ void NET_CloseServer(void) svs.socketipx = INVALID_SOCKET; } #endif +#ifdef TCPCONNECT + if (svs.sockettcp != INVALID_SOCKET) + { + UDP_CloseSocket(svs.sockettcp ); + svs.sockettcp = INVALID_SOCKET; + sv_tcpport.modified = true; + } +#endif net_local_sv_ipadr.type = NA_LOOPBACK; net_local_sv_ip6adr.type = NA_LOOPBACK; @@ -1171,13 +1538,12 @@ void NET_InitServer(void) if (sv_listen.value) { - p = COM_CheckParm ("-svport"); + p = COM_CheckParm ("-port"); if (p && p < com_argc) { port = atoi(com_argv[p+1]); } - - p = COM_CheckParm ("-port"); + p = COM_CheckParm ("-svport"); if (p && p < com_argc) { port = atoi(com_argv[p+1]); diff --git a/engine/common/netinc.h b/engine/common/netinc.h index 9816b71b9..854f0855f 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -1,58 +1,65 @@ #ifdef _WIN32 -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EMSGSIZE WSAEMSGSIZE -#define ECONNRESET WSAECONNRESET -#define ECONNABORTED WSAECONNABORTED -#define ECONNREFUSED WSAECONNREFUSED -#define EADDRNOTAVAIL WSAEADDRNOTAVAIL -#define EAFNOSUPPORT WSAEAFNOSUPPORT + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EMSGSIZE WSAEMSGSIZE + #define ECONNRESET WSAECONNRESET + #define ECONNABORTED WSAECONNABORTED + #define ECONNREFUSED WSAECONNREFUSED + #define EADDRNOTAVAIL WSAEADDRNOTAVAIL + #define EAFNOSUPPORT WSAEAFNOSUPPORT -#ifdef IPPROTO_IPV6 -#include -#endif + #ifdef _MSC_VER + #define USEIPX + #endif + #include "winquake.h" + #ifdef USEIPX + #include "wsipx.h" + #endif + #ifdef IPPROTO_IPV6 + #include + #endif #else -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include + #include + #include + #include -#include + #include -#ifdef sun -#include -#endif + #ifdef sun + #include + #endif -#ifdef NeXT -#include -#endif + #ifdef NeXT + #include + #endif -#if defined(__MORPHOS__) && !defined(ixemul) -#define closesocket CloseSocket -#define ioctlsocket IoctlSocket -#else -#define closesocket close -#define ioctlsocket ioctl -#endif + #if defined(__MORPHOS__) && !defined(ixemul) + #define closesocket CloseSocket + #define ioctlsocket IoctlSocket + #else + #define closesocket close + #define ioctlsocket ioctl + #endif #endif #if defined(_WIN32) -#define qerrno WSAGetLastError() + #define qerrno WSAGetLastError() #elif defined(__MORPHOS__) && !defined(ixemul) -#define qerrno Errno() + #define qerrno Errno() #else -#define qerrno errno + #define qerrno errno #endif #ifndef INVALID_SOCKET -#define INVALID_SOCKET -1 + #define INVALID_SOCKET -1 #endif diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 712772d6a..6c6c7b671 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -57,6 +57,7 @@ static plugin_t *protocolclientplugin; typedef struct { char *name; Plug_Builtin_t func; + int flags; } Plug_Plugins_t; Plug_Plugins_t *plugbuiltins; int numplugbuiltins; @@ -79,6 +80,7 @@ void Plug_RegisterBuiltin(char *name, Plug_Builtin_t bi, int flags) //got an empty number. plugbuiltins[newnum].name = name; plugbuiltins[newnum].func = bi; + plugbuiltins[newnum].flags = flags; } /* @@ -111,7 +113,13 @@ int VARGS Plug_FindBuiltin(void *offset, unsigned int mask, const long *args) for (i = 0; i < numplugbuiltins; i++) if (plugbuiltins[i].name) if (!strcmp(plugbuiltins[i].name, (char *)VM_POINTER(args[0]))) + { + if (offset && plugbuiltins[i].flags & PLUG_BIF_DLLONLY) + return 0; //block it, if not native + if (!offset && plugbuiltins[i].flags & PLUG_BIF_QVMONLY) + return 0; //block it, if not native return -i; + } return 0; } @@ -258,6 +266,22 @@ int VARGS Plug_ExportToEngine(void *offset, unsigned int mask, const long *arg) return 1; } +typedef void (*funcptr_t) (); +int VARGS Plug_ExportNative(void *offset, unsigned int mask, const long *arg) +{ + funcptr_t func; + char *name = (char*)VM_POINTER(arg[0]); + arg++; + + func = *(funcptr_t*)arg; + + if (!strcmp(name, "S_LoadSound")) + S_RegisterSoundInputPlugin(func); + else + return 0; + return 1; +} + typedef struct { //Make SURE that the engine has resolved all cvar pointers into globals before this happens. plugin_t *plugin; @@ -804,6 +828,7 @@ int VARGS Plug_Con_RenameSub(void *offset, unsigned int mask, const long *arg) typedef enum{ STREAM_NONE, STREAM_SOCKET, + STREAM_OSFILE, STREAM_FILE } plugstream_e; @@ -811,7 +836,13 @@ typedef struct { plugin_t *plugin; plugstream_e type; int socket; - FILE *handle; + struct { + char filename[MAX_QPATH]; + qbyte *buffer; + int buflen; + int curlen; + int curpos; + } file; } pluginstream_t; pluginstream_t *pluginstreamarray; int pluginstreamarraylen; @@ -834,6 +865,8 @@ int Plug_NewStreamHandle(plugstream_e type) pluginstreamarray[i].plugin = currentplug; pluginstreamarray[i].type = type; pluginstreamarray[i].socket = -1; + pluginstreamarray[i].file.buffer = NULL; + *pluginstreamarray[i].file.filename = '\0'; return i; } @@ -991,6 +1024,62 @@ int VARGS Plug_Net_TCPConnect(void *offset, unsigned int mask, const long *arg) return handle; } +int VARGS Plug_FS_Open(void *offset, unsigned int mask, const long *arg) +{ + //modes: + //1: read + //2: write + + //char *name, int *handle, int mode + + //return value is length of the file. + + int handle; + int *ret; + char *data; + + if (VM_OOB(arg[1], sizeof(int))) + return -2; + ret = VM_POINTER(arg[1]); + + if (arg[2] == 1) + { + data = COM_LoadMallocFile(VM_POINTER(arg[0])); + if (!data) + return -1; + + handle = Plug_NewStreamHandle(STREAM_FILE); + pluginstreamarray[handle].file.buffer = data; + pluginstreamarray[handle].file.curpos = 0; + pluginstreamarray[handle].file.curlen = com_filesize; + pluginstreamarray[handle].file.buflen = com_filesize; + + *ret = handle; + + return com_filesize; + } + else if (arg[2] == 2) + { + data = BZ_Malloc(8192); + if (!data) + return -1; + + handle = Plug_NewStreamHandle(STREAM_FILE); + Q_strncpyz(pluginstreamarray[handle].file.filename, VM_POINTER(arg[0]), MAX_QPATH); + pluginstreamarray[handle].file.buffer = data; + pluginstreamarray[handle].file.curpos = 0; + pluginstreamarray[handle].file.curlen = 0; + pluginstreamarray[handle].file.buflen = 8192; + + *ret = handle; + + return com_filesize; + } + else + return -2; +} + + int VARGS Plug_Net_Recv(void *offset, unsigned int mask, const long *arg) { int read; @@ -1017,6 +1106,16 @@ int VARGS Plug_Net_Recv(void *offset, unsigned int mask, const long *arg) else if (read == 0) return -2; //closed by remote connection. return read; + case STREAM_FILE: + if (pluginstreamarray[handle].file.curlen - pluginstreamarray[handle].file.curpos < destlen) + { + destlen = pluginstreamarray[handle].file.curlen - pluginstreamarray[handle].file.curpos; + if (destlen < 0) + return -2; + } + memcpy(dest, pluginstreamarray[handle].file.buffer + pluginstreamarray[handle].file.curpos, destlen); + pluginstreamarray[handle].file.curpos += destlen; + return destlen; default: return -2; } @@ -1043,6 +1142,19 @@ int VARGS Plug_Net_Send(void *offset, unsigned int mask, const long *arg) else if (written == 0) return -2; //closed by remote connection. return written; + case STREAM_FILE: + if (pluginstreamarray[handle].file.buflen < pluginstreamarray[handle].file.curpos + srclen) + { + pluginstreamarray[handle].file.buflen = pluginstreamarray[handle].file.curpos + srclen+8192; + pluginstreamarray[handle].file.buffer = + BZ_Realloc(pluginstreamarray[handle].file.buffer, pluginstreamarray[handle].file.buflen); + } + memcpy(pluginstreamarray[handle].file.buffer + pluginstreamarray[handle].file.curpos, src, srclen); + pluginstreamarray[handle].file.curpos += srclen; + if (pluginstreamarray[handle].file.curpos > pluginstreamarray[handle].file.curlen) + pluginstreamarray[handle].file.curlen = pluginstreamarray[handle].file.curpos; + return -2; + default: return -2; } @@ -1089,10 +1201,20 @@ int VARGS Plug_Net_SendTo(void *offset, unsigned int mask, const long *arg) int VARGS Plug_Net_Close(void *offset, unsigned int mask, const long *arg) { int handle = VM_LONG(arg[0]); - if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug || pluginstreamarray[handle].type != STREAM_SOCKET) + if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug) return -2; - closesocket(pluginstreamarray[handle].socket); + switch(pluginstreamarray[handle].type) + { + case STREAM_SOCKET: + closesocket(pluginstreamarray[handle].socket); + break; + case STREAM_FILE: + if (*pluginstreamarray[handle].file.filename) + COM_WriteFile(pluginstreamarray[handle].file.filename, pluginstreamarray[handle].file.buffer, pluginstreamarray[handle].file.curlen); + BZ_Free(pluginstreamarray[handle].file.buffer); + break; + } pluginstreamarray[handle].plugin = NULL; @@ -1161,6 +1283,7 @@ void Plug_Init(void) Plug_RegisterBuiltin("Plug_GetEngineFunction", Plug_FindBuiltin, 0);//plugin wishes to find a builtin number. Plug_RegisterBuiltin("Plug_ExportToEngine", Plug_ExportToEngine, 0); //plugin has a call back that we might be interested in. + Plug_RegisterBuiltin("Plug_ExportNative", Plug_ExportNative, PLUG_BIF_DLLONLY); Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles. Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0); Plug_RegisterBuiltin("Sys_Milliseconds", Plug_Sys_Milliseconds, 0); @@ -1203,6 +1326,12 @@ void Plug_Init(void) Plug_RegisterBuiltin("Net_SendTo", Plug_Net_SendTo, 0); Plug_RegisterBuiltin("Net_Close", Plug_Net_Close, 0); + Plug_RegisterBuiltin("FS_Open", Plug_FS_Open, 0); + Plug_RegisterBuiltin("FS_Read", Plug_Net_Recv, 0); + Plug_RegisterBuiltin("FS_Write", Plug_Net_Send, 0); + Plug_RegisterBuiltin("FS_Close", Plug_Net_Close, 0); + + Plug_RegisterBuiltin("Media_ShowFrameRGBA_32", Plug_Media_ShowFrameRGBA_32, 0); if (plug_loaddefault.value) diff --git a/engine/common/pmove.c b/engine/common/pmove.c index a1e489f42..1bf4f6341 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -637,6 +637,7 @@ void PM_AirMove (void) else { // not on ground, so little effect on velocity PM_AirAccelerate (wishdir, wishspeed, movevars.accelerate); +// PM_Accelerate (wishdir, wishspeed, movevars.airaccelerate); // add gravity pmove.velocity[2] -= movevars.entgravity * movevars.gravity * frametime; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 45a8c3bd4..b418d5068 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -27,9 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PEXT_VIEW2 0x00000010 #endif #define PEXT_BULLETENS 0x00000020 -#ifdef AVAIL_ZLIB -// #define PEXT_ZLIBDL 0x00000040 -#endif +#define PEXT_ACCURATETIMINGS 0x00000040 //#define PEXT_LIGHTUPDATES 0x00000080 //send progs/zap.mdl in the same mannor as a nail. #define PEXT_FATNESS 0x00000100 //GL only (or servers) #define PEXT_HLBSP 0x00000200 diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 77debb7c9..21af74b2d 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -102,6 +102,7 @@ void *Sys_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall) dllEntry=(void *)GetProcAddress(hVM, "dllEntry"); if(!dllEntry) { + Con_Printf ("Sys_LoadDLL: %s lacks a dllEntry function\n",name); FreeLibrary(hVM); return NULL; } @@ -111,6 +112,7 @@ void *Sys_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall) *vmMain=(void *)GetProcAddress(hVM, "vmMain"); if(!*vmMain) { + Con_Printf ("Sys_LoadDLL: %s lacks a vmMain function\n",name); FreeLibrary(hVM); return NULL; } diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index b910f1394..238688b7d 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -107,7 +107,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /G5 /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /D "Q3CLIENT" /D "Q3SERVER" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c +# ADD CPP /nologo /G5 /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 @@ -136,7 +136,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /I "..\client" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /Gr /W3 /GX /O2 /Ob2 /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "NDEBUG" /D "_MBCS" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /D "Q3CLIENT" /D "Q3SERVER" /FR /Yu"quakedef.h" /FD /c +# ADD CPP /nologo /G6 /Gr /W3 /GX /O2 /Ob2 /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "NDEBUG" /D "_MBCS" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR /Yu"quakedef.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" @@ -164,7 +164,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client\gltod3d\sdk7\include" /I "..\client\gltod3d\D3DFrame" /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /I "..\client" /D "NQPROT" /D "_DEBUG" /D "GLQUAKE" /D "SERVERDLL" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /YX /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c -# ADD CPP /nologo /G5 /W3 /Gi /GX /ZI /Od /I "..\client" /I "../libs/dxsdk7/include" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE" /D "SWQUAKE" /D "USE_D3D" /D "Q3SERVER" /D "Q3CLIENT" /Fr /Fp".\MDebug/qwcl.pch" /Yu"quakedef.h" /FD /c +# ADD CPP /nologo /G5 /W3 /Gi /GX /ZI /Od /I "..\client" /I "../libs/dxsdk7/include" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "GLQUAKE" /D "SWQUAKE" /D "USE_D3D" /Fr /Fp".\MDebug/qwcl.pch" /Yu"quakedef.h" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" @@ -286,7 +286,8 @@ BSC32=bscmake.exe LINK32=link.exe # ADD BASE LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /pdb:".\GLDebug/dglqwcl.pdb" /debug /machine:I386 /out:"../../../fteminglqw.exe" # SUBTRACT BASE LINK32 /pdb:none -# ADD LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /out:"../../fteqwsv.exe" /libpath:"../libs/dxsdk7/lib" +# ADD LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../fteqwsv.exe" /libpath:"../libs/dxsdk7/lib" +# SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" @@ -539,8 +540,6 @@ SOURCE=..\server\svq3_game.c !ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" -# PROP Exclude_From_Build 1 - !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # PROP Exclude_From_Build 1 @@ -681,8 +680,6 @@ SOURCE=..\client\cl_cg.c !ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" -# PROP Exclude_From_Build 1 - !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # PROP Exclude_From_Build 1 @@ -798,6 +795,10 @@ SOURCE=..\client\cl_ents.c # End Source File # Begin Source File +SOURCE=..\client\cl_ignore.c +# End Source File +# Begin Source File + SOURCE=..\client\cl_input.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -1189,8 +1190,6 @@ SOURCE=..\client\clq3_parse.c !ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" -# PROP Exclude_From_Build 1 - !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # PROP Exclude_From_Build 1 diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 715fd2692..459a85bed 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -860,6 +860,7 @@ static qboolean R_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int frame1, i if (g1 == g2) //lerping within group is only done if not changing group { lerp = fg1time*g1->rate; + if (lerp < 0) lerp = 0; //hrm frame1=lerp; frame2=frame1+1; lerp-=frame1; @@ -4077,10 +4078,10 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) #ifndef SERVERONLY if (LittleLong(surf->numShaders)+externalskins) { -#if 1//ndef Q3SHADERS +#ifndef Q3SHADERS char name[1024]; - extern int gl_bumpmappingpossible; #endif + extern int gl_bumpmappingpossible; char shadname[1024]; skin = Hunk_Alloc((LittleLong(surf->numShaders)+externalskins)*((sizeof(galiasskin_t)+sizeof(galiastexnum_t)))); @@ -4971,8 +4972,8 @@ galiasinfo_t *GLMod_ParseMD5MeshModel(char *buffer) int meshnum = 0; int i; - galiasbone_t *bones; - galiasgroup_t *pose; + galiasbone_t *bones = NULL; + galiasgroup_t *pose = NULL; galiasinfo_t *inf, *root, *lastsurf; float *posedata; #ifndef SERVERONLY @@ -5092,9 +5093,9 @@ galiasinfo_t *GLMod_ParseMD5MeshModel(char *buffer) galisskeletaltransforms_t *trans; #ifndef SERVERONLY - float *stcoord; + float *stcoord = NULL; #endif - int *indexes; + int *indexes = NULL; float w; vec4_t *rawweight = NULL; @@ -5103,7 +5104,7 @@ galiasinfo_t *GLMod_ParseMD5MeshModel(char *buffer) if (!nummeshes) Sys_Error("MD5MESH: mesh section before (or without) nummeshes"); - if (!foundjoints) + if (!foundjoints || !bones || !pose) Sys_Error("MD5MESH: mesh must come after joints"); if (!lastsurf) @@ -5169,7 +5170,7 @@ galiasinfo_t *GLMod_ParseMD5MeshModel(char *buffer) buffer = COM_Parse(buffer); num = atoi(com_token); - if (num < 0 || num >= numverts) + if (num < 0 || num >= numverts || !stcoord || !indexes) Sys_Error("MD5MESH: vertex out of range"); EXPECT("("); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 6401b4d6f..1b769a71a 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -58,6 +58,7 @@ extern cvar_t gl_picmip2d; extern cvar_t r_drawdisk; extern cvar_t gl_compress; extern cvar_t gl_font, gl_conback, gl_smoothfont, gl_fontedgeclamp; +extern cvar_t gl_texturemode; extern cvar_t cl_noblink; extern cvar_t gl_savecompressedtex; @@ -560,16 +561,17 @@ void GLDraw_CharToConback (int num, qbyte *dest) typedef struct { char *name; + char *altname; int minimize, maximize; } glmode_t; glmode_t modes[] = { - {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, - {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} + {"GL_NEAREST", "n", GL_NEAREST, GL_NEAREST}, + {"GL_LINEAR", "l", GL_LINEAR, GL_LINEAR}, + {"GL_NEAREST_MIPMAP_NEAREST", "nn", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, + {"GL_LINEAR_MIPMAP_NEAREST", "ln", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, + {"GL_NEAREST_MIPMAP_LINEAR", "nl", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, + {"GL_LINEAR_MIPMAP_LINEAR", "ll", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} }; /* @@ -577,31 +579,23 @@ glmode_t modes[] = { Draw_TextureMode_f =============== */ -void GLDraw_TextureMode_f (void) +void GLDraw_TextureMode_Changed (void) { int i; gltexture_t *glt; - if (Cmd_Argc() == 1) - { - for (i=0 ; i< 6 ; i++) - if (gl_filter_min == modes[i].minimize) - { - Con_Printf ("%s\n", modes[i].name); - return; - } - Con_Printf ("current filter is unknown???\n"); - return; - } + gl_texturemode.modified = false; - for (i=0 ; i< 6 ; i++) + for (i=0 ; i< sizeof(modes)/sizeof(modes[0]) ; i++) { - if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) ) + if (!Q_strcasecmp (modes[i].name, gl_texturemode.string ) ) + break; + if (!Q_strcasecmp (modes[i].altname, gl_texturemode.string ) ) break; } if (i == 6) { - Con_Printf ("bad filter name\n"); + Con_Printf ("bad gl_texturemode name\n"); return; } @@ -1085,8 +1079,6 @@ void GLDraw_Init (void) memset(scrap_allocated, 0, sizeof(scrap_allocated)); - Cmd_AddRemCommand ("gl_texturemode", &GLDraw_TextureMode_f); - GLDraw_ReInit(); R_BackendInit(); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index c51bb0d67..1785440fe 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -2793,7 +2793,7 @@ void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum else if (version == SPRITEHL_VERSION) { if (!pspriteframe->gl_texturenum) - pspriteframe->gl_texturenum = GL_LoadTexture8Pal32 (name, width, height, (unsigned *)(pinframe + 1), (qbyte*)palette, true, true); + pspriteframe->gl_texturenum = GL_LoadTexture8Pal32 (name, width, height, (qbyte *)(pinframe + 1), (qbyte*)palette, true, true); } else { diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 5543e4cc7..af7768e0e 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -1213,6 +1213,7 @@ static void PPL_BaseChain_Flat(msurface_t *first) for (s = first; s ; s=s->texturechain) { + if (s->mesh->numvertexes < 3) continue; if (vi != s->lightmaptexturenum) { if (vi < 0) diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 1994c7aba..a2309915f 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -3170,6 +3170,7 @@ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } +qbyte *Q1BSP_LeafPVS (model_t *model, mleaf_t *leaf, qbyte *buffer); /* =============== diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 5e75e4f6d..8f2b74c18 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -130,7 +130,7 @@ needs almost the entire 256k of stack space! void GLSCR_UpdateScreen (void) { - extern cvar_t vid_conwidth, vid_conheight; + extern cvar_t vid_conwidth, vid_conheight, gl_texturemode; int uimenu; #ifdef TEXTEDITOR extern qboolean editormodal; @@ -214,6 +214,8 @@ void GLSCR_UpdateScreen (void) oldsbar = cl_sbar.value; vid.recalc_refdef = true; } + if (gl_texturemode.modified) + GLDraw_TextureMode_Changed(); GL_BeginRendering (&glx, &gly, &glwidth, &glheight); diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index ae09c06dd..674b33e7d 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -414,6 +414,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) vid.conwidth = info->width; vid.width = vid.conwidth; vid.height = vid.conheight; + vid_conwidth.modified = true; vid.numpages = 2; @@ -527,6 +528,7 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info) vid.conwidth = info->width; vid.width = vid.conwidth; vid.height = vid.conheight; + vid_conwidth.modified = true; vid.numpages = 2; @@ -1275,11 +1277,7 @@ LONG WINAPI GLMainWndProc ( { WindowRect.right = ((short*)&lParam)[0] - WindowRect.left; WindowRect.bottom = ((short*)&lParam)[1] - WindowRect.top; - - if (modestate != MS_FULLDIB) //fullscreen doesn't have the RIGHT to respond to this. Apply to the Court of M$ if you want this changed... - { - vid_conwidth.modified = true; //make it reapplied - } + vid_conwidth.modified = true; //make it reapplied } break; diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 12aa3be47..efea1ce38 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -249,8 +249,7 @@ void R_DrawSkyChain (msurface_t *s) // used when gl_texsort is on GL_Bind(solidskytexture); - speedscale = cl.gametime; - speedscale += realtime - cl.gametimemark; + speedscale = cl.servertime; speedscale*=8; speedscale -= (int)speedscale & ~127 ; @@ -259,8 +258,7 @@ void R_DrawSkyChain (msurface_t *s) qglEnable (GL_BLEND); GL_Bind (alphaskytexture); - speedscale = cl.gametime; - speedscale += realtime - cl.gametimemark; + speedscale = cl.servertime; speedscale*=16; speedscale -= (int)speedscale & ~127 ; diff --git a/engine/http/iweb.h b/engine/http/iweb.h index 3eecfec3c..3f74c4385 100644 --- a/engine/http/iweb.h +++ b/engine/http/iweb.h @@ -69,7 +69,7 @@ char **com_argv; struct sockaddr_in; struct sockaddr; struct sockaddr_qstorage; -void NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s); +int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s); qboolean SV_AllowDownload (char *name); diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index b4d212c2d..3b7e296ce 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -394,7 +394,7 @@ reeval: #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif - if (ed->readonly) + if (!ed || ed->readonly) { pr_xstatement = st-pr_statements; PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 2d7f74a5e..b6fa1d254 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -1950,8 +1950,6 @@ int QCC_PR_CheakCompConst(void) strncpy(pr_token, pr_file_p, end-pr_file_p); pr_token[end-pr_file_p]='\0'; - if (!strcmp(pr_token, "varkeyword")) - printf("varkeyword!!!\n"); // printf("%s\n", pr_token); c = pHash_Get(&compconstantstable, pr_token); diff --git a/engine/server/q3g_public.h b/engine/server/q3g_public.h index 8ab35d559..97d585ddd 100644 --- a/engine/server/q3g_public.h +++ b/engine/server/q3g_public.h @@ -93,7 +93,7 @@ typedef struct { // the server looks at a sharedEntity, which is the start of the game's gentity_t structure typedef struct { q3entityState_t s; // communicated by server to clients - q3entityShared_t r; // shared by both the server system and game + q3entityShared_t r; // shared by both the server system and game - I *really* don't understand this, it looks like a bug. } q3sharedEntity_t; diff --git a/engine/server/server.h b/engine/server/server.h index 7e25ba479..a5dc61ab4 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -664,6 +664,18 @@ typedef struct levelcache_s { gametype_e gametype; } levelcache_t; +#ifdef TCPCONNECT +typedef struct svtcpstream_s { + int socketnum; + int inlen; + qboolean waitingforprotocolconfirmation; + char inbuffer[1500]; + float timeouttime; + netadr_t remoteaddr; + struct svtcpstream_s *next; +} svtcpstream_t; +#endif + typedef struct { gametype_e gametype; @@ -674,6 +686,11 @@ typedef struct int socketip6; int socketipx; +#ifdef TCPCONNECT + int sockettcp; + svtcpstream_t *tcpstreams; +#endif + client_t clients[MAX_CLIENTS]; int serverflags; // episode completion information @@ -919,6 +936,8 @@ qboolean SVQ3_InitGame(void); qboolean SVQ3_ConsoleCommand(void); void SVQ3_HandleClient(void); void SVQ3_DirectConnect(void); +void SVQ3_DropClient(client_t *cl); +int SVQ3_AddBot(void); void SVQ3_RunFrame(void); void SVQ3_SendMessage(client_t *client); qboolean SVQ3_Command(void); @@ -942,6 +961,7 @@ void SV_SetMoveVars(void); // // sv_send.c // +qboolean SV_ChallengePasses(int challenge); void SV_QCStat(int type, char *name, int statnum); void SV_ClearQCStats(void); diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 7ce68ae25..078030799 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -584,7 +584,7 @@ void SV_Map_f (void) SV_SpawnServer (level, startspot, false, cinematic); } - SV_BroadcastCommand ("reconnect\n"); + SV_BroadcastCommand ("cmd new\n"); if (!issamelevel) { @@ -944,7 +944,7 @@ void SV_Status_f (void) avg = 1000*svs.stats.latched_active / STATFRAMES; pak = (float)svs.stats.latched_packets/ STATFRAMES; - if (net_local_sv_ipadr.type != NA_LOOPBACK) + if (svs.socketip != INVALID_SOCKET && net_local_sv_ipadr.type != NA_LOOPBACK) { extern cvar_t pr_imitatemvdsv; if (pr_imitatemvdsv.value) @@ -952,6 +952,13 @@ void SV_Status_f (void) else Con_Printf ("ip address : %s\n",NET_AdrToString (net_local_sv_ipadr)); } + if (svs.socketip6 != INVALID_SOCKET && net_local_sv_ip6adr.type != NA_LOOPBACK) + Con_Printf ("ipv6 address : %s\n",NET_AdrToString (net_local_sv_ip6adr)); + if (svs.socketipx != INVALID_SOCKET && net_local_sv_ipxadr.type != NA_LOOPBACK) + Con_Printf ("ipx address : %s\n",NET_AdrToString (net_local_sv_ipxadr)); + if (svs.sockettcp != INVALID_SOCKET && net_local_sv_tcpipadr.type != NA_LOOPBACK) + Con_Printf ("tcp address : %s\n",NET_AdrToString (net_local_sv_tcpipadr)); + Con_Printf ("cpu utilization : %3i%%\n",(int)cpu); Con_Printf ("avg response time: %i ms\n",(int)avg); Con_Printf ("packets/frame : %5.2f\n", pak); //not relevent as a limit. @@ -1273,39 +1280,14 @@ void SV_Localinfo_f (void) Con_DPrintf("Localinfo %s changed (%s -> %s)\n", Cmd_Argv(1), old, Cmd_Argv(2)); } -void SV_SaveInfo(FILE *f, char *info, char *commandname) -{ - char *command; - char *value; - - while(*info == '\\') - { - command = info+1; - value = strchr(command, '\\'); - info = strchr(value+1, '\\'); - if (!info) //eot.. - info = value+strlen(value); - - if (*command == '*') //unsettable, so don't write it for later setting. - continue; - - fwrite(commandname, strlen(commandname), 1, f); - fwrite(" ", 1, 1, f); - fwrite(command, value-command, 1, f); - fwrite(" ", 1, 1, f); - fwrite(value+1, info-(value+1), 1, f); - fwrite("\n", 1, 1, f); - } -} - void SV_SaveInfos(FILE *f) { fwrite("\n", 1, 1, f); fwrite("serverinfo * \"\"\n", 16, 1, f); - SV_SaveInfo(f, svs.info, "serverinfo"); + Info_WriteToFile(f, svs.info, "serverinfo", CVAR_SERVERINFO); fwrite("\n", 1, 1, f); fwrite("localinfo * \"\"\n", 15, 1, f); - SV_SaveInfo(f, localinfo, "localinfo"); + Info_WriteToFile(f, localinfo, "localinfo", 0); } /* diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 899b1b90c..4a129c5cd 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -123,6 +123,7 @@ cvar_t sv_masterport = {"sv_masterport", "0"}; cvar_t sv_voicechat = {"sv_voicechat", "0"}; //still development. cvar_t sv_gamespeed = {"sv_gamespeed", "1"}; cvar_t sv_csqcdebug = {"sv_csqcdebug", "0"}; +cvar_t sv_tcpport = {"sv_tcpport", "0"}; cvar_t pausable = {"pausable", "1"}; @@ -3007,6 +3008,7 @@ void SV_InitLocal (void) Cvar_Register (&sv_public, cvargroup_servercontrol); Cvar_Register (&sv_listen, cvargroup_servercontrol); + Cvar_Register (&sv_tcpport, cvargroup_servercontrol); Cvar_Register (&sv_reportheartbeats, cvargroup_servercontrol); #ifndef SERVERONLY @@ -3085,6 +3087,7 @@ void SV_InitLocal (void) #ifdef PEXT_BULLETENS svs.fteprotocolextensions |= PEXT_BULLETENS; #endif + svs.fteprotocolextensions |= PEXT_ACCURATETIMINGS; #ifdef PEXT_ZLIBDL svs.fteprotocolextensions |= PEXT_ZLIBDL; #endif diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 1463642f9..e25fa4c57 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -995,13 +995,23 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) // every now and then, send an update so that extrapolation // on client side doesn't stray too far off if (ISQWCLIENT(client)) - if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.physicstime - client->nextservertimeupdate > 0) { - MSG_WriteByte (msg, svc_updatestatlong); - MSG_WriteByte (msg, STAT_TIME); - MSG_WriteLong (msg, (int)(sv.physicstime * 1000)); + if (client->fteprotocolextensions & PEXT_ACCURATETIMINGS && sv.physicstime - client->nextservertimeupdate > 0) + { //the fte pext causes the server to send out accurate timings, allowing for perfect interpolation. + MSG_WriteByte (msg, svc_updatestatlong); + MSG_WriteByte (msg, STAT_TIME); + MSG_WriteLong (msg, (int)(sv.physicstime * 1000)); - client->nextservertimeupdate = sv.physicstime;//+10; + client->nextservertimeupdate = sv.physicstime;//+10; + } + else if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.physicstime - client->nextservertimeupdate > 0) + { //the zquake ext causes the server to send out peridoic timings, allowing for moderatly accurate game time. + MSG_WriteByte (msg, svc_updatestatlong); + MSG_WriteByte (msg, STAT_TIME); + MSG_WriteLong (msg, (int)(sv.physicstime * 1000)); + + client->nextservertimeupdate = sv.physicstime+10; + } } #ifdef NQPROT diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 9a3a9fa02..3d5248a39 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -132,7 +132,7 @@ void SV_New_f (void) // host_client->sendinfo = true; gamedir = Info_ValueForKey (svs.info, "*gamedir"); - if (!gamedir[0]) + if (!gamedir[0] || !strcmp(gamedir, "fte")) gamedir = "qw"; //NOTE: This doesn't go through ClientReliableWrite since it's before the user