diff --git a/engine/client/cd_win.c b/engine/client/cd_win.c index 4b525b9d0..50e5a53bc 100644 --- a/engine/client/cd_win.c +++ b/engine/client/cd_win.c @@ -68,8 +68,9 @@ static int CDAudio_GetAudioDiskInfo(void) DWORD dwReturn; MCI_STATUS_PARMS mciStatusParms; - cdValid = false; + if (!initialized) + return -1; mciStatusParms.dwItem = MCI_STATUS_READY; dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms); @@ -133,6 +134,9 @@ void CDAudio_Play(int track, qboolean looping) } } + if (!initialized) + return; + track = remap[track]; if (track < 1 || track > maxTrack) @@ -278,6 +282,26 @@ static void CD_f (void) command = Cmd_Argv (1); + + if (Q_strcasecmp(command, "play") == 0) + { + CDAudio_Play((qbyte)Q_atoi(Cmd_Argv (2)), false); + return; + } + + if (Q_strcasecmp(command, "loop") == 0) + { + CDAudio_Play((qbyte)Q_atoi(Cmd_Argv (2)), true); + return; + } + + + if (!initialized) + { + Con_Printf("No cd drive detected\n"); + return; + } + if (Q_strcasecmp(command, "on") == 0) { enabled = true; @@ -324,18 +348,6 @@ static void CD_f (void) return; } - if (Q_strcasecmp(command, "play") == 0) - { - CDAudio_Play((qbyte)Q_atoi(Cmd_Argv (2)), false); - return; - } - - if (Q_strcasecmp(command, "loop") == 0) - { - CDAudio_Play((qbyte)Q_atoi(Cmd_Argv (2)), true); - return; - } - if (!cdValid) { CDAudio_GetAudioDiskInfo(); @@ -446,6 +458,8 @@ int CDAudio_Init(void) MCI_SET_PARMS mciSetParms; int n; + Cmd_AddCommand ("cd", CD_f); + #if 0 // QW if (cls.state == ca_dedicated) return -1; @@ -484,8 +498,6 @@ int CDAudio_Init(void) enabled = false; } - Cmd_AddCommand ("cd", CD_f); - Cvar_Hook(&bgmvolume, BGMVolume_Callback); // Con_Printf("CD Audio Initialized\n"); diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 31199f6e3..e46595455 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -893,7 +893,7 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( cl_latestframenum = MSG_ReadLong(); if (nq_dp_protocol >=7) - /*cl.servermovesequence =*/ MSG_ReadLong(); + cl.ackedinputsequence = MSG_ReadLong(); pack = &cl.frames[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities; pack->servertime = cl.gametime; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 300e1ee59..b5345c2da 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -739,7 +739,7 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) MSG_WriteByte (buf, clc_move); if (nq_dp_protocol>=7) - MSG_WriteLong(buf, 0); + MSG_WriteLong(buf, cls.netchan.outgoing_sequence); MSG_WriteFloat (buf, cl.gametime); // so server can get ping times @@ -1254,13 +1254,13 @@ void CL_SendCmd (double frametime) msecs -= msecstouse; i = cls.netchan.outgoing_sequence & UPDATE_MASK; - cmd = &cl.frames[i].cmd[plnum]; - *cmd = independantphysics[plnum]; + cmd = &cl.frames[i].cmd[0]; + *cmd = independantphysics[0]; cl.frames[i].senttime = realtime; cl.frames[i].receivedtime = 0; // nq doesn't allow us to find our own packetloss - memset(&independantphysics[plnum], 0, sizeof(independantphysics[plnum])); CLNQ_SendCmd (); + memset(&independantphysics[0], 0, sizeof(independantphysics[plnum])); return; } #endif @@ -1609,6 +1609,22 @@ void CL_RegisterSplitCommands(void) } } +void CL_SendCvar_f (void) +{ + cvar_t *var; + char *val; + char *name = Cmd_Argv(1); + + var = Cvar_FindVar(name); + if (!var) + val = ""; + else if (var->flags & CVAR_NOUNSAFEEXPAND) + val = ""; + else + val = var->string; + CL_SendClientCommand(true, "sentcvar %s \"%s\"", name, val); +} + /* ============ CL_InitInput @@ -1622,6 +1638,7 @@ void CL_InitInput (void) Cmd_AddCommand("rotate", IN_Rotate_f); Cmd_AddCommand("in_restart", IN_Restart); + Cmd_AddCommand("sendcvar", CL_SendCvar_f); Cvar_Register (&cl_nodelta, inputnetworkcvargroup); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 606702577..14224dbbe 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1412,6 +1412,11 @@ void CL_CheckServerInfo(void) movevars.airstep = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_airstep")) != 0); movevars.walljump = (Q_atof(Info_ValueForKey(cl.serverinfo, "pm_walljump"))); movevars.ktjump = Q_atof(Info_ValueForKey(cl.serverinfo, "pm_ktjump")); + s = Info_ValueForKey(cl.serverinfo, "pm_stepheight"); + if (*s) + movevars.stepheight = Q_atof(s); + else + movevars.stepheight = PM_DEFAULTSTEPHEIGHT; // Initialize cl.maxpitch & cl.minpitch s = (cls.z_ext & Z_EXT_PITCHLIMITS) ? Info_ValueForKey (cl.serverinfo, "maxpitch") : ""; @@ -3345,6 +3350,8 @@ void Host_Init (quakeparms_t *parms) Memory_Init (parms->membase, parms->memsize); + Sys_Init(); + COM_ParsePlusSets(); Cbuf_Init (); Cmd_Init (); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 964a278c4..ec88c7e5c 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -29,6 +29,9 @@ void CL_SetStat (int pnum, int stat, int value); int nq_dp_protocol; int msgflags; +int cl_dp_csqc_progssize; +int cl_dp_csqc_progscrc; + char *svc_strings[] = { @@ -181,7 +184,7 @@ char *svc_nqstrings[] = "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", - "dpsvc_cgame", //50 + "dpsvc_downloaddata", //50 "dpsvc_updatestatubyte", "dpsvc_effect", "dpsvc_effect2", @@ -399,10 +402,12 @@ void CL_FinishDownload(char *filename, char *tempname) { if (strncmp(tempname,"skins/",6)) { + FS_CreatePath(filename, FS_GAME); FS_Rename(tempname, filename, FS_GAME); } else { + FS_CreatePath(filename+6, FS_SKINS); FS_Rename(tempname+6, filename+6, FS_SKINS); } } @@ -448,6 +453,21 @@ void MapDownload(char *name, qboolean gotornot) CL_EnqueDownload(filename, false, false); } */ + +qboolean CL_CheckFile(char *filename) +{ + if (strstr (filename, "..")) + { + Con_TPrintf (TL_NORELATIVEPATHS); + return true; + } + + if (COM_FCheckExists (filename)) + { // it exists, no need to download + return true; + } + return false; +} /* =============== CL_CheckOrEnqueDownloadFile @@ -456,20 +476,14 @@ Returns true if the file exists, otherwise it attempts to start a download from the server. =============== */ + qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname) { //returns false if we don't have the file yet. if (!localname) localname = filename; - if (strstr (localname, "..")) - { - Con_TPrintf (TL_NORELATIVEPATHS); - return true; - } - if (COM_FCheckExists (localname)) - { // it exists, no need to download + if (CL_CheckFile(localname)) return true; - } //ZOID - can't download when recording if (cls.demorecording) @@ -624,6 +638,32 @@ int CL_LoadModels(int stage) pmove.numphysent = 0; +#ifdef PEXT_CSQC + if (atstage()) + { + if (cls.protocol == CP_NETQUAKE) + { + char *s; + s = Info_ValueForKey(cl.serverinfo, "*csprogs"); + if (*s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. + { + extern cvar_t allow_download_csprogs; + unsigned int chksum = strtoul(s, NULL, 0); + if (allow_download_csprogs.value) + { + char *str = va("csprogsvers/%x.dat", chksum); + CL_CheckOrEnqueDownloadFile("csprogs.dat", str); + } + else + { + Con_Printf("Not downloading csprogs.dat due to allow_download_csprogs\n"); + } + } + } + endstage(); + } +#endif + #ifdef PEXT_CSQC if (atstage()) { @@ -752,6 +792,7 @@ Sound_NextDownload */ void Sound_NextDownload (void) { + char mangled[512]; char *s; int i; @@ -785,7 +826,19 @@ void Sound_NextDownload (void) s = cl.sound_name[i]; if (*s == '*') continue; - CL_CheckOrEnqueDownloadFile(va("sound/%s",s), NULL); + s = va("sound/%s",s); + + if (CL_CheckFile(s)) + continue; //we have it already + + //the things I do for nexuiz... *sigh* + COM_StripExtension(s, mangled, sizeof(mangled)); + COM_DefaultExtension(mangled, ".ogg", sizeof(mangled)); + if (CL_CheckFile(mangled)) + continue; + + //download the one the server said. + CL_CheckOrEnqueDownloadFile(s, NULL); } for (i=1 ; i sizeof(buffer)) + chunk = sizeof(buffer); + VFS_WRITE(cls.downloadqw, buffer, chunk); + } + + downloadstarttime = Sys_DoubleTime(); +} + +void CLDP_ParseDownloadFinished(char *s) +{ + unsigned short runningcrc; + char buffer[8192]; + int size, pos, chunk; + if (!cls.downloadqw) + return; + + Cmd_TokenizeString(s+1, false, false); + + VFS_CLOSE (cls.downloadqw); + + cls.downloadqw = FS_OpenVFS (cls.downloadtempname, "rb", FS_GAME); + if (cls.downloadqw) + { + size = VFS_GETLEN(cls.downloadqw); + QCRC_Init(&runningcrc); + for (pos = 0, chunk = 1; chunk; pos += chunk) + { + chunk = size - pos; + if (chunk > sizeof(buffer)) + chunk = sizeof(buffer); + VFS_READ(cls.downloadqw, buffer, chunk); + QCRC_AddBlock(&runningcrc, buffer, chunk); + } + VFS_CLOSE (cls.downloadqw); + } + + Cmd_TokenizeString(s+1, false, false); + if (size != atoi(Cmd_Argv(1))) + { + Con_Printf("Download failed: wrong file size\n"); + CL_DownloadFailed(cls.downloadname); + return; + } + if (runningcrc != atoi(Cmd_Argv(2))) + { + Con_Printf("Download failed: wrong crc\n"); + CL_DownloadFailed(cls.downloadname); + return; + } + + CL_FinishDownload(cls.downloadname, cls.downloadtempname); + *cls.downloadname = '\0'; + cls.downloadqw = NULL; + cls.downloadpercent = 0; + + Con_Printf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime)); + + // get another file if needed + + CL_RequestNextDownload (); +} + static vfsfile_t *upload_file; static qbyte *upload_data; static int upload_pos; @@ -1718,6 +1884,8 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. Stats_NewMap(); Cvar_ForceCallback(&r_particlesdesc); + Info_SetValueForStarKey(cl.serverinfo, "*csprogs", va("%i", cl_dp_csqc_progscrc), sizeof(cl.serverinfo)); + protover = MSG_ReadLong (); sizeofcoord = 2; @@ -1875,7 +2043,8 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); switch (cls.signon) { case 1: - CL_SendClientCommand(true, "prespawn"); + cl.sendprespawn = true; +// CL_SendClientCommand(true, "prespawn"); break; case 2: @@ -1891,6 +2060,15 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); CL_SendClientCommand(true, "playermodel %s", model.string); CL_SendClientCommand(true, "playerskin %s", skin.string); + + { + char *s; + s = Info_ValueForKey(cl.serverinfo, "*csprogs"); + if (*s) + CSQC_Init(atoi(s)); + else + CSQC_Shutdown(); + } } break; @@ -4211,10 +4389,12 @@ void CL_ParseServerMessage (void) case svc_packetentities: CL_ParsePacketEntities (false); + cl.ackedinputsequence = cl.validsequence; break; case svc_deltapacketentities: CL_ParsePacketEntities (true); + cl.ackedinputsequence = cl.validsequence; break; case svc_maxspeed : @@ -4673,7 +4853,25 @@ void CLNQ_ParseServerMessage (void) else { Con_DPrintf ("stufftext: %s\n", s); - Cbuf_AddText (s, RESTRICT_SERVER); //no cheating here... + if (!strncmp(s, "cl_serverextension_download ", 14)) + { + } + else if (!strncmp(s, "\ncl_downloadbegin ", 17)) + CLDP_ParseDownloadBegin(s); + else if (!strncmp(s, "\ncl_downloadfinished ", 17)) + CLDP_ParseDownloadFinished(s); + else if (!strncmp(s, "csqc_progname ", 14)) + { +// Info_SetValueForStarKey(cl.serverinfo, "*cspname", s+14, sizeof(cl.serverinfo)); + } + else if (!strncmp(s, "csqc_progsize ", 14)) + cl_dp_csqc_progssize = atoi(s+14); + else if (!strncmp(s, "csqc_progcrc ", 13)) + cl_dp_csqc_progscrc = atoi(s+13); + else + { + Cbuf_AddText (s, RESTRICT_SERVER); //no cheating here... + } } break; @@ -4890,7 +5088,7 @@ void CLNQ_ParseServerMessage (void) CL_ParseEffect(true); break; - case 57://svc_entities + case svcdp_entities: if (cls.signon == 4 - 1) { // first update is the final signon stage cls.signon = 4; @@ -4899,7 +5097,16 @@ void CLNQ_ParseServerMessage (void) //well, it's really any protocol, but we're only going to support version 5. CLNQ_ParseDarkPlaces5Entities(); break; + + case svcdp_csqcentities: + CSQC_ParseEntities(); + break; + + case svcdp_downloaddata: + CLDP_ParseDownloadData(); + break; } + } } #endif diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index fd6d5bb85..8614095c3 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -474,7 +474,7 @@ void CL_CalcCrouch (int pnum) if (cl.onground[pnum] && cl.simorg[pnum][2] - oldz[pnum] > 0) { - if (cl.simorg[pnum][2] - oldz[pnum] > 20) + if (cl.simorg[pnum][2] - oldz[pnum] > movevars.stepheight+2) { // if on steep stairs, increase speed if (crouchspeed[pnum] < 160) @@ -717,12 +717,12 @@ void CL_PredictMovePNum (int pnum) return; } - if (!cl.validsequence) + if (!cl.ackedinputsequence) { return; } - if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1) + if (cls.netchan.outgoing_sequence - cl.ackedinputsequence >= UPDATE_BACKUP-1) { //lagging like poo. if (!cl.intermission) //keep the angles working though. VectorCopy (cl.viewangles[pnum], cl.simangles[pnum]); @@ -730,7 +730,7 @@ void CL_PredictMovePNum (int pnum) } // this is the last frame received from the server - from = &cl.frames[cl.validsequence & UPDATE_MASK]; + from = &cl.frames[cl.ackedinputsequence & UPDATE_MASK]; if (!cl.intermission) { @@ -793,7 +793,7 @@ fixedorg: VectorCopy (vel, cl.simvel[pnum]); VectorCopy (org, cl.simorg[pnum]); - to = &cl.frames[cl.validsequence & UPDATE_MASK]; + to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK]; @@ -805,13 +805,13 @@ fixedorg: oldphysent = pmove.numphysent; CL_SetSolidPlayers (cl.playernum[pnum]); - to = &cl.frames[cl.validsequence & UPDATE_MASK]; + to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK]; if (Cam_TrackNum(pnum)>=0 && !cl_nolerp.value && cls.demoplayback != DPB_MVD) { float f; - to = &cl.frames[cl.validsequence & UPDATE_MASK]; + to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK]; from = &cl.frames[cl.oldvalidsequence & UPDATE_MASK]; //figure out the lerp factor @@ -838,10 +838,10 @@ fixedorg: } else { - for (i=1 ; iplayerstate->pm_type = PM_FLY; CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index c0bac10c7..58df2fe64 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -2301,6 +2301,7 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud) { Sbar_IntermissionOverlay (); M_Draw (uimenu); + MP_Draw(); } else if (cl.intermission == 2 && key_dest == key_game) { @@ -2349,6 +2350,7 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud) Editor_Draw(); #endif M_Draw (uimenu); + MP_Draw(); SCR_DrawConsole (false); } diff --git a/engine/client/client.h b/engine/client/client.h index 23409429a..9035147c6 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -329,7 +329,7 @@ typedef struct int tcpinlen; #endif - enum {DL_NONE, DL_QW, DL_QWCHUNKS, DL_Q3, DL_QWPENDING, DL_HTTP, DL_FTP} downloadmethod; + enum {DL_NONE, DL_QW, DL_QWCHUNKS, DL_Q3, DL_DARKPLACES, DL_QWPENDING, DL_HTTP, DL_FTP} downloadmethod; vfsfile_t *downloadqw; // file transfer from server char downloadtempname[MAX_OSPATH]; char downloadname[MAX_OSPATH]; @@ -429,6 +429,7 @@ typedef struct int parsecount; // server message counter int oldparsecount; int oldvalidsequence; + int ackedinputsequence; //in quakeworld/q2 this is always equal to validsequence. dp can differ. int validsequence; // this is the sequence number of the last good // packetentity_t we got. If this is 0, we can't // render a frame yet diff --git a/engine/client/menu.c b/engine/client/menu.c index 08827aacf..f4050d681 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -1065,7 +1065,7 @@ void M_Draw (int uimenu) #endif #ifdef MENU_DAT case m_menu_dat: - MP_Draw(); +// MP_Draw(); return; #endif } diff --git a/engine/client/net_master.c b/engine/client/net_master.c index a2ac5c097..106bf1bd3 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -1246,7 +1246,7 @@ void MasterInfo_Begin(void) Master_AddMaster("62.112.145.129:27000", MT_MASTERQW, "Ocrana master server."); // Master_AddMaster("master.edome.net", MT_MASTERQW, "edome master server."); - Master_AddMaster("qwmaster.barrysworld.com", MT_MASTERQW, "barrysworld master server."); + //down Master_AddMaster("qwmaster.barrysworld.com", MT_MASTERQW, "barrysworld master server."); Master_AddMaster("qwmaster.ocrana.de:27000", MT_MASTERQW, "Ocrana2 master server."); Master_AddMaster("213.221.174.165:27000", MT_MASTERQW, "unknown1 master server."); Master_AddMaster("195.74.0.8", MT_MASTERQW, "unknown2 master server."); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index f96cf504f..bb3751c64 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -86,6 +86,7 @@ extern sfx_t *cl_sfx_r_exp3; \ globalfloat(player_localentnum, "player_localentnum"); /*float the entity number of the local player*/ \ globalfloat(intermission, "intermission"); /*float the entity number of the local player*/ \ + globalvector(view_angles, "view_angles"); \ \ globalvector(pmove_org, "pmove_org"); \ globalvector(pmove_vel, "pmove_vel"); \ @@ -2699,11 +2700,11 @@ static void PF_shaderforname (progfuncs_t *prinst, struct globalvars_s *pr_globa shader_t *shad; shad = R_RegisterSkin(str); if (shad) - G_INT(OFS_RETURN) = shad-r_shaders + 1; + G_FLOAT(OFS_RETURN) = shad-r_shaders + 1; else - G_INT(OFS_RETURN) = 0; + G_FLOAT(OFS_RETURN) = 0; #else - G_INT(OFS_RETURN) = 0; + G_FLOAT(OFS_RETURN) = 0; #endif } @@ -2747,7 +2748,7 @@ realcheck: // the midpoint must be within 16 of the bottom start[0] = stop[0] = (mins[0] + maxs[0])*0.5; start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*pm_stepheight; + stop[2] = start[2] - 2*movevars.stepheight; trace = CS_Move (start, vec3_origin, vec3_origin, stop, true, ent); if (trace.fraction == 1.0) @@ -2768,7 +2769,7 @@ realcheck: if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > pm_stepheight) + if (trace.fraction == 1.0 || mid - trace.endpos[2] > movevars.stepheight) return false; } @@ -2846,9 +2847,9 @@ qboolean CS_movestep (csqcedict_t *ent, vec3_t move, qboolean relink, qboolean n } // push down from a step height above the wished position - neworg[2] += pm_stepheight; + neworg[2] += movevars.stepheight; VectorCopy (neworg, end); - end[2] -= pm_stepheight*2; + end[2] -= movevars.stepheight*2; trace = CS_Move (neworg, ent->v->mins, ent->v->maxs, end, false, ent); if (set_trace) @@ -2859,7 +2860,7 @@ qboolean CS_movestep (csqcedict_t *ent, vec3_t move, qboolean relink, qboolean n if (trace.startsolid) { - neworg[2] -= pm_stepheight; + neworg[2] -= movevars.stepheight; trace = CS_Move (neworg, ent->v->mins, ent->v->maxs, end, false, ent); if (set_trace) cs_settracevars(&trace); @@ -3211,7 +3212,7 @@ PF_str2chr, // #222 float(string str, float index) str2chr (FTE_STRINGS) PF_chr2str, // #223 string(float chr, ...) chr2str (FTE_STRINGS) PF_strconv, // #224 string(float ccase, float redalpha, float redchars, string str, ...) strconv (FTE_STRINGS) -PF_strpad, // #225 string(float ccase, float redalpha, float redchars, string str, ...) strconv (FTE_STRINGS) +PF_strpad, // #225 string strpad(float pad, string str1, ...) strpad (FTE_STRINGS) PF_infoadd, // #226 string(string old, string key, string value) infoadd PF_infoget, // #227 string(string info, string key) infoget PF_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) @@ -3525,14 +3526,32 @@ qbyte *CSQC_PRLoadFile (char *path, void *buffer, int bufsize) file = COM_LoadStackFile(newname, buffer, bufsize); if (file) - if (Com_BlockChecksum(file, com_filesize) == csqcchecksum) //and the user wasn't trying to be cunning. - return file; + { + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) == csqcchecksum) + return file; + } + else + { + if (Com_BlockChecksum(file, com_filesize) == csqcchecksum) //and the user wasn't trying to be cunning. + return file; + } + } file = COM_LoadStackFile(path, buffer, bufsize); if (file && !cls.demoplayback) //allow them to use csprogs.dat if playing a demo, and don't care about the checksum { - if (Com_BlockChecksum(file, com_filesize) != csqcchecksum) - return NULL; //not valid + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) != csqcchecksum) + return NULL; + } + else + { + if (Com_BlockChecksum(file, com_filesize) != csqcchecksum) + return NULL; //not valid + } //back it up COM_WriteFile(newname, file, com_filesize); @@ -3556,15 +3575,35 @@ int CSQC_PRFileSize (char *path) file = COM_LoadTempFile (newname); if (file) - if (Com_BlockChecksum(file, com_filesize) == csqcchecksum) //and the user wasn't trying to be cunning. - return com_filesize+1; + { + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) == csqcchecksum) + return com_filesize+1; + } + else + { + if (Com_BlockChecksum(file, com_filesize) == csqcchecksum) //and the user wasn't trying to be cunning. + return com_filesize+1; + } + } file = COM_LoadTempFile(path); if (file && !cls.demoplayback) //allow them to use csprogs.dat if playing a demo, and don't care about the checksum { - if (Com_BlockChecksum(file, com_filesize) != csqcchecksum) - return -1; //not valid + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) != csqcchecksum) + return -1; //not valid + } + else + { + if (Com_BlockChecksum(file, com_filesize) != csqcchecksum) + return -1; //not valid + } } + if (!file) + return -1; return com_filesize; } @@ -3718,10 +3757,17 @@ qboolean CSQC_DrawView(void) if (csqcg.clientcommandframe) *csqcg.clientcommandframe = cls.netchan.outgoing_sequence; if (csqcg.servercommandframe) - *csqcg.servercommandframe = cls.netchan.incoming_sequence; + *csqcg.servercommandframe = cl.ackedinputsequence; if (csqcg.intermission) *csqcg.intermission = cl.intermission; + if (csqcg.view_angles) + { + csqcg.view_angles[0] = cl.viewangles[0][0]; + csqcg.view_angles[1] = cl.viewangles[0][1]; + csqcg.view_angles[2] = cl.viewangles[0][2]; + } + if (csqcg.time) *csqcg.time = Sys_DoubleTime(); @@ -3858,7 +3904,7 @@ void CSQC_ParseEntities(void) if (csqcg.clientcommandframe) *csqcg.clientcommandframe = cls.netchan.outgoing_sequence; if (csqcg.servercommandframe) - *csqcg.servercommandframe = cls.netchan.incoming_sequence; + *csqcg.servercommandframe = cl.ackedinputsequence; for(;;) { diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 464ea7c37..dd13a15a5 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -23,6 +23,8 @@ typedef struct menuedict_s +evalc_t menuc_eval_chain; + int menuentsize; // cvars @@ -830,6 +832,12 @@ void PF_M_addwantedhostcachekey(progfuncs_t *prinst, struct globalvars_s *pr_glo { PF_M_gethostcacheindexforkey(prinst, pr_globals); } + +void PF_M_getextresponse(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + //this does something weird + G_INT(OFS_RETURN) = 0; +} #else void PF_gethostcachevalue (progfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;} @@ -887,7 +895,8 @@ void PF_CL_precache_file (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_menu_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int i, f; - char *s, *t; + char *s; + string_t t; menuedict_t *ent, *chain; //note, all edicts share the common header, but don't use it's fields! eval_t *val; @@ -901,13 +910,13 @@ void PF_menu_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent = (menuedict_t *)EDICT_NUM(prinst, i); if (ent->isfree) continue; - t = *(string_t *)&((float*)ent->fields)[f] + prinst->stringtable; + t = *(string_t *)&((float*)ent->fields)[f]; if (!t) continue; - if (strcmp(t, s)) + if (strcmp(PR_GetString(prinst, t), s)) continue; - val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", NULL); + val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", &menuc_eval_chain); if (val) val->edict = EDICT_TO_PROG(prinst, (void*)chain); chain = ent; @@ -1295,7 +1304,8 @@ builtin_t menu_builtins[] = { PF_M_refreshhostcache, PF_M_gethostcachenumber, PF_M_gethostcacheindexforkey, - PF_M_addwantedhostcachekey + PF_M_addwantedhostcachekey, + PF_M_getextresponse // #624 }; int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]); @@ -1407,6 +1417,8 @@ void MP_Init (void) M_DeInit_Internal(); + memset(&menuc_eval_chain, 0, sizeof(menuc_eval_chain)); + menuprogparms.progsversion = PROGSTRUCT_VERSION; menuprogparms.ReadFile = COM_LoadStackFile;//char *(*ReadFile) (char *fname, void *buffer, int *len); @@ -1521,7 +1533,7 @@ void MP_Reload_f(void) void MP_RegisterCvarsAndCmds(void) { Cmd_AddCommand("coredump_menuqc", MP_CoreDump_f); - Cmd_AddCommand("menuqc_reload", MP_Reload_f); + Cmd_AddCommand("menu_restart", MP_Reload_f); Cvar_Register(&forceqmenu, MENUPROGSGROUP); Cvar_Register(&pr_menuqc_coreonerror, MENUPROGSGROUP); @@ -1532,6 +1544,8 @@ void MP_RegisterCvarsAndCmds(void) void MP_Draw(void) { + if (!menuprogs) + return; if (setjmp(mp_abort)) return; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index c32c89011..65dc04170 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -1783,6 +1783,9 @@ void Sbar_Draw (void) if (sbarfailed) //files failed to load. { + if (cl.stats[pnum][STAT_HEALTH] <= 0) //when dead, show nothing + continue; + if (scr_viewsize.value != 120) Cvar_Set(&scr_viewsize, "120"); diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index 7b738d55d..90e49bacf 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -709,9 +709,13 @@ sfxcache_t *S_LoadWavSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) int len; sfxcache_t *sc; + if (datalen < 4 || strncmp(data, "RIFF", 4)) + return NULL; + info = GetWavinfo (s->name, data, datalen); if (info.numchannels < 1 || info.numchannels > 2) { + s->failedload = true; Con_Printf ("%s has an unsupported quantity of channels.\n",s->name); return NULL; } @@ -851,6 +855,15 @@ sfxcache_t *S_LoadSound (sfx_t *s) if (!data) data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); + if (!data) + { + char altname[sizeof(namebuffer)]; + COM_StripExtension(namebuffer, altname, sizeof(altname)); + COM_DefaultExtension(altname, ".ogg", sizeof(altname)); + data = COM_LoadStackFile(altname, stackbuf, sizeof(stackbuf)); + if (data) + Con_DPrintf("found a mangled name\n"); + } } if (!data) @@ -861,6 +874,8 @@ sfxcache_t *S_LoadSound (sfx_t *s) return NULL; } + s->failedload = false; + for (i = sizeof(AudioInputPlugins)/sizeof(AudioInputPlugins[0])-1; i >= 0; i--) { if (AudioInputPlugins[i]) @@ -871,6 +886,9 @@ sfxcache_t *S_LoadSound (sfx_t *s) } } + if (!s->failedload) + Con_Printf ("Format not recognised: %s\n", namebuffer); + s->failedload = true; return NULL; } diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index d0e700507..4883cb1c7 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -3,50 +3,50 @@ #ifdef AVAIL_OGGVORBIS #ifdef __MORPHOS__ -#include -#include + #include + #include -#include -#include -#else -#include + #include + #include + #else + #include #endif #if defined(__MORPHOS__) -#define oggvorbislibrary VorbisFileBase -struct Library *VorbisFileBase; + #define oggvorbislibrary VorbisFileBase + struct Library *VorbisFileBase; #elif defined(_WIN32) -#define WINDOWSDYNAMICLINK + #define WINDOWSDYNAMICLINK -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include -HINSTANCE oggvorbislibrary; + HINSTANCE oggvorbislibrary; #else -#include -void *oggvorbislibrary; + #include + void *oggvorbislibrary; #endif #ifdef __MORPHOS__ -#define p_ov_open_callbacks(a, b, c, d, e) ov_open_callbacks(a, b, c, d, &e) -#define p_ov_clear ov_clear -#define p_ov_info ov_info -#define p_ov_comment ov_comment -#define p_ov_pcm_total ov_pcm_total -#define p_ov_read ov_read + #define p_ov_open_callbacks(a, b, c, d, e) ov_open_callbacks(a, b, c, d, &e) + #define p_ov_clear ov_clear + #define p_ov_info ov_info + #define p_ov_comment ov_comment + #define p_ov_pcm_total ov_pcm_total + #define p_ov_read ov_read #else -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); + 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); #endif @@ -84,6 +84,9 @@ sfxcache_t *S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) //qboolean telluser; //unreferenced //int len; //unreferenced + if (datalen < 4 || strncmp(data, "OggS", 4)) + return NULL; + name = s->name; if (!s->decoder) @@ -107,6 +110,7 @@ sfxcache_t *S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) } Z_Free(s->decoder); s->decoder=NULL; + s->failedload = true; return NULL; } @@ -131,34 +135,38 @@ int OV_DecodeSome(sfx_t *s, int minlength) // Con_Printf("Minlength = %03i ", minlength); - if (dec->mediaaswavbuflen < dec->mediaaswavpos+minlength+11050) //expand if needed. - { -// Con_Printf("Expand buffer\n"); - dec->mediaaswavbuflen += minlength+22100; - dec->mediaaswavdata = BZ_Realloc(dec->mediaaswavdata, dec->mediaaswavbuflen); - s->cache.data = dec->mediaaswavdata; - s->cache.fake = true; - - sc = s->cache.data; - sc->numchannels = dec->mediasc.numchannels; - sc->loopstart = -1; - } - else - sc = s->cache.data; - - if (minlength < sc->length) - { -// Con_Printf("No need for decode\n"); - //done enough for now, don't whizz through the lot - return 0; - } - for (;;) { + if (dec->mediaaswavbuflen < dec->mediaaswavpos+minlength+11050) //expand if needed. + { + // Con_Printf("Expand buffer\n"); + dec->mediaaswavbuflen += minlength+22100; + dec->mediaaswavdata = BZ_Realloc(dec->mediaaswavdata, dec->mediaaswavbuflen); + s->cache.data = dec->mediaaswavdata; + s->cache.fake = true; + + sc = s->cache.data; + sc->numchannels = dec->mediasc.numchannels; + sc->loopstart = -1; + } + else + sc = s->cache.data; + + if (minlength < sc->length) + { + // Con_Printf("No need for decode\n"); + //done enough for now, don't whizz through the lot + return 0; + } + bytesread = p_ov_read(&dec->vf, dec->mediaaswavdata+dec->mediaaswavpos, dec->mediaaswavbuflen-dec->mediaaswavpos, bigendianp, 2, 1, ¤t_section); if (bytesread <= 0) { - Con_Printf("ogg decoding failed\n"); + if (bytesread != 0) //0==eof + { + Con_Printf("ogg decoding failed\n"); + return 1; + } return 0; } @@ -275,6 +283,8 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf #elif defined(WINDOWSDYNAMICLINK) { oggvorbislibrary = LoadLibrary("vorbisfile.dll"); + if (!oggvorbislibrary) + oggvorbislibrary = LoadLibrary("libvorbisfile.dll"); if (!oggvorbislibrary) { Con_Printf("Couldn't load DLL: \"vorbisfile.dll\".\n"); @@ -311,14 +321,17 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf tried = true; if (!oggvorbislibrary) + { + Con_Printf("ogg vorbis library is not loaded.\n"); return false; + } buffer->start = start; buffer->length = length; buffer->pos = 0; if (p_ov_open_callbacks(buffer, &buffer->vf, NULL, 0, callbacks)) { -// Con_Printf("Input does not appear to be an Ogg bitstream.\n"); + Con_Printf("Input does not appear to be an Ogg bitstream.\n"); return false; } diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index a48c90187..3f51ce530 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -473,8 +473,6 @@ int main (int c, char **v) if (COM_CheckParm("-nostdout")) nostdout = 1; - Sys_Init(); - Host_Init(&parms); oldtime = Sys_DoubleTime (); diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index 8ffa18517..39864662c 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -259,7 +259,6 @@ int main(int argc, char **argv) #else parms.membase = malloc (parms.memsize); #endif - Sys_Init (); Sys_Printf ("Host_Init\n"); Host_Init (&parms); diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 70d818b5f..e4a241003 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -462,6 +462,9 @@ void Sys_Init (void) // unsigned int lowpart, highpart; OSVERSIONINFO vinfo; + Cvar_Register(&sys_disableWinKeys, "System vars"); + Cvar_Register(&sys_disableTaskSwitch, "System vars"); + #ifndef SERVERONLY #ifndef CLIENTONLY if (!isDedicated && !COM_CheckParm("-nomutex")) @@ -1232,14 +1235,9 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (!tevent) Sys_Error ("Couldn't create event"); - Sys_Init (); - Sys_Printf ("Host_Init\n"); Host_Init (&parms); - Cvar_Register(&sys_disableWinKeys, "System vars"); - Cvar_Register(&sys_disableTaskSwitch, "System vars"); - oldtime = Sys_DoubleTime (); diff --git a/engine/client/view.c b/engine/client/view.c index 008acef71..f79098f94 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1168,7 +1168,7 @@ void V_CalcRefdef (int pnum) else if (scr_viewsize.value == 80) view->origin[2] += 0.5; - if (!view_message || view_message->flags & (PF_GIB|PF_DEAD) ) + if (!view_message || view_message->flags & (PF_GIB|PF_DEAD) || (unsigned int)cl.stats[pnum][STAT_WEAPON] >= MAX_MODELS) view->model = NULL; else view->model = cl.model_precache[cl.stats[pnum][STAT_WEAPON]]; diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index d4e1ae27e..32d17b2c4 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -530,7 +530,7 @@ MAX_CL_STATS = 256 #define SAVEGAME_VERSION 667 - +#define PM_DEFAULTSTEPHEIGHT 18 #define dem_cmd 0 diff --git a/engine/common/common.c b/engine/common/common.c index 163cd71ca..9087d537e 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1602,6 +1602,247 @@ void COM_DefaultExtension (char *path, char *extension, int maxlen) Q_strncatz (path, extension, maxlen); } + + + +///===================================== + + + + +//Strips out the flags +void COM_DeFunString(unsigned long *str, char *out, int outsize, qboolean ignoreflags) +{ + if (ignoreflags) + { + while(*str) + { + if (!--outsize) + break; + *out++ = (unsigned char)(*str++&255); + } + *out++ = 0; + } + else + { + int fl, d; + //FIXME: TEST! + + fl = CON_WHITEMASK; + while(*str) + { + if (!--outsize) + break; + if ((*str & CON_FLAGSMASK) != fl) + { + d = fl^(*str & CON_FLAGSMASK); +// if (fl & CON_NONCLEARBG) //not represented. + if (d & CON_BLINKTEXT) + { + if (outsize<=2) + break; + outsize -= 2; + *out++ = '^'; + *out++ = 'b'; + } + if (d & CON_2NDCHARSETTEXT) + { + if (outsize<=2) + break; + outsize -= 2; + *out++ = '^'; + *out++ = 'a'; + } + if (d & CON_HALFALPHA) + { + if (outsize<=2) + break; + outsize -= 2; + *out++ = '^'; + *out++ = 'h'; + } + + if (d & (CON_FGMASK | CON_BGMASK | CON_NONCLEARBG)) + { + if (outsize<=4) + break; + outsize -= 4; + + d = (*str & CON_FLAGSMASK); + *out++ = '^'; + *out++ = '&'; + if ((d & CON_FGMASK) == CON_WHITEMASK) + *out++ = '-'; + else + sprintf(out, "%X", d>>24); + if (d & CON_NONCLEARBG) + { + sprintf(out, "%X", d>>28); + } + else + *out++ = '-'; + } + + fl = (*str & CON_FLAGSMASK); + } + *out++ = (unsigned char)(*str++&255); + } + *out++ = 0; + } +} + +//Takes a q3-style fun string, and returns an expanded string-with-flags +void COM_ParseFunString(char *str, unsigned long *out, int outsize) +{ + int ext = CON_WHITEMASK; + int extstack[4]; + int extstackdepth = 0; + + while(*str) + { + if (*str == '^') + { + str++; + if (*str >= '0' && *str <= '9') + { + ext = q3codemasks[*str++-'0'] | (ext&~CON_Q3MASK); //change colour only. + continue; + } + else if (*str == '&') // extended code + { + if (isextendedcode(str[1]) && isextendedcode(str[2])) + { + str++;// foreground char + if (*str == '-') // default for FG + ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~CON_FGMASK); + else if (*str >= 'A') + ext = ((*str - ('A' - 10)) << CON_FGSHIFT) | (ext&~CON_FGMASK); + else + ext = ((*str - '0') << CON_FGSHIFT) | (ext&~CON_FGMASK); + str++; // background char + if (*str == '-') // default (clear) for BG + ext &= ~CON_BGMASK & ~CON_NONCLEARBG; + else if (*str >= 'A') + ext = ((*str - ('A' - 10)) << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; + else + ext = ((*str - '0') << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; + str++; + continue; + } + // else invalid code + goto messedup; + } + else if (*str == 'a') + { + str++; + ext ^= CON_2NDCHARSETTEXT; + continue; + } + else if (*str == 'b') + { + str++; + ext ^= CON_BLINKTEXT; + continue; + } + else if (*str == 'h') + { + str++; + ext ^= CON_HALFALPHA; + continue; + } + else if (*str == 's') //store on stack (it's great for names) + { + str++; + if (extstackdepth < sizeof(extstack)/sizeof(extstack[0])) + { + extstack[extstackdepth] = ext; + extstackdepth++; + } + continue; + } + else if (*str == 'r') //restore from stack (it's great for names) + { + str++; + if (extstackdepth) + { + extstackdepth--; + ext = extstack[extstackdepth]; + } + continue; + } + else if (*str == '^') + { + if (!--outsize) + break; + *out++ = '^' | ext; + str++; + } + else + { + if (!--outsize) + break; + *out++ = '^' | ext; + if (!--outsize) + break; + *out++ = (*str++) | ext; + } + continue; + } +messedup: + if (!--outsize) + break; + *out++ = (*str++) | ext; + } + *out = 0; +} + +int COM_FunStringLength(unsigned char *str) +{ + int len; + + while(*str) + { + if (*str == '^') + { + str++; + if (*str >= '0' && *str <= '9') + str++; //invisible + else if (*str == '&') // extended code + { + if (isextendedcode(str[1]) && isextendedcode(str[2])) + { + str++;// foreground char + str++; // background char + str++; + continue; + } + // else invalid code + goto messedup; + } + else if (*str == 'a' || *str == 'b' || *str == 'h' || *str == 's' || *str == 'r') + str++; //invisible + else if (*str == '^') + { + len++; //double-code single-output + str++; + } + else + { + len++; //not recognised + len++; + str++; + } + continue; + } +messedup: + len++; + str++; + } + + return len; +} + + //============================================================================ #define TOKENSIZE sizeof(com_token) diff --git a/engine/common/fs.c b/engine/common/fs.c index 05461fda2..1d869dc17 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2788,6 +2788,7 @@ void COM_Gamedir (char *dir) #endif } +/* typedef struct { char *file; char *path; @@ -2801,7 +2802,9 @@ potentialgamepath_t pgp[] = { {"%s/baseq3/pak0.pk3", "%s/baseq3"}, //quake3 {"%s/base/assets0.pk3", "%s/base"} //jk2 }; +*/ +#define NEXCFG "set sv_maxairspeed \"400\"\nset sv_mintic \"0.01\"\ncl_nolerp 0\n" typedef struct { char *gamename; //sent to the master server when this is the current gamemode. @@ -2809,6 +2812,8 @@ typedef struct { char *argname; //used if this was used as a parameter. char *auniquefile; //used if this file is relative from the gamedir + char *customexec; + char *dir1; char *dir2; char *dir3; @@ -2817,17 +2822,19 @@ typedef struct { gamemode_info_t gamemode_info[] = { //note that there is no basic 'fte' gamemode, this is because we aim for network compatability. Darkplaces-Quake is the closest we get. //this is to avoid having too many gamemodes anyway. - {"Darkplaces-Quake", "darkplaces", "-quake", "id1/pak0.pak", "id1", "qw", "fte"}, - {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", NULL/*"hipnotic/pak0.pak"*/,"id1", "qw", "hipnotic", "fte"}, - {"Darkplaces-Rogue", "rogue", "-rogue", NULL/*"rogue/pak0.pak", "id1"*/, "qw", "rogue", "fte"}, - {"Nexuiz", "nexuiz", "-nexuiz", "data/cvars.txt", "id1", "qw", "data", "fte"}, + +//rogue/hipnotic have no special files - the detection conflicts and stops us from running regular quake + {"Darkplaces-Quake", "darkplaces", "-quake", "id1/pak0.pak", NULL, "id1", "qw", "fte"}, + {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", NULL, NULL, "id1", "qw", "hipnotic", "fte"}, + {"Darkplaces-Rogue", "rogue", "-rogue", NULL, NULL, "id1", "qw", "rogue", "fte"}, + {"Nexuiz", "nexuiz", "-nexuiz", "nexuiz.exe", NEXCFG, "id1", "qw", "data", "fte"}, //supported commercial mods (some are currently only partially supported) - {"FTE-Hexen2", "hexen", "-hexen2", "data1/pak0.pak", "data1", "fte"}, - {"FTE-Quake2", "q2", "-q2", "baseq2/pak0.pak", "baseq2", "fte"}, - {"FTE-Quake3", "q3", "-q3", "baseq3/pak0.pk3", "baseq3", "fte"}, + {"FTE-Hexen2", "hexen", "-hexen2", "data1/pak0.pak", NULL, "data1", "fte"}, + {"FTE-Quake2", "q2", "-q2", "baseq2/pak0.pak", NULL, "baseq2", "fte"}, + {"FTE-Quake3", "q3", "-q3", "baseq3/pak0.pk3", NULL, "baseq3", "fte"}, - {"FTE-JK2", "jk2", "-jk2", "base/assets0.pk3", "base", "fte"}, + {"FTE-JK2", "jk2", "-jk2", "base/assets0.pk3", NULL, "base", "fte"}, {NULL} }; @@ -3095,6 +3102,9 @@ void COM_InitFilesystem (void) } Cvar_Set(&com_gamename, gamemode_info[gamenum].gamename); + if (gamemode_info[gamenum].customexec) + Cbuf_AddText(gamemode_info[gamenum].customexec, RESTRICT_LOCAL); + #ifdef _WIN32 { //win32 sucks. diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 8d7297dd2..a00d88016 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -271,17 +271,17 @@ int PM_StepSlideMove (qboolean in_air) org = (originalvel[2] < 0) ? pmove.origin : original; VectorCopy (org, dest); - dest[2] -= pm_stepheight; + dest[2] -= movevars.stepheight; trace = PM_PlayerTrace (org, dest); if (trace.fraction == 1 || trace.plane.normal[2] < MIN_STEP_NORMAL) return blocked; // adjust stepsize, otherwise it would be possible to walk up a // a step higher than STEPSIZE - stepsize = pm_stepheight - (org[2] - trace.endpos[2]); + stepsize = movevars.stepheight - (org[2] - trace.endpos[2]); } else - stepsize = pm_stepheight; + stepsize = movevars.stepheight; VectorCopy (pmove.origin, down); VectorCopy (pmove.velocity, downvel); @@ -600,7 +600,7 @@ void PM_LadderMove (void) // assume it is a stair or a slope, so press down from stepheight above VectorMA (pmove.origin, frametime, pmove.velocity, dest); VectorCopy (dest, start); - start[2] += pm_stepheight + 1; + start[2] += movevars.stepheight + 1; trace = PM_PlayerTrace (start, dest); if (!trace.startsolid && !trace.allsolid) // FIXME: check steep slope? { // walked up the step diff --git a/engine/common/pmove.h b/engine/common/pmove.h index a3e92c339..658fd4abc 100644 --- a/engine/common/pmove.h +++ b/engine/common/pmove.h @@ -93,6 +93,7 @@ typedef struct { qboolean slidefix; qboolean airstep; qboolean slidyslopes; + int stepheight; } movevars_t; diff --git a/engine/common/q2pmove.c b/engine/common/q2pmove.c index 17580847a..60b313171 100644 --- a/engine/common/q2pmove.c +++ b/engine/common/q2pmove.c @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" -float pm_stepheight = 18; +float pm_q2stepheight = PM_DEFAULTSTEPHEIGHT; #if defined(Q2CLIENT) || defined(Q2SERVER) #define Q2PMF_DUCKED 1 @@ -293,7 +293,7 @@ void PMQ2_StepSlideMove (void) VectorCopy (q2pml.velocity, down_v); VectorCopy (start_o, up); - up[2] += pm_stepheight; + up[2] += pm_q2stepheight; trace = q2pm->trace (up, q2pm->mins, q2pm->maxs, up); if (trace.allsolid) @@ -307,7 +307,7 @@ void PMQ2_StepSlideMove (void) // push down the final amount VectorCopy (q2pml.origin, down); - down[2] -= pm_stepheight; + down[2] -= pm_q2stepheight; trace = q2pm->trace (q2pml.origin, q2pm->mins, q2pm->maxs, down); if (!trace.allsolid) { diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index e64688f02..3878b40c9 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -1319,7 +1319,7 @@ void R_ModifyTextureCoords ( shaderpass_t *pass, int unit ) int i, j; float *table; float t1, t2, sint, cost; - float *tcArray; + float *tcArray, *buffer; tcmod_t *tcmod; r_texNums[unit] = R_ShaderpassTex ( pass ); @@ -1336,11 +1336,12 @@ void R_ModifyTextureCoords ( shaderpass_t *pass, int unit ) return; } - R_VertexTCBase ( pass->tcgen, unit ); + buffer = R_VertexTCBase (pass->tcgen, unit); + qglTexCoordPointer(2, GL_FLOAT, 0, buffer); for (i = 0, tcmod = pass->tcmods; i < pass->numtcmods; i++, tcmod++) { - tcArray = tUnitCoordsArray[unit][0]; + tcArray = buffer; switch (tcmod->type) { diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index c79fc977d..c47e91fc8 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -241,7 +241,10 @@ qboolean Draw_RealPicFromWad (mpic_t *out, char *name) int texnum; char name2[256]; - in = W_SafeGetLumpName (name); + if (!strncmp(name, "gfx/", 4)) + in = W_SafeGetLumpName (name+4); + else + in = W_SafeGetLumpName (name); gl = (glpic_t *)out->data; if (in) @@ -513,8 +516,6 @@ mpic_t *GLDraw_SafeCachePic (char *path) { mpic_t *m; m = GLDraw_SafePicFromWad(path); - if (!m && !strncmp(path, "gfx/", 4)) - return GLDraw_SafePicFromWad(path+4); return m; } } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 273305585..5217f2346 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -1107,6 +1107,8 @@ TRACE(("dbg: GLR_NewMap: tp\n")); void GLR_PreNewMap(void) { + extern int solidskytexture; + solidskytexture = 0; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 8e9a8b5bc..3f301cc04 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -3269,7 +3269,7 @@ void PF_clienttype (progfuncs_t *prinst, struct globalvars_s *pr_globals) return; } if (svs.clients[entnum].protocol == SCP_BAD) - G_FLOAT(OFS_RETURN) = 2; //an active, not-bot client. + G_FLOAT(OFS_RETURN) = 2; //an active, bot client. else G_FLOAT(OFS_RETURN) = 1; //an active, not-bot client. } @@ -3287,7 +3287,7 @@ void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *str; - str = PR_GetStringOfs(prinst, OFS_PARM0); + str = PF_VarString(prinst, 0, pr_globals); if (!strcmp(str, "host_framerate 0\n")) Cbuf_AddText ("sv_mintic 0\n", RESTRICT_INSECURE); //hmm... do this better... else @@ -3317,7 +3317,12 @@ static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = sv.worldmodel->fromgame == fg_halflife; else { - cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); + cvar_t *cv = Cvar_FindVar(str); + if (!cv) + { + cv = Cvar_Get(str, "", 0, "QC variables"); + Con_Printf("Creating cvar %s\n", str); + } G_FLOAT(OFS_RETURN) = cv->value; } } @@ -5688,9 +5693,9 @@ static int chrchar_alpha(int i, int basec, int baset, int convc, int convt, int //bulk convert a string. change case or colouring. void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - int ccase = G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper + int ccase = G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper int redalpha = G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate - int redchars = G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate + int rednum = G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate unsigned char *string = PF_VarString(prinst, 3, pr_globals); int len = strlen(string); int i; @@ -5703,22 +5708,22 @@ void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) for (i = 0; i < len; i++, string++, result++) //should this be done backwards? { if (*string >= '0' && *string <= '9') //normal numbers... - *result = chrconv_number(*string, '0', redchars); + *result = chrconv_number(*string, '0', rednum); else if (*string >= '0'+128 && *string <= '9'+128) - *result = chrconv_number(*string, '0'+128, redchars); + *result = chrconv_number(*string, '0'+128, rednum); else if (*string >= '0'+128-30 && *string <= '9'+128-30) - *result = chrconv_number(*string, '0'+128-30, redchars); + *result = chrconv_number(*string, '0'+128-30, rednum); else if (*string >= '0'-30 && *string <= '9'-30) - *result = chrconv_number(*string, '0'-30, redchars); + *result = chrconv_number(*string, '0'-30, rednum); else if (*string >= 'a' && *string <= 'z') //normal numbers... - *result = chrchar_alpha(*string, 'a', 0, ccase, redchars, i); + *result = chrchar_alpha(*string, 'a', 0, ccase, redalpha, i); else if (*string >= 'A' && *string <= 'Z') //normal numbers... - *result = chrchar_alpha(*string, 'A', 0, ccase, redchars, i); + *result = chrchar_alpha(*string, 'A', 0, ccase, redalpha, i); else if (*string >= 'a'+128 && *string <= 'z'+128) //normal numbers... - *result = chrchar_alpha(*string, 'a', 128, ccase, redchars, i); + *result = chrchar_alpha(*string, 'a', 128, ccase, redalpha, i); else if (*string >= 'A'+128 && *string <= 'Z'+128) //normal numbers... - *result = chrchar_alpha(*string, 'A', 128, ccase, redchars, i); + *result = chrchar_alpha(*string, 'A', 128, ccase, redalpha, i); else if ((*string & 127) < 16 || !redalpha) //special chars.. *result = *string; @@ -5790,6 +5795,28 @@ void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_TSTRING(key); } +//DP_QC_STRINGCOLORFUNCTIONS +// #476 float(string s) strlennocol - returns how many characters are in a string, minus color codes +void PF_strlennocol (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PR_GetStringOfs(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = COM_FunStringLength(in); +} + +//DP_QC_STRINGCOLORFUNCTIONS +// string (string s) strdecolorize - returns the passed in string with color codes stripped +void PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PR_GetStringOfs(prinst, OFS_PARM0); + char result[8192]; + unsigned long flagged[8192]; + COM_ParseFunString(in, flagged, sizeof(flagged)/sizeof(flagged[0])); + COM_DeFunString(flagged, result, sizeof(result), true); + + RETURN_TSTRING(result); +} + + //back to frik_file support. @@ -5881,9 +5908,8 @@ void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals) } } -void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) +void PF_fclose_i (int fnum) { - int fnum = G_FLOAT(OFS_PARM0)-FIRST_QC_FILE_INDEX; if (fnum < 0 || fnum >= MAX_QC_FILES) { Con_Printf("PF_fclose: File out of range\n"); @@ -5896,12 +5922,6 @@ void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) return; //not open } - if (pf_fopen_files[fnum].prinst != prinst) - { - Con_Printf("PF_fclose: File is from wrong instance\n"); - return; //this just isn't ours. - } - switch(pf_fopen_files[fnum].accessmode) { case 0: @@ -5917,6 +5937,25 @@ void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) pf_fopen_files[fnum].prinst = NULL; } +void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int fnum = G_FLOAT(OFS_PARM0)-FIRST_QC_FILE_INDEX; + + if (fnum < 0 || fnum >= MAX_QC_FILES) + { + Con_Printf("PF_fclose: File out of range\n"); + return; //out of range + } + + if (pf_fopen_files[fnum].prinst != prinst) + { + Con_Printf("PF_fclose: File is from wrong instance\n"); + return; //this just isn't ours. + } + + PF_fclose_i(fnum); +} + void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char c, *s, *o, *max; @@ -6008,15 +6047,14 @@ void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) pf_fopen_files[fnum].ofs+=len; } -void PF_fcloseall (progfuncs_t *prinst, struct globalvars_s *pr_globals) +void PF_fcloseall (progfuncs_t *prinst) { int i; for (i = 0; i < MAX_QC_FILES; i++) { if (pf_fopen_files[i].prinst != prinst) continue; - G_FLOAT(OFS_PARM0) = i+FIRST_QC_FILE_INDEX; - PF_fclose(prinst, pr_globals); + PF_fclose_i(i); } } @@ -6274,6 +6312,7 @@ lh_extension_t QSG_Extensions[] = { {"DP_QC_MULTIPLETEMPSTRINGS"}, {"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, {"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, + {"DP_QC_STRINGCOLORFUNCTIONS", 2, NULL, {"strlennocol", "strdecolorize"}}, {"DP_QC_UNLIMITEDTEMPSTRINGS"}, {"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}}, {"DP_QC_TRACETOSS"}, @@ -6663,7 +6702,7 @@ void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals) ================= PF_strpad -string strcat(float pad, string str1, ...) +string strpad(float pad, string str1, ...) ================= */ @@ -7048,7 +7087,8 @@ void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int i, f; - char *s, *t; + char *s; + string_t t; edict_t *ent, *chain; chain = (edict_t *) *prinst->parms->sv_edicts; @@ -7061,10 +7101,10 @@ void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent = EDICT_NUM(prinst, i); if (ent->isfree) continue; - t = *(string_t *)&((float*)ent->v)[f] + prinst->stringtable; + t = *(string_t *)&((float*)ent->v)[f]; if (!t) continue; - if (strcmp(t, s)) + if (strcmp(PR_GetString(prinst, t), s)) continue; ent->v->chain = EDICT_TO_PROG(prinst, chain); @@ -9687,6 +9727,9 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"WriteUnterminatedString",PF_WriteString2,0, 0, 0, 456}, //writestring but without the null terminator. makes things a little nicer. + {"strlennocol", PF_strlennocol, 0, 0, 0, 476}, // #476 float(string s) strlennocol + {"strdecolorize", PF_strdecolorize, 0, 0, 0, 477}, // #477 string(string s) strdecolorize + //end other peoples extras //don't exceed sizeof(pr_builtin)/sizeof(pr_builtin[0]) (currently 1024) without modifing the size of pr_builtin diff --git a/engine/server/q2game.h b/engine/server/q2game.h index ee3d984d1..eee350b9b 100644 --- a/engine/server/q2game.h +++ b/engine/server/q2game.h @@ -30,7 +30,7 @@ typedef enum multicast_e MULTICAST_PVS_R } multicast_t; -extern float pm_stepheight; +extern float pm_q2stepheight; #ifdef Q2SERVER diff --git a/engine/server/server.h b/engine/server/server.h index 5d66675ee..db5011b3a 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -409,10 +409,14 @@ typedef struct client_s q3client_frame_t *q3frames; #endif } frameunion; + vfsfile_t *download; // file being downloaded int downloadsize; // total bytes int downloadcount; // bytes sent + int downloadacked; //DP-specific + int downloadstarted; //DP-specific + int spec_track; // entnum of player tracking #ifdef Q3SERVER diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 5f088abc0..a81ff6253 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -613,7 +613,20 @@ void SV_Map_f (void) SV_SpawnServer (level, startspot, false, cinematic); } - SV_BroadcastCommand ("cmd new\n"); + //SV_BroadcastCommand ("cmd new\n"); + for (i=0, host_client = svs.clients ; icontroller) + continue; + if (host_client->state>=cs_connected) + { + if (ISNQCLIENT(host_client)) + SVNQ_New_f(); + else + SV_New_f(); + } + } if (!issamelevel) { diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index c9701c89b..b18578433 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1719,7 +1719,7 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size clst.zext = client->zquake_extensions; clst.cl = cl; - if (ent != vent) + if (ent != vent || host_client->viewent == j+1) clst.modelindex = 0; if (sv.demostatevalid) @@ -2293,25 +2293,28 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore state->fatness = clent->v->fatness*2; #endif - if (state->effects & QWEF_FLAG1) + if (progstype == PROG_QW) { - memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); - state = &pack->entities[pack->num_entities]; - pack->num_entities++; - state->modelindex = SV_ModelIndex("progs/flag.mdl"); - state->frame = 0; - state->number++; - state->skinnum = 0; - } - else if (state->effects & QWEF_FLAG2) - { - memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); - state = &pack->entities[pack->num_entities]; - pack->num_entities++; - state->modelindex = SV_ModelIndex("progs/flag.mdl"); - state->frame = 0; - state->number++; - state->skinnum = 1; + if (state->effects & QWEF_FLAG1) + { + memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); + state = &pack->entities[pack->num_entities]; + pack->num_entities++; + state->modelindex = SV_ModelIndex("progs/flag.mdl"); + state->frame = 0; + state->number++; + state->skinnum = 0; + } + else if (state->effects & QWEF_FLAG2) + { + memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); + state = &pack->entities[pack->num_entities]; + pack->num_entities++; + state->modelindex = SV_ModelIndex("progs/flag.mdl"); + state->frame = 0; + state->number++; + state->skinnum = 1; + } } state->effects &= ~(QWEF_FLAG1 | QWEF_FLAG2); } @@ -2558,6 +2561,9 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (state->effects & 0x32) state->effects |= 0; + if (state->effects & 0x00400000) + state->effects &= ~0x00400000; + if (state->effects & EF_FULLBRIGHT) { state->hexen2flags |= MLS_FULLBRIGHT; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 810723b1f..248e6acc0 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1535,7 +1535,7 @@ client_t *SVC_DirectConnect(void) if (!sv_listen_qw.value && net_from.type != NA_LOOPBACK) { SV_RejectMessage (SCP_BAD, "QuakeWorld protocols are not permitted on this server.\n"); - Con_Printf ("* rejected connect from quakeworld\n", version); + Con_Printf ("* rejected connect from quakeworld\n"); return NULL; } @@ -3018,6 +3018,7 @@ void SV_InitLocal (void) extern cvar_t pm_airstep; extern cvar_t pm_walljump; extern cvar_t pm_slidyslopes; + extern cvar_t pm_stepheight; SV_InitOperatorCommands (); SV_UserInit (); @@ -3085,6 +3086,7 @@ void SV_InitLocal (void) Cvar_Register (&pm_slidyslopes, cvargroup_serverphysics); Cvar_Register (&pm_airstep, cvargroup_serverphysics); Cvar_Register (&pm_walljump, cvargroup_serverphysics); + Cvar_Register (&pm_stepheight, cvargroup_serverphysics); Cvar_Register (&sv_compatablehulls, cvargroup_serverphysics); @@ -3490,7 +3492,8 @@ void SV_FixupName(char *in, char *out) } *s = '\0'; - if (!*out) { //reached end and it was all whitespace + if (!*out) + { //reached end and it was all whitespace //white space only strcpy(out, "unnamed"); p = out; @@ -3585,9 +3588,12 @@ void SV_ExtractFromUserinfo (client_t *cl) val = Info_ValueForKey (cl->userinfo, "name"); val[40] = 0; //trim to smallish length now (to allow for adding more. - SV_FixupName(val, newname); + if (cl->protocol != SCP_BAD || *val) + SV_FixupName(val, newname); + else + newname[0] = 0; - if (!val[0]) + if (!val[0] && cl->protocol != SCP_BAD) strcpy(newname, "Hidden"); else if (!stricmp(val, "console")) { @@ -3778,6 +3784,8 @@ void SV_Init (quakeparms_t *parms) Memory_Init (parms->membase, parms->memsize); + Sys_Init(); + COM_ParsePlusSets(); Cbuf_Init (); @@ -3810,7 +3818,6 @@ void SV_Init (quakeparms_t *parms) if (isDedicated) #endif { - Sys_Init (); PM_Init (); #ifdef PLUGINS diff --git a/engine/server/sv_move.c b/engine/server/sv_move.c index ff37137da..d0ccf1cef 100644 --- a/engine/server/sv_move.c +++ b/engine/server/sv_move.c @@ -71,7 +71,7 @@ realcheck: // the midpoint must be within 16 of the bottom start[0] = stop[0] = (mins[0] + maxs[0])*0.5; start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*pm_stepheight; + stop[2] = start[2] - 2*movevars.stepheight; savedhull = ent->v->hull; ent->v->hull = 0; trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent); @@ -95,7 +95,7 @@ realcheck: if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > pm_stepheight) + if (trace.fraction == 1.0 || mid - trace.endpos[2] > movevars.stepheight) return false; } @@ -184,9 +184,9 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink, qboolean noene } // push down from a step height above the wished position - neworg[2] += pm_stepheight; + neworg[2] += movevars.stepheight; VectorCopy (neworg, end); - end[2] -= pm_stepheight*2; + end[2] -= movevars.stepheight*2; trace = SV_Move (neworg, ent->v->mins, ent->v->maxs, end, false, ent); if (set_trace) @@ -197,7 +197,7 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink, qboolean noene if (trace.startsolid) { - neworg[2] -= pm_stepheight; + neworg[2] -= movevars.stepheight; trace = SV_Move (neworg, ent->v->mins, ent->v->maxs, end, false, ent); if (set_trace) set_move_trace(&trace, set_trace); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 9b37b1621..9dc81b13a 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -60,6 +60,7 @@ cvar_t pm_slidefix = SCVARF("pm_slidefix", "0", CVAR_SERVERINFO); cvar_t pm_slidyslopes = SCVARF("pm_slidyslopes", "0", CVAR_SERVERINFO); cvar_t pm_airstep = SCVARF("pm_airstep", "0", CVAR_SERVERINFO); cvar_t pm_walljump = SCVARF("pm_walljump", "0", CVAR_SERVERINFO); +cvar_t pm_stepheight = FCVAR("pm_stepheight", "sv_stepheight", "0", CVAR_SERVERINFO); extern cvar_t sv_nomsec; @@ -1213,7 +1214,7 @@ void SV_CheckStuck (edict_t *ent) return; } - for (z=0 ; z < pm_stepheight ; z++) + for (z=0 ; z < movevars.stepheight ; z++) for (i=-1 ; i <= 1 ; i++) for (j=-1 ; j <= 1 ; j++) { @@ -1419,8 +1420,8 @@ void SV_WalkMove (edict_t *ent) VectorCopy (vec3_origin, upmove); VectorCopy (vec3_origin, downmove); - upmove[2] = pm_stepheight; - downmove[2] = -pm_stepheight + oldvel[2]*host_frametime; + upmove[2] = movevars.stepheight; + downmove[2] = -movevars.stepheight + oldvel[2]*host_frametime; // move up SV_PushEntity (ent, upmove); // FIXME: don't link? @@ -1609,7 +1610,7 @@ void SV_WalkMove (edict_t *ent) // move up VectorClear (upmove); - upmove[2] = pm_stepheight; + upmove[2] = movevars.stepheight; // FIXME: don't link? SV_PushEntity(ent, upmove); @@ -1652,7 +1653,7 @@ void SV_WalkMove (edict_t *ent) // move down VectorClear (downmove); - downmove[2] = -pm_stepheight + start_velocity[2]*host_frametime; + downmove[2] = -movevars.stepheight + start_velocity[2]*host_frametime; // FIXME: don't link? downtrace = SV_PushEntity (ent, downmove); @@ -2030,5 +2031,6 @@ void SV_SetMoveVars(void) movevars.friction = sv_friction.value; movevars.waterfriction = sv_waterfriction.value; movevars.entgravity = 1.0; + movevars.stepheight = pm_stepheight.value; } #endif diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 11e1e9f62..f8875da1d 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1477,6 +1477,8 @@ qboolean SV_SendClientDatagram (client_t *client) SZ_Clear (&msg); } + SV_DarkPlacesDownloadChunk(client, &msg); + // send the datagram Netchan_Transmit (&client->netchan, msg.cursize, buf, SV_RateForClient(client)); @@ -1563,7 +1565,7 @@ void SV_UpdateToReliableMessages (void) MSG_WriteString (&sv.reliable_datagram, host_client->name); } } - host_client->edict->v->netname = host_client->name - svprogfuncs->stringtable; + host_client->edict->v->netname = PR_SetString(svprogfuncs, host_client->name); } } @@ -1910,7 +1912,22 @@ void SV_SendClientMessages (void) { //nq clients get artificial choke too c->send_message = false; if (c->nextservertimeupdate != sv.physicstime && c->state != cs_zombie) + { c->send_message = true; + + if (c->state == cs_connected && !c->datagram.cursize && !c->netchan.message.cursize) + { + if (c->nextservertimeupdate < sv.physicstime) + { //part of the nq protocols allowed downloading content over isdn + //the nop requirement of the protocol persisted to prevent timeouts when content loading is otherwise slow.. + //aditionally we might need this for lost packets, not sure + //but the client isn't able to respond unless we send an occasional datagram + if (c->nextservertimeupdate) + MSG_WriteByte(&c->datagram, svc_nop); + c->nextservertimeupdate = sv.physicstime+5; + } + } + } } if (!c->send_message) continue; @@ -1925,6 +1942,7 @@ void SV_SendClientMessages (void) SV_SendClientDatagram (c); else { + SV_DarkPlacesDownloadChunk(c, &c->datagram); Netchan_Transmit (&c->netchan, c->datagram.cursize, c->datagram.data, SV_RateForClient(c)); // just update reliable c->datagram.cursize = 0; } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 00f1ec714..eb248aa59 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -345,10 +345,14 @@ void SVNQ_New_f (void) if (host_client->protocol == SCP_DARKPLACES7) { + extern cvar_t allow_download; char *f; - MSG_WriteByte (&host_client->netchan.message, svc_stufftext); - MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n"); + if (allow_download.value) + { + MSG_WriteByte (&host_client->netchan.message, svc_stufftext); + MSG_WriteString (&host_client->netchan.message, "cl_serverextension_download 1\n"); + } f = COM_LoadTempFile("csprogs.dat"); if (f) @@ -1504,17 +1508,37 @@ void SV_Begin_f (void) //============================================================================= -void SV_DarkPlacesDownloadChunk(client_t *cl) +//dp downloads are a 2-stream system +//the server->client stream is as you'd expect. except that its unreliable rather than reliable +//the client->server stream contains no actual data. +//when c2s has a hole, the s2c stream is reset to the last-known 'good' position. +//eventually the client is left acking packets with no data in them, the server then tells the client that the download is complete. +//the client does no checks to see if there's a hole, other than the crc + +//so any single lost packet (even client->server) means that the entire stream will be set back by your ping time +void SV_DarkPlacesDownloadChunk(client_t *cl, sizebuf_t *msg) { #define MAXDPDOWNLOADCHUNK 1024 char buffer[MAXDPDOWNLOADCHUNK]; int size, start; + if (!ISNQCLIENT(cl)) + return; + if (!cl->download) + return; + + if (!cl->downloadstarted) + return; + if (cl->num_backbuf) - size = 16; - else - size = 512; + return; + + size = 1024; //fixme + + if (size > cl->datagram.maxsize - cl->datagram.cursize) + size = cl->datagram.maxsize - cl->datagram.cursize - 16; + if (size > MAXDPDOWNLOADCHUNK) //don't clog it too much size = MAXDPDOWNLOADCHUNK; @@ -1522,20 +1546,23 @@ void SV_DarkPlacesDownloadChunk(client_t *cl) if (start+size > cl->downloadsize) //clamp to the size of the file. size = cl->downloadsize - start; - VFS_READ(cl->download, buffer, size); + size = VFS_READ(cl->download, buffer, size); + if (size < 0) + size = 0; - //reliable? I don't care, this works. - ClientReliableWrite_Begin (cl, svcdp_downloaddata, 7+size); - ClientReliableWrite_Long (cl, start); - ClientReliableWrite_Short (cl, size); - ClientReliableWrite_SZ (cl, buffer, size); + MSG_WriteByte(msg, svcdp_downloaddata); + MSG_WriteLong (msg, start); + MSG_WriteShort (msg, size); + SZ_Write(msg, buffer, size); } -void SVDP_ForceDownloadChunk_f(void) +void SVDP_StartDownload_f(void) { if (host_client->protocol != SCP_DARKPLACES7) return; - SV_DarkPlacesDownloadChunk(host_client); + if (!host_client->download) + return; + host_client->downloadstarted = true; } void SV_DarkPlacesDownloadAck(client_t *cl) @@ -1543,7 +1570,20 @@ void SV_DarkPlacesDownloadAck(client_t *cl) int start = MSG_ReadLong(); int size = (unsigned short)MSG_ReadShort(); - if (size == 0) + if (!cl->download) + return; + + if (start != cl->downloadacked) + { + //packetloss + VFS_SEEK(cl->download, cl->downloadacked); + } + else if (size != 0) + { + cl->downloadacked += size; //successful packet + cl->downloadcount = cl->downloadacked; + } + else { char *s; unsigned short crc; @@ -1564,9 +1604,11 @@ void SV_DarkPlacesDownloadAck(client_t *cl) s = va("\ncl_downloadfinished %i %i \"\"\n", host_client->downloadsize, crc); ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen(s)); ClientReliableWrite_String(cl, s); + + VFS_CLOSE(host_client->download); + host_client->download = NULL; + host_client->downloadsize = 0; } - else - SV_DarkPlacesDownloadChunk(cl); } void SV_NextChunkedDownload(int chunknum) @@ -1860,6 +1902,8 @@ void SV_BeginDownload_f(void) { // don't allow anything with .. path if (ISNQCLIENT(host_client)) { + SV_PrintToClient(host_client, PRINT_HIGH, "Download rejected by server settings\n"); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_String (host_client, "\nstopdownload\n"); } @@ -1981,6 +2025,20 @@ void SV_BeginDownload_f(void) Con_Printf ("Downloading %s to %s\n", name, host_client->name); } +void SV_StopDownload_f(void) +{ + //this doesn't mean the download failed or was canceled. + if (host_client->download) + { + VFS_CLOSE (host_client->download); + host_client->download = NULL; + } + else + Con_Printf ("But you're not downloading anything\n"); + + host_client->downloadstarted = false; +} + //============================================================================= @@ -2312,17 +2370,34 @@ void SV_Pings_f (void) return; } - for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) + if (ISNQCLIENT(host_client)) { - if (client->state != cs_spawned) - continue; + char *s; + ClientReliableWrite_Begin(host_client, svc_stufftext, 15+10*MAX_CLIENTS); + ClientReliableWrite_SZ(host_client, "pingplreport", 12); + for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) + { + s = va(" %i %i", SV_CalcPing(client), client->lossage); + ClientReliableWrite_SZ(host_client, s, strlen(s)); + } + ClientReliableWrite_Byte (host_client, '\n'); + ClientReliableWrite_Byte (host_client, '\0'); - ClientReliableWrite_Begin (host_client, svc_updateping, 4); - ClientReliableWrite_Byte (host_client, j); - ClientReliableWrite_Short (host_client, SV_CalcPing(client)); - ClientReliableWrite_Begin (host_client, svc_updatepl, 4); - ClientReliableWrite_Byte (host_client, j); - ClientReliableWrite_Byte (host_client, client->lossage); + } + else + { + for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) + { + if (client->state != cs_spawned) + continue; + + ClientReliableWrite_Begin (host_client, svc_updateping, 4); + ClientReliableWrite_Byte (host_client, j); + ClientReliableWrite_Short (host_client, SV_CalcPing(client)); + ClientReliableWrite_Begin (host_client, svc_updatepl, 4); + ClientReliableWrite_Byte (host_client, j); + ClientReliableWrite_Byte (host_client, client->lossage); + } } } @@ -3216,17 +3291,16 @@ void Cmd_Observe_f (void) void SV_EnableClientsCSQC(void) { #ifdef PEXT_CSQC - if (host_client->fteprotocolextensions & PEXT_CSQC) + if (host_client->fteprotocolextensions & PEXT_CSQC || atoi(Cmd_Argv(1))) host_client->csqcactive = true; else - Con_DPrintf("CSQC enabled without protocol extensions\n"); + Con_Printf("CSQC entities not enabled - no support from network protocol\n"); #endif } void SV_DisableClientsCSQC(void) { #ifdef PEXT_CSQC - if (host_client->fteprotocolextensions & PEXT_CSQC) - host_client->csqcactive = false; + host_client->csqcactive = false; #endif } @@ -3291,7 +3365,7 @@ ucmd_t ucmds[] = {"notarget", Cmd_Notarget_f}, {"setpos", Cmd_SetPos_f}, -// {"stopdownload", SV_StopDownload_f}, + {"stopdownload", SV_StopDownload_f}, {"demolist", SV_MVDList_f}, {"demoinfo", SV_MVDInfo_f}, @@ -3811,6 +3885,8 @@ void SVNQ_Ping_f(void) ucmd_t nqucmds[] = { + {"new", SVNQ_New_f, true}, + {"status", NULL}, {"god", Cmd_God_f}, @@ -3818,6 +3894,7 @@ ucmd_t nqucmds[] = {"notarget", Cmd_Notarget_f}, {"fly", NULL}, {"noclip", Cmd_Noclip_f}, + {"pings", SV_Pings_f}, {"name", SVNQ_NQInfo_f}, @@ -3836,7 +3913,7 @@ ucmd_t nqucmds[] = {"vote", SV_Vote_f}, {"download", SV_BeginDownload_f}, - {"sv_startdownload", SVDP_ForceDownloadChunk_f}, + {"sv_startdownload", SVDP_StartDownload_f}, {"setinfo", SV_SetInfo_f}, {"playermodel", NULL}, @@ -5195,7 +5272,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl) // calc ping time frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; - frame->ping_time = 999; + frame->ping_time = -1; // make sure the reply sequence number matches the incoming // sequence number