From 8c02fb26b3a88683e86ac443868b7920e1bfc804 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 25 Mar 2018 09:36:14 +0000 Subject: [PATCH] removed old scr_chatmode splitscreen can now properly be configured via build configs, and potentially more than just 4 seats. fix splitscreen and enemycolour forcing. forcing now works, but only when all seats are on/spectating the same team. fix demo playback issue with http urls with webgl that don't allow streaming. srgb fixes for the scoreboard. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5229 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cam.c | 21 +++- engine/client/cl_demo.c | 6 +- engine/client/cl_main.c | 76 +++++++----- engine/client/cl_parse.c | 50 +++++--- engine/client/cl_plugin.inc | 9 +- engine/client/cl_screen.c | 4 +- engine/client/client.h | 5 +- engine/client/image.c | 3 + engine/client/m_mp3.c | 2 + engine/client/m_multi.c | 24 +++- engine/client/m_single.c | 2 + engine/client/menu.c | 12 ++ engine/client/net_master.c | 38 ++++-- engine/client/quakedef.h | 2 +- engine/client/r_2d.c | 11 +- engine/client/renderer.c | 2 - engine/client/sbar.c | 105 +---------------- engine/client/snd_dma.c | 2 + engine/client/view.c | 184 ++++++++++++++++-------------- engine/common/bothdefs.h | 10 +- engine/common/common.c | 1 + engine/common/config_fteqw.h | 3 +- engine/common/config_minimal.h | 17 +-- engine/common/config_nocompat.h | 2 +- engine/common/config_wastes.h | 1 + engine/common/console.h | 2 - engine/common/net_chan.c | 2 + engine/common/net_ssl_gnutls.c | 10 +- engine/common/net_wins.c | 2 +- engine/common/protocol.h | 3 +- engine/dotnet2005/ftequake.vcproj | 20 ++++ engine/gl/gl_screen.c | 2 - engine/gl/gl_videgl.c | 24 ++-- engine/gl/gl_videgl.h | 4 + engine/gl/gl_vidnt.c | 2 +- engine/server/server.h | 2 +- engine/server/sv_ccmds.c | 2 +- engine/server/sv_init.c | 2 + engine/server/sv_main.c | 43 +++++-- engine/server/sv_user.c | 30 ++--- 40 files changed, 410 insertions(+), 332 deletions(-) diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 3cbdc65b..f7e77986 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -538,7 +538,7 @@ qboolean Cam_DrawViewModel(playerview_t *pv) int Cam_TrackNum(playerview_t *pv) { - if (pv->spectator && pv->cam_state == CAM_EYECAM) + if (pv->spectator && CAM_ISLOCKED(pv)) return pv->cam_spec_track; return -1; } @@ -659,6 +659,9 @@ static qboolean Cam_IsVisible(vec3_t playerorigin, vec3_t vec) vec3_t v; float d; + VectorClear(pmove.player_mins); + VectorClear(pmove.player_maxs); + trace = Cam_DoTrace(playerorigin, vec); if (trace.fraction != 1 || /*trace.inopen ||*/ trace.inwater) return false; @@ -850,6 +853,15 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd) frame = &cl.inframes[cl.validsequence & UPDATE_MASK]; player = frame->playerstate + pv->cam_spec_track; + if (!cmd) + { //this is our fancy force-wallcam mode. + if (pv->cam_state != CAM_WALLCAM || !Cam_IsVisible(player->origin, pv->cam_desired_position)) + { + if (!InitFlyby(pv, pv->cam_desired_position, player->origin, player->viewangles, true)) + InitFlyby(pv, pv->cam_desired_position, player->origin, player->viewangles, false); + } + return; + } self = frame->playerstate + pv->playernum; if (!cl_chasecam.value && (pv->cam_state != CAM_WALLCAM || !Cam_IsVisible(player->origin, pv->cam_desired_position))) @@ -873,7 +885,7 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd) return; - if (cl_chasecam.value || scr_chatmode == 2) + if (cl_chasecam.value) { float *neworg; // float *newang; @@ -882,8 +894,7 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd) else neworg = player->origin; - if (scr_chatmode != 2) - pv->cam_lastviewtime = realtime; + pv->cam_lastviewtime = realtime; // VectorCopy(newang, pv->viewangles); if (memcmp(neworg, &self->origin, sizeof(vec3_t)) != 0) @@ -1145,7 +1156,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd) void Cam_Reset(void) { - int pnum; + unsigned int pnum; for (pnum = 0; pnum < MAX_SPLITS; pnum++) { playerview_t *pv = &cl.playerview[pnum]; diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 6defcf80..d8c62bde 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1958,19 +1958,19 @@ void CL_Record_f (void) MSG_WriteByte (&buf, svc_setview); MSG_WriteEntity (&buf, cl.playerview[0].viewentity); - MSG_WriteByte (&buf, svc_signonnum); + MSG_WriteByte (&buf, svcnq_signonnum); MSG_WriteByte (&buf, 1); CL_WriteRecordDemoMessage (&buf, seq++); seq = CL_Record_ParticlesStaticsBaselines(&buf, seq); //fixme: brushes... - MSG_WriteByte (&buf, svc_signonnum); + MSG_WriteByte (&buf, svcnq_signonnum); MSG_WriteByte (&buf, 2); CL_WriteRecordDemoMessage (&buf, seq++); //fixme: clients seq = CL_Record_Lightstyles(&buf, seq); //fixme: stats - MSG_WriteByte (&buf, svc_signonnum); + MSG_WriteByte (&buf, svcnq_signonnum); MSG_WriteByte (&buf, 3); CL_WriteRecordDemoMessage (&buf, seq++); break; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 8c3f9b2c..20f1389a 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -4763,9 +4763,9 @@ qboolean Host_BeginFileDownload(struct dl_download *dl, char *mimetype) if (!(f->flags & HRF_FILETYPES)) { if (mimetype) - Con_Printf("mime type \"%s\" and file extension of \"%s\" not recognised\n", mimetype, f->fname); + Con_Printf("mime type \"%s\" nor file extension of \"%s\" not known\n", mimetype, f->fname); else - Con_Printf("file extension of \"%s\" not recognised\n", f->fname); + Con_Printf("file extension of \"%s\" not known\n", f->fname); //file type not guessable from extension either. f->flags |= HRF_ABORT; Host_DoRunFile(f); @@ -4891,33 +4891,33 @@ done: return; } - if (!(f->flags & HRF_FILETYPES)) - { #ifdef WEBCLIENT - if (isurl(f->fname) && !f->srcfile) + if (isurl(f->fname) && !f->srcfile) + { + if (!(f->flags & HRF_OPENED)) { - if (!(f->flags & HRF_OPENED)) + struct dl_download *dl; + f->flags |= HRF_OPENED; + dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded); + if (dl) { - struct dl_download *dl; - f->flags |= HRF_OPENED; - dl = HTTP_CL_Get(f->fname, NULL, Host_RunFileDownloaded); - if (dl) - { - f->flags |= HRF_DOWNLOADED; - dl->notifystarted = Host_BeginFileDownload; - dl->user_ctx = f; + f->flags |= HRF_DOWNLOADED; + dl->notifystarted = Host_BeginFileDownload; + dl->user_ctx = f; - if (!(f->flags & HRF_WAITING)) - { - f->flags |= HRF_WAITING; - waitingformanifest++; - } - return; + if (!(f->flags & HRF_WAITING)) + { + f->flags |= HRF_WAITING; + waitingformanifest++; } + return; } } + } #endif + if (!(f->flags & HRF_FILETYPES)) + { f->flags |= Host_GuessFileType(NULL, f->fname); //if we still don't know what it is, give up. @@ -4939,10 +4939,29 @@ done: if (f->flags & HRF_DEMO) { - //play directly via system path, no prompts needed - FS_FixupGamedirForExternalFile(f->fname, loadcommand, sizeof(loadcommand)); - Cbuf_AddText(va("playdemo \"%s\"\n", loadcommand), RESTRICT_LOCAL); - + if (f->srcfile) + { + VFS_SEEK(f->srcfile, 0); + if (f->flags & HRF_DEMO_QWD) + CL_PlayDemoStream(f->srcfile, f->fname, true, DPB_QUAKEWORLD, 0); +#ifdef Q2CLIENT + else if (f->flags & HRF_DEMO_DM2) + CL_PlayDemoStream(f->srcfile, f->fname, true, DPB_QUAKE2, 0); +#endif +#ifdef NQPROT + else if (f->flags & HRF_DEMO_DEM) + CL_PlayDemoStream(f->srcfile, f->fname, true, DPB_NETQUAKE, 0); +#endif + else //if (f->flags & HRF_DEMO_MVD) + CL_PlayDemoStream(f->srcfile, f->fname, true, DPB_MVD, 0); + f->srcfile = NULL; + } + else + { + //play directly via system path, no prompts needed + FS_FixupGamedirForExternalFile(f->fname, loadcommand, sizeof(loadcommand)); + Cbuf_AddText(va("playdemo \"%s\"\n", loadcommand), RESTRICT_LOCAL); + } goto done; } else if (f->flags & HRF_BSP) @@ -5206,7 +5225,7 @@ qboolean Host_RunFile(const char *fname, int nlen, vfsfile_t *file) } else #elif !defined(FTE_TARGET_WEB) - //unix file urls are fairly consistant. + //unix file urls are fairly consistant - must be an absolute path. if (nlen >= 8 && !strncmp(fname, "file:///", 8)) { fname += 7; @@ -5624,12 +5643,7 @@ double Host_Frame (double time) if (SCR_UpdateScreen && !vid.isminimized) { - extern cvar_t scr_chatmodecvar, r_stereo_method; - - if (scr_chatmodecvar.ival && cl.intermissionmode == IM_NONE) - scr_chatmode = (cl.playerview[0].spectator&&cl.splitclients<2&&cls.state == ca_active)?2:1; - else - scr_chatmode = 0; + extern cvar_t r_stereo_method; r_refdef.stereomethod = r_stereo_method.ival; #ifdef FTE_TARGET_WEB diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 39e50c3f..e26d561a 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -3166,7 +3166,7 @@ static void CLQW_ParseServerData (void) } /*parsing here is slightly different to allow us 255 max players instead of 127*/ - cl.splitclients = MSG_ReadByte(); + cl.splitclients = (qbyte)MSG_ReadByte(); if (cl.splitclients & 128) { // spec = true; @@ -3179,7 +3179,7 @@ static void CLQW_ParseServerData (void) cl.playerview[pnum].spectator = true; if (cls.z_ext & Z_EXT_VIEWHEIGHT) cl.playerview[pnum].viewheight = 0; - cl.playerview[pnum].playernum = MSG_ReadByte(); + cl.playerview[pnum].playernum = (qbyte)MSG_ReadByte(); if (cl.playerview[pnum].playernum >= cl.allocated_client_slots) Host_EndGame("unsupported local player slot\n"); cl.playerview[pnum].viewentity = cl.playerview[pnum].playernum+1; @@ -4921,6 +4921,13 @@ static int QDECL CLQ2_EnumeratedSkin(const char *name, qofs_t size, time_t mtime return true; } +//returns the player if they're not spectating. +static int CL_TryTrackNum(playerview_t *pv) +{ + if (pv->spectator && pv->cam_state != CAM_FREECAM && pv->cam_spec_track >= 0) + return pv->cam_spec_track; + return pv->playernum; +} /* ===================== CL_NewTranslation @@ -4930,6 +4937,7 @@ void CL_NewTranslation (int slot) { int top, bottom; int local; + qboolean mayforce; char *s; player_info_t *player; @@ -4974,6 +4982,24 @@ void CL_NewTranslation (int slot) return; } + mayforce = !(cl.fpd & FPD_NO_FORCE_COLOR); +#if MAX_SPLITS > 1 + if (mayforce && cl.splitclients > 1 && cl.teamplay) + { //if we're using splitscreen, only allow team/enemy forcing if all split clients are on the same team + char *needteam; + int i; + needteam = cl.players[CL_TryTrackNum(&cl.playerview[0])].team; + for (i = 1; i < cl.splitclients; i++) + { + if (strcmp(needteam, cl.players[CL_TryTrackNum(&cl.playerview[i])].team)) + { + mayforce = false; + break; + } + } + } +#endif + s = Skin_FindName (player); COM_StripExtension(s, s, MAX_QPATH); if (player->qwskin && !stricmp(s, player->qwskin->name)) @@ -4981,20 +5007,12 @@ void CL_NewTranslation (int slot) player->skinid = 0; player->model = NULL; - - top = player->rtopcolor; bottom = player->rbottomcolor; - if (cl.splitclients < 2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. + + if (mayforce) { - if (cl.teamplay && cl.playerview[0].spectator) - { - local = Cam_TrackNum(&cl.playerview[0]); - if (local < 0) - local = cl.playerview[0].playernum; - } - else - local = cl.playerview[0].playernum; + local = CL_TryTrackNum(&cl.playerview[0]); if ((cl.teamplay || cls.protocol == CP_NETQUAKE) && !strcmp(player->team, cl.players[local].team)) { if (cl_teamtopcolor != ~0) @@ -6676,9 +6694,9 @@ void CLQW_ParseServerMessage (void) Cbuf_Execute (); // make sure any stuffed commands are done CLQW_ParseServerData (); break; - case svc_signonnum: + case svcfte_splitscreenconfig: cl.splitclients = MSG_ReadByte(); - for (i = 0; i < cl.splitclients && i < 4; i++) + for (i = 0; i < cl.splitclients && i < MAX_SPLITS; i++) { cl.playerview[i].playernum = MSG_ReadByte(); cl.playerview[i].viewentity = cl.playerview[i].playernum+1; @@ -7688,7 +7706,7 @@ void CLNQ_ParseServerMessage (void) cl.playerview[destsplit].viewentity = i; break; - case svc_signonnum: + case svcnq_signonnum: i = MSG_ReadByte (); if (i <= cls.signon) diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index ecbd35a7..6a23f52d 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -527,7 +527,7 @@ static qintptr_t VARGS Plug_GetPlayerInfo(void *offset, quintptr_t mask, const q { if (i < 0) { - if (i >= -MAX_SPLITS) + if (i >= -(int)MAX_SPLITS) i = cl.playerview[-i-1].playernum; if (i < 0) { @@ -1244,8 +1244,11 @@ qintptr_t VARGS Plug_Mod_GetPluginModelFuncs(void *offset, quintptr_t mask, cons GenMatrixPosQuat4Scale, COM_StripExtension, Alias_ForceConvertBoneData, - - Terr_GetTerrainFuncs +#ifdef TERRAIN + Terr_GetTerrainFuncs, +#else + NULL, +#endif }; if (VM_LONG(arg[0]) >= sizeof(funcs)) return (qintptr_t)&funcs; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index a54a5769..5ff00e05 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -175,8 +175,6 @@ console is: -int scr_chatmode; -extern cvar_t scr_chatmodecvar; float mousecursor_x, mousecursor_y; @@ -2230,7 +2228,7 @@ void SCR_SetUpToDrawConsole (void) else scr_conlines = 0; } - else if ((Key_Dest_Has(kdm_console) || scr_chatmode)) + else if (Key_Dest_Has(kdm_console)) { //go half-screen if we're meant to have the console visible scr_conlines = vid.height*scr_consize.value; // half screen diff --git a/engine/client/client.h b/engine/client/client.h index 64be8f41..da2b5e96 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -697,7 +697,6 @@ struct playerview_s vec3_t cam_desired_position; // where the camera wants to be int cam_oldbuttons; // - vec3_t cam_viewangles; // double cam_lastviewtime; // timer for wallcam float cam_reautotrack; // timer to throttle tracking changes. int cam_spec_track; // player# of who we are tracking / want to track / might want to track @@ -799,9 +798,9 @@ typedef struct lerpents_t lerpplayers[MAX_CLIENTS]; //when running splitscreen, we have multiple viewports all active at once - int splitclients; //we are running this many clients split screen. + unsigned int splitclients; //we are running this many clients split screen. playerview_t playerview[MAX_SPLITS]; - int defaultnetsplit;//which multiview splitscreen to parse the message for (set by mvd playback code) + unsigned int defaultnetsplit;//which multiview splitscreen to parse the message for (set by mvd playback code) // localized movement vars float bunnyspeedcap; diff --git a/engine/client/image.c b/engine/client/image.c index 6d3bdf27..16d388ab 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -2988,7 +2988,10 @@ static struct pendingtextureinfo *Image_ReadKTXFile(unsigned int flags, char *fn mips->type = PTI_2D_ARRAY; } else + { + header->pixeldepth = 1; mips->type = PTI_2D; + } } mips->extrafree = filedata; mips->encoding = encoding; diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index af31e2ff..84ec55dc 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -2542,7 +2542,9 @@ qboolean Media_PlayFilm(char *name, qboolean enqueue) if (videoshader) { +#ifdef HAVE_CDPLAYER CDAudio_Stop(); +#endif SCR_EndLoadingPlaque(); if (Key_Dest_Has(kdm_emenu)) diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 540b8583..4e4523aa 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -995,14 +995,32 @@ void M_Menu_Teamplay_Items_Status_Location_Misc_f (void) void M_Menu_Network_f (void) { +#if MAX_SPLITS > 1 + extern cvar_t cl_splitscreen; static const char *splitopts[] = { "Disabled", "2 Screens", +#if MAX_SPLITS > 2 "3 Screens", +#endif +#if MAX_SPLITS > 3 "4 Screens", +#endif NULL }; - static const char *splitvalues[] = {"0", "1", "2", "3", NULL}; + static const char *splitvalues[] = + { + "0", + "1", +#if MAX_SPLITS > 2 + "2", +#endif +#if MAX_SPLITS > 3 + "3", +#endif + NULL + }; +#endif static const char *smoothingopts[] = { "Lower Latency", "Smoother", @@ -1011,7 +1029,7 @@ void M_Menu_Network_f (void) }; static const char *smoothingvalues[] = {"0", "1", "2", NULL}; extern cvar_t cl_download_csprogs, cl_download_redirection, requiredownloads, cl_solid_players; - extern cvar_t cl_splitscreen, cl_predict_players, cl_predict_smooth, cl_predict_extrapolate; + extern cvar_t cl_predict_players, cl_predict_smooth, cl_predict_extrapolate; menu_t *menu; static menuresel_t resel; int y; @@ -1031,7 +1049,9 @@ void M_Menu_Network_f (void) MB_CHECKBOXCVARTIP("Extrapolate Prediction", cl_predict_extrapolate, 0, "Extrapolate local player movement beyond the frames already sent to the server"), MB_CHECKBOXCVARTIP("Predict Other Players", cl_predict_players, 0, "Toggle player prediction"), MB_CHECKBOXCVARTIP("Solid Players", cl_solid_players, 0, "When running/clipping into other players, ON make it appear they are solid, OFF will make it appear like running into a marshmellon."), +#if MAX_SPLITS > 1 MB_COMBOCVAR("Split-screen", cl_splitscreen, splitopts, splitvalues, "Enables split screen with a number of clients. This feature requires server support."), +#endif MB_END() }; menu = M_Options_Title(&y, 0); diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 90efd483..05e88930 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -532,10 +532,12 @@ void M_Menu_SinglePlayer_f (void) b->common.width = width; b->common.height = 20; +#if MAX_SPLITS > 1 b = (menubutton_t*)MC_AddCvarCombo(menu, 72, 72+width/2, 92, "", &cl_splitscreen, opts, vals); MC_AddWhiteText(menu, 72, 0, 92, "^aSplitscreen", false); b->common.height = 20; b->common.width = width; +#endif menu->cursoritem = (menuoption_t*)MC_AddCursor(menu, &resel, 54, 32); } diff --git a/engine/client/menu.c b/engine/client/menu.c index 407d1a5f..523abe42 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -505,7 +505,9 @@ void M_Menu_Keys_f (void) int y; menu_t *menu; vfsfile_t *bindslist; +#if MAX_SPLITS > 1 extern cvar_t cl_splitscreen; +#endif Key_Dest_Add(kdm_emenu); @@ -533,6 +535,7 @@ void M_Menu_Keys_f (void) break; } +#if MAX_SPLITS > 1 if (cl.splitclients || cl_splitscreen.ival || cl_forceseat.ival) { static char *texts[MAX_SPLITS+2] = @@ -540,8 +543,12 @@ void M_Menu_Keys_f (void) "Depends on device", "Player 1", "Player 2", +#if MAX_SPLITS >= 3 "Player 3", +#endif +#if MAX_SPLITS >= 4 "Player 4", +#endif NULL }; static char *values[MAX_SPLITS+1] = @@ -549,12 +556,17 @@ void M_Menu_Keys_f (void) "0", "1", "2", +#if MAX_SPLITS >= 3 "3", +#endif +#if MAX_SPLITS >= 4 "4" +#endif }; MC_AddCvarCombo(menu, 16, 170, y, "Force client", &cl_forceseat, (const char **)texts, (const char **)values); y+=8; } +#endif bindslist = FS_OpenVFS("bindlist.lst", "rb", FS_GAME); if (bindslist) diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 499ec1f6..cae615fd 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -122,9 +122,9 @@ net_masterlist_t net_masterlist[] = { //engine-specified/maintained master lists (so users can be lazy and update the engine without having to rewrite all their configs). {MP_QUAKEWORLD, CVARFC("net_qwmasterextra1", "qwmaster.ocrana.de:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "Ocrana(2nd)"}, //german. admin unknown {MP_QUAKEWORLD, CVARFC("net_qwmasterextra2", ""/*"masterserver.exhale.de:27000" seems dead*/, CVAR_NOSAVE, Net_Masterlist_Callback)}, //german. admin unknown - {MP_QUAKEWORLD, CVARFC("net_qwmasterextra3", "asgaard.morphos-team.net:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "Germany, admin: bigfoot"}, +// {MP_QUAKEWORLD, CVARFC("net_qwmasterextra3", "asgaard.morphos-team.net:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "Germany, admin: bigfoot"}, {MP_QUAKEWORLD, CVARFC("net_qwmasterextra4", "master.quakeservers.net:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "Germany, admin: raz0?"}, - {MP_QUAKEWORLD, CVARFC("net_qwmasterextra5", "qwmaster.fodquake.net:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "admin: bigfoot"}, +// {MP_QUAKEWORLD, CVARFC("net_qwmasterextra5", "qwmaster.fodquake.net:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "admin: bigfoot"}, // {MP_QUAKEWORLD, CVARFC("net_qwmasterextraHistoric", "satan.idsoftware.com:27000", CVAR_NOSAVE, Net_Masterlist_Callback), "Official id Master"}, // {MP_QUAKEWORLD, CVARFC("net_qwmasterextraHistoric", "satan.idsoftware.com:27002", CVAR_NOSAVE, Net_Masterlist_Callback), "Official id Master For CTF Servers"}, // {MP_QUAKEWORLD, CVARFC("net_qwmasterextraHistoric", "satan.idsoftware.com:27003", CVAR_NOSAVE, Net_Masterlist_Callback), "Official id Master For TeamFortress Servers"}, @@ -890,8 +890,8 @@ qboolean Master_PassesMasks(serverinfo_t *a) // qboolean enabled; //always filter out dead unresponsive servers. - if (!a->ping) - return false; +// if (!(a->status & 1)) +// return false; /* switch(a->special & SS_PROTOCOLMASK) { @@ -1813,7 +1813,7 @@ qboolean NET_SendPollPacket(int len, void *data, netadr_t to) pollsocketsBCast[FIRSTIPXSOCKET+lastpollsockIPX] = false; } if (pollsocketsList[FIRSTIPXSOCKET+lastpollsockIPX]==INVALID_SOCKET) - return; //bother + return true; //bother bcast = !memcmp(to.address.ipx, "\0\0\0\0\xff\xff\xff\xff\xff\xff", sizeof(to.address.ipx)); if (pollsocketsBCast[FIRSTIPXSOCKET+lastpollsockIPX] != bcast) @@ -2287,19 +2287,27 @@ void MasterInfo_ProcessHTTP(struct dl_download *dl) info->sends = 1; info->special = 0; - if (protocoltype == MP_DPMASTER) + if (protocoltype == MP_QUAKEWORLD) + info->special |= SS_QUAKEWORLD; + else if (protocoltype == MP_DPMASTER) info->special |= SS_DARKPLACES; +#if defined(Q2CLIENT) || defined(Q2SERVER) else if (protocoltype == MP_QUAKE2) info->special |= SS_QUAKE2; +#endif +#if defined(Q3CLIENT) || defined(Q3SERVER) else if (protocoltype == MP_QUAKE3) info->special |= SS_QUAKE3; +#endif +#ifdef NQPROT else if (protocoltype == MP_NETQUAKE) info->special |= SS_NETQUAKE; +#endif info->refreshtime = 0; info->ping = 0xffff; - snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adrbuf, sizeof(adrbuf), &info->adr)); + snprintf(info->name, sizeof(info->name), "%s h", NET_AdrToString(adrbuf, sizeof(adrbuf), &info->adr)); info->next = firstserver; firstserver = info; @@ -2398,6 +2406,7 @@ char *jsonnode(int level, char *node) else { info = Z_Malloc(sizeof(serverinfo_t)); + info->ping = 0xffff; info->adr = adr; info->sends = 1; info->special = flags; @@ -2405,7 +2414,7 @@ char *jsonnode(int level, char *node) info->players = cp; info->maxplayers = mp; - snprintf(info->name, sizeof(info->name), "%s", *servername?servername:NET_AdrToString(servername, sizeof(servername), &info->adr)); + snprintf(info->name, sizeof(info->name), "%s j", *servername?servername:NET_AdrToString(servername, sizeof(servername), &info->adr)); info->next = firstserver; firstserver = info; @@ -2963,7 +2972,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor info->adr = net_from; - snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adr, sizeof(adr), &info->adr)); + snprintf(info->name, sizeof(info->name), "%s ?", NET_AdrToString(adr, sizeof(adr), &info->adr)); info->next = firstserver; firstserver = info; @@ -3036,10 +3045,11 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor peer->peer = Z_Malloc(sizeof(serverinfo_t)); peer->peer->adr = pa; peer->peer->sends = 1; - peer->peer->special = 0; + peer->peer->special = SS_QUAKEWORLD; peer->peer->refreshtime = 0; peer->peer->ping = 0xffff; peer->peer->next = firstserver; + snprintf(peer->peer->name, sizeof(peer->peer->name), "%s p", NET_AdrToString(adr, sizeof(adr), &pa)); firstserver = peer->peer; } peer++; @@ -3359,6 +3369,8 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) char adr[MAX_ADR_SIZE]; int i; + char madr[MAX_ADR_SIZE]; + switch(adrtype) { case NA_IP: @@ -3374,6 +3386,8 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) return; } + NET_AdrToString(madr, sizeof(madr), &net_from); + MSG_ReadByte (); //should be \n last = firstserver; @@ -3412,6 +3426,7 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) default: break; } + info->ping = 0xffff; p1 = MSG_ReadByte(); p2 = MSG_ReadByte(); @@ -3431,10 +3446,11 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) else { info->sends = 1; + info->special = type; info->refreshtime = 0; - snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adr, sizeof(adr), &info->adr)); + snprintf(info->name, sizeof(info->name), "%s (via %s)", NET_AdrToString(adr, sizeof(adr), &info->adr), madr); info->next = last; last = info; diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index 3decbeb8..e23d01b1 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -347,7 +347,7 @@ qboolean COM_HasWork(void); void COM_WorkerFullSync(void); void COM_DestroyWorkerThread(void); void COM_WorkerPartialSync(void *priorityctx, int *address, int value); -void *com_resourcemutex; //random mutex to simplify resource creation type stuff. +extern void *com_resourcemutex; //random mutex to simplify resource creation type stuff. void COM_WorkerAbort(char *message); //calls sys_error on the main thread, if running on a worker. #ifdef _DEBUG void COM_AssertMainThread(const char *msg); diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 93930572..f2613575 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -578,9 +578,9 @@ void R2D_ImageColours(float r, float g, float b, float a) } void R2D_ImagePaletteColour(unsigned int i, float a) { - draw_active_colour[0] = host_basepal[i*3+0]/255.0; - draw_active_colour[1] = host_basepal[i*3+1]/255.0; - draw_active_colour[2] = host_basepal[i*3+2]/255.0; + draw_active_colour[0] = SRGBf(host_basepal[i*3+0]/255.0); + draw_active_colour[1] = SRGBf(host_basepal[i*3+1]/255.0); + draw_active_colour[2] = SRGBf(host_basepal[i*3+2]/255.0); draw_active_colour[3] = a; Font_InvalidateColour(draw_active_colour); @@ -888,11 +888,6 @@ void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque) a = scr_conalpha.value; } - if (scr_chatmode == 2) - { - h>>=1; - w>>=1; - } if (R_GetShaderSizes(conback, NULL, NULL, false) <= 0) { R2D_ImageColours(0, 0, 0, a); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index d01795ac..acc85e4c 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -222,7 +222,6 @@ cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1", cvar_t scr_centersbar = CVAR ("scr_centersbar", "2"); cvar_t scr_centertime = CVAR ("scr_centertime", "2"); cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always.\n"); -cvar_t scr_chatmodecvar = CVAR ("scr_chatmode", "0"); cvar_t scr_conalpha = CVARC ("scr_conalpha", "0.7", Cvar_Limiter_ZeroToOne_Callback); cvar_t scr_consize = CVAR ("scr_consize", "0.5"); @@ -890,7 +889,6 @@ void Renderer_Init(void) Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); Cvar_Register(&scr_fov_viewmodel, SCREENOPTIONS); -// Cvar_Register(&scr_chatmodecvar, SCREENOPTIONS); Cvar_Register (&scr_sshot_type, SCREENOPTIONS); Cvar_Register (&scr_sshot_compression, SCREENOPTIONS); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index b7e7adc5..ec3da18b 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -1266,7 +1266,7 @@ void Sbar_FillPC (float x, float y, float w, float h, unsigned int pcolour) { if (pcolour >= 16) { - R2D_ImageColours (((pcolour&0xff0000)>>16)/255.0f, ((pcolour&0xff00)>>8)/255.0f, (pcolour&0xff)/255.0f, 1.0); + R2D_ImageColours (SRGBA(((pcolour&0xff0000)>>16)/255.0f, ((pcolour&0xff00)>>8)/255.0f, (pcolour&0xff)/255.0f, 1.0)); R2D_FillBlock (x, y, w, h); } else @@ -1279,7 +1279,7 @@ static void Sbar_FillPCDark (float x, float y, float w, float h, unsigned int pc { if (pcolour >= 16) { - R2D_ImageColours (((pcolour&0xff0000)>>16)/1024.0f, ((pcolour&0xff00)>>8)/1024.0f, (pcolour&0xff)/1024.0f, alpha); + R2D_ImageColours (SRGBA(((pcolour&0xff0000)>>16)/1024.0f, ((pcolour&0xff00)>>8)/1024.0f, (pcolour&0xff)/1024.0f, alpha)); R2D_FillBlock (x, y, w, h); } else @@ -2962,13 +2962,6 @@ void Sbar_Draw (playerview_t *pv) else Sbar_Voice(16); - { - extern int scr_chatmode; - if (scr_chatmode) - Sbar_ChatModeOverlay(pv); - } - - Sbar_DrawUPS (pv); SCR_DrawClock(); SCR_DrawGameClock(); @@ -3598,100 +3591,6 @@ if (showcolumns & (1< 2 && cls.protocol == CP_QUAKEWORLD && cls.demoplayback != DPB_EZTV) - { - cl.last_ping_request = realtime; - CL_SendClientCommand(true, "pings"); - } - -// scores - Sbar_SortFrags (true, false); - - if (Cam_TrackNum(pv)>=0) - Q_strncpyz (team, cl.players[Cam_TrackNum(pv)].team, sizeof(team)); - else if (pv->playernum>=0 && pv->playernumplayernum].team, sizeof(team)); - else - *team = '\0'; - -// draw the text - l = scoreboardlines; - - if (start) - y = start; - else - y = 24; - y = vid.height/2; - - x = 4; - Draw_FunString ( x , y, "name"); - y += 8; - Draw_FunString ( x , y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i=0 ; iname[0]) - continue; - - // draw background - top = Sbar_TopColour(s); - bottom = Sbar_BottomColour(s); - - if (largegame) - Sbar_FillPC ( x, y+1, 8*4, 3, top); - else - Sbar_FillPC ( x, y, 8*4, 4, top); - Sbar_FillPC ( x, y+4, 8*4, 4, bottom); -/* - if (cl.spectator && k == Cam_TrackNum(pv)) - { - Draw_Character ( x, y, 16); - Draw_Character ( x+8*3, y, 17); - } - else if (!cl.spectator && k == pv->cl.playernum) - { - Draw_Character ( x, y, 16); - Draw_Character ( x+8*3, y, 17); - } - else if (cl.teamplay) - { - if (!stricmp(s->team, team)) - { - Draw_Character ( x, y, '['); - Draw_Character ( x+8*3, y, ']'); - } - } -*/ - // draw name - if (cl.teamplay) - Draw_FunString (x+8*4, y, s->name); - else - Draw_FunString (x+8*4, y, s->name); - - y += skip; - } - - if (y >= vid.height-10) // we ran over the screen size, squish - largegame = true; -} - /* ================== Sbar_MiniDeathmatchOverlay diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index a05d0221..edf787a5 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -2697,6 +2697,7 @@ static void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch) seat = 0; VectorSubtract(ch->origin, listener[seat].origin, world_vec); dist = DotProduct(world_vec,world_vec); +#if MAX_SPLITS > 1 for (i = 1; i < cl.splitclients; i++) { VectorSubtract(ch->origin, listener[i].origin, world_vec); @@ -2707,6 +2708,7 @@ static void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch) seat = i; } } +#endif } else { diff --git a/engine/client/view.c b/engine/client/view.c index 68cb1e20..6032d571 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1300,7 +1300,7 @@ void V_ApplyRefdef (void) else sb_lines = 24+16+8; - if (scr_viewsize.value >= 100.0 || scr_chatmode) + if (scr_viewsize.value >= 100.0) { full = true; size = 100.0; @@ -1344,14 +1344,6 @@ void V_ApplyRefdef (void) else r_refdef.vrect.y = (h - r_refdef.vrect.height)/2; - if (scr_chatmode) - { - if (scr_chatmode != 2) - r_refdef.vrect.height = r_refdef.vrect.y=r_refdef.grect.height/2; - r_refdef.vrect.width = r_refdef.vrect.x=r_refdef.grect.width/2; - if (r_refdef.vrect.width<320 || r_refdef.vrect.height<200) //disable hud if too small - sb_lines=0; - } r_refdef.vrect.x += r_refdef.grect.x; r_refdef.vrect.y += r_refdef.grect.y; #endif @@ -1642,61 +1634,24 @@ entity_t *CL_EntityNum(int num) #endif #endif -float CalcFov (float fov_x, float width, float height); -static void SCR_VRectForPlayer(vrect_t *vrect, int pnum, unsigned maxseats) +static qboolean SCR_VRectForPlayer(vrect_t *vrect, int pnum, unsigned maxseats) { -#if MAX_SPLITS > 4 -#pragma warning "Please change this function to cope with the new MAX_SPLITS value" -#endif - switch(maxseats) + int w = 1, h = 1; + while (w*h < maxseats) { - case 1: - vrect->width = vid.fbvwidth; - vrect->height = vid.fbvheight; - vrect->x = 0; - vrect->y = 0; - - if (scr_chatmode == 2) - { - vrect->height/=2; - vrect->y += vrect->height; - } - break; - - case 2: //horizontal bands - case 3: -#ifdef GLQUAKE - if (qrenderer == QR_OPENGL && vid.rotpixelwidth > vid.rotpixelheight * 2 - && r_projection.ival == PROJ_PANORAMA /*panoramic view always stacks player views*/ - ) - { //over twice as wide as high, assume dual moniter, horizontal. - vrect->width = vid.fbvwidth/cl.splitclients; - vrect->height = vid.fbvheight; - vrect->x = 0 + vrect->width*pnum; - vrect->y = 0; - } + //spread them out so they're all fair. + //panorama always stacks vertically, using the full width, because we can. + if (vid.fbvwidth/(w*16.0) > vid.fbvheight/(h*10.0) && r_projection.ival != PROJ_PANORAMA) + w++; else -#endif - { - //stack them vertically - vrect->width = vid.fbvwidth; - vrect->height = vid.fbvheight/cl.splitclients; - vrect->x = 0; - vrect->y = 0 + vrect->height*pnum; - } - - break; - - case 4: //4 squares - vrect->width = vid.fbvwidth/2; - vrect->height = vid.fbvheight/2; - vrect->x = (pnum&1) * vrect->width; - vrect->y = (pnum&2)/2 * vrect->height; - break; - - default: - Sys_Error("cl.splitclients is invalid."); + h++; } + vrect->width = vid.fbvwidth/(float)w; + vrect->height = vid.fbvheight/(float)h; + vrect->x = (pnum%w) * vrect->width; + vrect->y = (pnum/w) * vrect->height; + + return pnum < w*h; } void Draw_ExpandedString(float x, float y, conchar_t *str); @@ -2159,23 +2114,8 @@ void V_RenderPlayerViews(playerview_t *pv) cl_numvisedicts = oldnuments; cl_numstris = oldstris; - if (scr_chatmode == 2) - { - vec3_t dir; - - r_refdef.vrect.y -= r_refdef.vrect.height; - r_secondaryview = 2; - - VectorSubtract(r_refdef.vieworg, pv->cam_desired_position, dir); - VectorAngles(dir, NULL, r_refdef.viewangles, false); - - - VectorCopy(pv->cam_desired_position, r_refdef.vieworg); - R_RenderView (); - } r_secondaryview = true; - #ifdef SIDEVIEWS /* //adjust main view height to strip off the rearviews at the top if (vsecwidth >= 1) @@ -2278,10 +2218,11 @@ void V_RenderPlayerViews(playerview_t *pv) r_refdef.externalview = false; } +#include "shader.h" void V_RenderView (void) { - int viewnum; - int maxviews = cl.splitclients; + int seatnum; + int maxseats = cl.splitclients; Surf_LessenStains(); @@ -2289,18 +2230,18 @@ void V_RenderView (void) return; if (cl.intermissionmode != IM_NONE) - maxviews = 1; + maxseats = 1; R_PushDlights (); r_secondaryview = 0; - for (viewnum = 0; viewnum < maxviews; viewnum++) + for (seatnum = 0; seatnum < cl.splitclients && seatnum < maxseats; seatnum++) { - V_ClearRefdef(&cl.playerview[viewnum]); - if (viewnum) + V_ClearRefdef(&cl.playerview[seatnum]); + if (seatnum) { //should be enough to just hack a few things. - V_EditExternalModels(cl.playerview[viewnum].viewentity, NULL, 0); + V_EditExternalModels(r_refdef.playerview->viewentity, NULL, 0); } else { @@ -2324,7 +2265,8 @@ void V_RenderView (void) } if (R2D_Flush) R2D_Flush(); - SCR_VRectForPlayer(&r_refdef.grect, viewnum, maxviews); + + SCR_VRectForPlayer(&r_refdef.grect, seatnum, maxseats); V_RenderPlayerViews(r_refdef.playerview); #ifdef PLUGINS @@ -2340,6 +2282,82 @@ void V_RenderView (void) SCR_TileClear (0); #endif } + if (seatnum > 1) + { + int extra = 0; + for (; ; seatnum++, extra++) + { + if (!SCR_VRectForPlayer(&r_refdef.grect, seatnum, maxseats)) + break; + + switch(extra) + { +#ifdef QUAKEHUD + case 0: //show a mini-console. + { + console_t *con = &con_main; + extern cvar_t gl_conback; + shader_t *conback; + if (*gl_conback.string && (conback = R_RegisterPic(gl_conback.string, NULL)) && R_GetShaderSizes(conback, NULL, NULL, true) > 0) + R2D_Image(r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height, 0, 0, 1, 1, conback); + else if ((conback = R_RegisterPic("gfx/conback.lmp", NULL)) && R_GetShaderSizes(conback, NULL, NULL, true) > 0) + R2D_Image(r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height, 0, 0, 1, 1, conback); + else + R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height); + if (!scr_conlines) + { + int gah; + Font_BeginString(font_console, 0, 0, &gah, &gah); + Con_DrawOneConsole(con, con->flags & CONF_KEYFOCUSED, font_console, r_refdef.grect.x+8, r_refdef.grect.y, r_refdef.grect.width-16, r_refdef.grect.height-Font_CharHeight(), 0); + } + } + break; + case 1: //show some scores, because we can. + { //FIXME: show ALL tracked players. + int tmp; + R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height); + r_refdef.playerview = &cl.playerview[0]; + tmp = r_refdef.playerview->sb_showscores; + r_refdef.playerview->sb_showscores = true; + Sbar_DrawScoreboard (r_refdef.playerview); + r_refdef.playerview->sb_showscores = tmp; + } + break; + case 2: + { + static playerview_t cam_view; + vec3_t dir; + int track = cl.playerview[0].cam_spec_track; + if (track < 0) + track = cl.playerview[0].playernum; + + if (cam_view.cam_state == CAM_FREECAM || cam_view.cam_spec_track != track) + cam_view.cam_state = CAM_PENDING; + cam_view.playernum = -1;//cl.playerview[0].playernum; + cam_view.cam_spec_track = track; + cam_view.viewentity = 0; + cam_view.nolocalplayer = true; + cam_view.spectator = true; + + Cam_Track(&cam_view, NULL); + + VectorSubtract(cl.playerview[0].simorg, cam_view.cam_desired_position, dir); + VectorAngles(dir, NULL, cam_view.simangles, false); + + VectorCopy(cam_view.cam_desired_position, cam_view.simorg); + + V_ClearRefdef(&cam_view); + V_EditExternalModels(0, NULL, 0); + V_RenderPlayerViews(r_refdef.playerview); + } + break; +#endif + default: //wow, loads. nothing to show though. + R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y, r_refdef.grect.width, r_refdef.grect.height); + break; + } + } + } r_refdef.playerview = NULL; } diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index ff5029f9..7f73cbd8 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -87,7 +87,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef HAVE_CONFIG_H #define CONFIG_FILE_NAME config.h #elif defined(NOLEGACY) - #define CONFIG_FILE_NAME config_nolegacy.h + #undef NOLEGACY + #define CONFIG_FILE_NAME config_nocompat.h #elif defined(MINIMAL) #define CONFIG_FILE_NAME config_minimal.h #else @@ -405,6 +406,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef AVAIL_XZDEC #undef AVAIL_GZDEC #endif +#if (defined(_MSC_VER) && (_MSC_VER < 1500)) || defined(FTE_SDL) + #undef AVAIL_WASAPI //wasapi is available in the vista sdk, while that's compatible with earlier versions, its not really expected until 2008 +#endif //include a file to update the various configurations for game-specific configs (hopefully just names) #ifdef BRANDING_INC @@ -1201,7 +1205,9 @@ STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255, // DP //split screen stuff -#define MAX_SPLITS 4 +#ifndef MAX_SPLITS +#define MAX_SPLITS 1u //disabled, but must be defined for sanities sake. +#endif diff --git a/engine/common/common.c b/engine/common/common.c index 443a92ca..8cef6239 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -5075,6 +5075,7 @@ cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSERVER, "C #define WORKERTHREADS 16 //max /*multithreading worker thread stuff*/ +void *com_resourcemutex; static int com_liveworkers[WG_COUNT]; static void *com_workercondition[WG_COUNT]; static volatile int com_workeracksequence; diff --git a/engine/common/config_fteqw.h b/engine/common/config_fteqw.h index 86c62049..3987fb8c 100644 --- a/engine/common/config_fteqw.h +++ b/engine/common/config_fteqw.h @@ -43,6 +43,7 @@ #define LOADERTHREAD //worker threads for loading misc stuff. falls back on main thread if not supported. #define AVAIL_DINPUT #define SIDEVIEWS 4 //enable secondary/reverse views. +#define MAX_SPLITS 4u #define TEXTEDITOR //my funky text editor! its awesome! #define PLUGINS //support for external plugins (like huds or fancy menus or whatever) #define USE_SQLITE //sql-database-as-file support @@ -63,7 +64,7 @@ #define RFBSPS //qfusion's bsp format / jk2o etc. #define TERRAIN //FTE's terrain, as well as .map support //#define DOOMWADS //map support, filesystem support is separate. -//#define MAP_PROC //doom3... +//#define MAP_PROC //doom3... //Model formats #define SPRMODELS //Quake's sprites diff --git a/engine/common/config_minimal.h b/engine/common/config_minimal.h index e15aa284..07e02de8 100644 --- a/engine/common/config_minimal.h +++ b/engine/common/config_minimal.h @@ -1,5 +1,7 @@ // Build-Config file for FTE's minimal builds. // to use: make FTE_CONFIG=minimal +// These builds are a compromise between true minimal and something that will actually work. +// As such we allow pk3s, md3s, pngs, and built-in menus, but that's about it. // Features should either be commented or not. If you change undefs to defines or vice versa then expect problems. // Later code will disable any features if they're not supported on the current platform, so don't worry about win/lin/mac/android/web/etc here - any such issues should be fixed elsewhere. @@ -27,7 +29,7 @@ //#undef D3D9QUAKE //#undef D3D11QUAKE //#undef VKQUAKE -//#undef HEADLESSQUAKE //no-op renderer... +#undef HEADLESSQUAKE //no-op renderer... //#undef WAYLANDQUAKE //linux only //Misc Renderer stuff @@ -43,17 +45,18 @@ #define LOADERTHREAD //worker threads for loading misc stuff. falls back on main thread if not supported. #define AVAIL_DINPUT //#define SIDEVIEWS 4 //enable secondary/reverse views. +//#define MAX_SPLITS 4u //#define TEXTEDITOR //my funky text editor! its awesome! //#define PLUGINS //support for external plugins (like huds or fancy menus or whatever) //#define USE_SQLITE //sql-database-as-file support //Filesystem formats -//#define PACKAGE_PK3 +#define PACKAGE_PK3 #define PACKAGE_Q1PAK //also q2 //#define PACKAGE_DOOMWAD //doom wad support (generates various file names, and adds support for doom's audio, sprites, etc) //#define AVAIL_XZDEC //.xz decompression //#define AVAIL_GZDEC //.gz decompression -//#define AVAIL_ZLIB //whether pk3s can be compressed or not. +#define AVAIL_ZLIB //whether pk3s can be compressed or not. //#define AVAIL_DZIP //.dzip support for smaller demos (which are actually more like pak files and can store ANY type of file) //Map formats @@ -63,15 +66,15 @@ //#define RFBSPS //qfusion's bsp format / jk2o etc. //#define TERRAIN //FTE's terrain, as well as .map support //#define DOOMWADS //map support, filesystem support is separate. -//#define MAP_PROC //doom3... +//#define MAP_PROC //doom3... //Model formats #define SPRMODELS //Quake's sprites //#define SP2MODELS //Quake2's models -#define DSPMODELS //Doom sprites! +//#define DSPMODELS //Doom sprites! #define MD1MODELS //Quake's models. //#define MD2MODELS //Quake2's models -//#define MD3MODELS //Quake3's models, also often used for q1 etc too. +#define MD3MODELS //Quake3's models, also often used for q1 etc too. //#define MD5MODELS //Doom3 models. //#define ZYMOTICMODELS //nexuiz uses these, for some reason. //#define DPMMODELS //these keep popping up, despite being a weak format. @@ -86,7 +89,7 @@ //#define IMAGEFMT_DDS //.dds files embed mipmaps and texture compression. faster to load. //#define IMAGEFMT_BLP //legacy crap #define PACKAGE_TEXWAD //quake's image wad support -//#define AVAIL_PNGLIB //.png image format support (read+screenshots) +#define AVAIL_PNGLIB //.png image format support (read+screenshots) //#define AVAIL_JPEGLIB //.jpeg image format support (read+screenshots) //#define AVAIL_FREETYPE //for truetype font rendering //#define DECOMPRESS_ETC2 //decompress etc2(core in gles3/gl4.3) if the graphics driver doesn't support it (eg d3d or crappy gpus with vulkan). diff --git a/engine/common/config_nocompat.h b/engine/common/config_nocompat.h index bd02e34a..0301f6b6 100644 --- a/engine/common/config_nocompat.h +++ b/engine/common/config_nocompat.h @@ -63,7 +63,7 @@ #define RFBSPS //qfusion's bsp format / jk2o etc. //#define TERRAIN //FTE's terrain, as well as .map support //#define DOOMWADS //map support, filesystem support is separate. -//#define MAP_PROC //doom3... +//#define MAP_PROC //doom3... //Model formats #define SPRMODELS //Quake's sprites diff --git a/engine/common/config_wastes.h b/engine/common/config_wastes.h index 6e32274d..df8af80d 100644 --- a/engine/common/config_wastes.h +++ b/engine/common/config_wastes.h @@ -132,6 +132,7 @@ #undef HAVE_CDPLAYER //includes cd playback. actual cds. named/numbered tracks are supported regardless (though you need to use the 'music' command to play them without this). #undef QTERM #undef SIDEVIEWS +#undef MAX_SPLITS #undef SUBSERVERS #undef SV_MASTER #undef HAVE_MIXER //openal only diff --git a/engine/common/console.h b/engine/common/console.h index 12c55ff5..1b9e2c5e 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -204,8 +204,6 @@ extern int edit_line; extern int key_linepos; extern int history_line; -extern int scr_chatmode; - //extern int con_totallines; extern qboolean con_initialized; extern qbyte *con_chars; diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 00796785..756b8373 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -153,7 +153,9 @@ unsigned int Net_PextMask(int maskset, qboolean fornq) #endif mask |= PEXT_SPAWNSTATIC2; mask |= PEXT_COLOURMOD; + #if MAX_SPLITS > 1 mask |= PEXT_SPLITSCREEN; + #endif mask |= PEXT_HEXEN2; mask |= PEXT_CUSTOMTEMPEFFECTS; mask |= PEXT_256PACKETENTITIES; diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c index 9f9d73bf..b712793f 100644 --- a/engine/common/net_ssl_gnutls.c +++ b/engine/common/net_ssl_gnutls.c @@ -966,14 +966,18 @@ qboolean SSL_InitGlobal(qboolean isserver) isserver = !!isserver; if (COM_CheckParm("-notls")) return false; +#ifdef LOADERTHREAD if (com_resourcemutex) Sys_LockMutex(com_resourcemutex); +#endif if (!initstatus[isserver]) { if (!Init_GNUTLS()) { +#ifdef LOADERTHREAD if (com_resourcemutex) Sys_UnlockMutex(com_resourcemutex); +#endif Con_Printf("GnuTLS "GNUTLS_VERSION" library not available.\n"); return false; } @@ -998,8 +1002,10 @@ qboolean SSL_InitGlobal(qboolean isserver) qgnutls_certificate_set_x509_trust_file (xcred[isserver], CAFILE, GNUTLS_X509_FMT_PEM); #endif +#ifdef LOADERTHREAD if (com_resourcemutex) Sys_UnlockMutex(com_resourcemutex); +#endif if (isserver) { #if 1 @@ -1026,8 +1032,10 @@ qboolean SSL_InitGlobal(qboolean isserver) } else { +#ifdef LOADERTHREAD if (com_resourcemutex) - Sys_UnlockMutex(com_resourcemutex); + Sys_UnlockMutex(com_resourcemutex); +#endif } if (initstatus[isserver] < 0) diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 2134f2d6..65504551 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -6805,7 +6805,7 @@ void NET_PrintConnectionsStatus(ftenet_connections_t *collection) int TCP_OpenStream (netadr_t *remoteaddr) { #ifndef HAVE_TCP - return INVALID_SOCKET; + return (int)INVALID_SOCKET; #else unsigned long _true = true; int newsocket; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 84e11edd..a5df0740 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -195,7 +195,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_temp_entity 23 // variable #define svc_setpause 24 // [qbyte] on / off -#define svc_signonnum 25 // [qbyte] used for the signon sequence +#define svcnq_signonnum 25 // [qbyte] used for the signon sequence +#define svcfte_splitscreenconfig 25 // [qbyte] seats, player[seat]. spectator flags passed via userinfo. #define svc_centerprint 26 // [string] to put in center of the screen diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 5c6f969d..d7868f3b 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -42179,6 +42179,26 @@ RelativePath="..\common\zone.h" > + + + + + + + + + + diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 093d5915..c1b0f27f 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -41,8 +41,6 @@ extern qboolean scr_initialized; extern float oldsbar; extern qboolean scr_drawloading; -extern int scr_chatmode; -extern cvar_t scr_chatmodecvar; extern cvar_t vid_conautoscale; extern qboolean scr_con_forcedraw; extern qboolean depthcleared; diff --git a/engine/gl/gl_videgl.c b/engine/gl/gl_videgl.c index 8553df7a..596d01ab 100644 --- a/engine/gl/gl_videgl.c +++ b/engine/gl/gl_videgl.c @@ -93,19 +93,19 @@ const char *EGL_GetErrorString(int error) { switch(error) { - case EGL_BAD_ACCESS: return "BAD_ACCESS"; - case EGL_BAD_ALLOC: return "BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: return "BAD_ATTRIBUTE"; - case EGL_BAD_CONFIG: return "BAD_CONFIG"; - case EGL_BAD_CONTEXT: return "BAD_CONEXT"; + case EGL_BAD_ACCESS: return "BAD_ACCESS"; + case EGL_BAD_ALLOC: return "BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: return "BAD_ATTRIBUTE"; + case EGL_BAD_CONFIG: return "BAD_CONFIG"; + case EGL_BAD_CONTEXT: return "BAD_CONEXT"; case EGL_BAD_CURRENT_SURFACE: return "BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: return "BAD_DISPLAY"; - case EGL_BAD_MATCH: return "BAD_MATCH"; - case EGL_BAD_NATIVE_PIXMAP: return "BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: return "BAD_NATIVE_WINDOW"; - case EGL_BAD_PARAMETER: return "BAD_PARAMETER"; - case EGL_BAD_SURFACE: return "BAD_SURFACE"; - default: return va("EGL:%#x", error); + case EGL_BAD_DISPLAY: return "BAD_DISPLAY"; + case EGL_BAD_MATCH: return "BAD_MATCH"; + case EGL_BAD_NATIVE_PIXMAP: return "BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: return "BAD_NATIVE_WINDOW"; + case EGL_BAD_PARAMETER: return "BAD_PARAMETER"; + case EGL_BAD_SURFACE: return "BAD_SURFACE"; + default: return va("EGL:%#x", error); } } diff --git a/engine/gl/gl_videgl.h b/engine/gl/gl_videgl.h index 6df6e7a1..df084426 100644 --- a/engine/gl/gl_videgl.h +++ b/engine/gl/gl_videgl.h @@ -17,6 +17,10 @@ #define EGL_PLATFORM_WAYLAND_KHR 0x31D8 //EGL_KHR_platform_wayland #endif +#ifndef EGL_PLATFORM_WIN32 +#define EGL_PLATFORM_WIN32 0 //no meaningful value. +#endif + void *EGL_Proc(char *f); void EGL_UnloadLibrary(void); qboolean EGL_LoadLibrary(char *driver); diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 7c2d7611..55e4978d 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -1522,7 +1522,7 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette) if (stat) { maindc = GetDC(mainwindow); - stat = EGL_Init (info, palette, mainwindow, maindc); + stat = EGL_Init (info, palette, EGL_PLATFORM_WIN32, mainwindow, maindc, (EGLNativeWindowType)mainwindow, (EGLNativeDisplayType)maindc); if (stat) if (!GL_Init(info, &EGL_Proc)) diff --git a/engine/server/server.h b/engine/server/server.h index 2f93e657..3f35d26c 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1155,7 +1155,7 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose); void SV_SaveInfos(vfsfile_t *f); -void SV_FixupName(char *in, char *out, unsigned int outlen); +void SV_FixupName(const char *in, char *out, unsigned int outlen); #ifdef SUBSERVERS //cluster stuff diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 64894334..d55b0329 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -2798,7 +2798,7 @@ static void SV_SendGameCommand_f(void) } else #endif - Con_Printf("Mod-specific command not known\n"); + Con_Printf("Mod-specific command \"%s\" not known\n", Cmd_Argv(1)); } diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 0d52044d..65c655ec 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -1305,6 +1305,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, i = QWMAX_CLIENTS; } } + if (i > MAX_CLIENTS) + i = MAX_CLIENTS; SV_UpdateMaxPlayers(i); // leave slots at start for clients only diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index b8bd59de..1a1ff363 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -184,7 +184,6 @@ char cvargroup_servercontrol[] = "server control variables"; vfsfile_t *sv_fraglogfile; -void SV_FixupName(char *in, char *out, unsigned int outlen); void SV_AcceptClient (netadr_t *adr, int userid, char *userinfo); void PRH2_SetPlayerClass(client_t *cl, int classnum, qboolean fromqc); @@ -2091,10 +2090,12 @@ void SV_ClientProtocolExtensionsChanged(client_t *client) client_t *SV_AddSplit(client_t *controller, char *info, int id) { client_t *cl, *prev; - int i; + int i, j; int curclients; qboolean loadgame; const char *name; + unsigned int clients = 0, spectators = 0; + qboolean asspec; if (!(controller->fteprotocolextensions & PEXT_SPLITSCREEN)) { @@ -2111,8 +2112,8 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) if (id && curclients != id) return NULL; //this would be weird. - if (curclients >= 16) - return NULL; //protocol limit on stats. +// if (curclients >= 16) +// return NULL; //protocol limit on stats. if (curclients >= MAX_SPLITS) return NULL; //only allow splitscreen if its explicitly allowed. unless its the local client in which case its always allowed. @@ -2168,9 +2169,26 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) } loadgame = (cl->state == cs_loadzombie); + if (loadgame) + asspec = cl->spectator; + else + asspec = !!atoi(Info_ValueForKey(info, "spectator")); + for (j=0 ; j= (asspec?maxspectators.ival:maxclients.ival)) + { + SV_PrintToClient(controller, PRINT_HIGH, "Server full, cannot add new seat\n"); + return NULL; + } - if (!loadgame) - cl->spectator = controller->spectator; + cl->spectator = asspec; cl->netchan.remote_address = controller->netchan.remote_address; cl->netchan.message.prim = controller->netchan.message.prim; cl->zquake_extensions = controller->zquake_extensions; @@ -2238,14 +2256,17 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) Info_RemoveKey (cl->userinfo, "spectator"); //this is a hint rather than a game breaker should it fail. - Info_SetValueForStarKey (cl->userinfo, "*spectator", va("%i", cl->spectator), sizeof(cl->userinfo)); + if (cl->spectator) + Info_SetValueForStarKey (cl->userinfo, "*spectator", va("%i", cl->spectator), sizeof(cl->userinfo)); + cl->state = controller->state; + +// host_client = NULL; +// sv_player = NULL; SV_ExtractFromUserinfo (cl, true); if (!loadgame) SV_GetNewSpawnParms(cl); - cl->state = controller->state; - if (cl->state >= cs_connected) { cl->sendinfo = true; @@ -2837,7 +2858,7 @@ client_t *SVC_DirectConnect(void) { if (cl->state == cs_free) continue; - if (cl->spectator) + if (cl->spectator && cl->spectator!=2) spectators++; else clients++; @@ -5225,7 +5246,7 @@ void SV_InitLocal (void) //" is so mods that use player names in tokenizing/frik_files don't mess up. mods are still expected to be able to cope with space. //is allowed to shorten, out must be as long as in and min of "unnamed"+1 -void SV_FixupName(char *in, char *out, unsigned int outlen) +void SV_FixupName(const char *in, char *out, unsigned int outlen) { char *s, *p; unsigned int len; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index f069aee5..0fb4b2a8 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -750,7 +750,7 @@ void SVNQ_New_f (void) { //old clients can't cope with reliables until they finish loading the models specified above. //we need to wait before sending any more //updated clients can wait a bit, and use signonnum 1 to tell them when to start loading stuff. - MSG_WriteByte (&host_client->netchan.message, svc_signonnum); + MSG_WriteByte (&host_client->netchan.message, svcnq_signonnum); MSG_WriteByte (&host_client->netchan.message, 1); host_client->netchan.nqunreliableonly = 2; } @@ -1034,7 +1034,7 @@ void SV_SendClientPrespawnInfo(client_t *client) { if (ISNQCLIENT(client) && (client->fteprotocolextensions2 & PEXT2_PREDINFO)) { - ClientReliableWrite_Begin(client, svc_signonnum, 2); + ClientReliableWrite_Begin(client, svcnq_signonnum, 2); ClientReliableWrite_Byte (client, 1); } } @@ -1639,7 +1639,7 @@ void SV_SendClientPrespawnInfo(client_t *client) if (ISNQCLIENT(client)) { //effectively a cmd spawn... but also causes the client to actually send the player's name too. - ClientReliableWrite_Begin (client, svc_signonnum, 2); + ClientReliableWrite_Begin (client, svcnq_signonnum, 2); ClientReliableWrite_Byte (client, 2); } else @@ -1967,12 +1967,12 @@ void SV_Begin_Core(client_t *split) else { #ifndef NOLEGACY - sv_player->xv->clientcolors = split->playercolor; + split->edict->xv->clientcolors = split->playercolor; if (progstype != PROG_QW) { //some redundant things, purely for dp compat eval_t *eval; edict_t *ent = split->edict; - sv_player->v->team = split->playercolor&15; + ent->v->team = split->playercolor&15; eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, "playermodel", ev_string, NULL); if (eval) @@ -2100,7 +2100,7 @@ void SV_Begin_Core(client_t *split) } SV_PostRunCmd(); host_client = oh; - sv_player = host_client->edict; + sv_player = oh?oh->edict:NULL; } } } @@ -2111,8 +2111,8 @@ void SV_Begin_Core(client_t *split) split->dp_pl = NULL; if (progstype == PROG_NQ) { - split->dp_ping = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, sv_player, "ping", ev_float, NULL); - split->dp_pl = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, sv_player, "ping_packetloss", ev_float, NULL); + split->dp_ping = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping", ev_float, NULL); + split->dp_pl = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping_packetloss", ev_float, NULL); } #endif } @@ -4040,7 +4040,7 @@ static void SV_UpdateSeats(client_t *controller) for (curclients = 0, cl = controller; cl; cl = cl->controlled) curclients++; - ClientReliableWrite_Begin(controller, svc_signonnum, 2+curclients); + ClientReliableWrite_Begin(controller, svcfte_splitscreenconfig, 2+curclients); ClientReliableWrite_Byte(controller, curclients); for (curclients = 0, cl = controller; cl; cl = cl->controlled, curclients++) { @@ -4966,7 +4966,7 @@ static void Cmd_AddSeat_f(void) { client_t *cl, *prev; qboolean changed = false; - //don't allow an altseat to add. paranoia. + //don't allow an altseat to add or remove. that's not how this works. if (host_client->controller) return; @@ -5003,7 +5003,7 @@ static void Cmd_AddSeat_f(void) //okay, it can get lost now. cl->drop = true; } - host_client->controller->joinobservelockeduntil = realtime + 3; + host_client->joinobservelockeduntil = realtime + 3; changed = true; break; } @@ -5512,7 +5512,7 @@ static void SVNQ_Spawn_f (void) //SV_Begin_Core(host_client); - ClientReliableWrite_Begin (host_client, svc_signonnum, 2); + ClientReliableWrite_Begin (host_client, svcnq_signonnum, 2); ClientReliableWrite_Byte (host_client, 3); host_client->send_message = true; @@ -6110,8 +6110,10 @@ void SV_ExecuteUserCommand (const char *s, qboolean fromQC) { //'cmd 2 say hi' should char *a=Cmd_Argv(0), *e; int pnum = strtoul(a, &e, 10); - - if (e == a+1 && pnum >= 1 && pnum <= MAX_SPLITS) + + //commands might be in the form of eg '2on2' so make sure that its fully numeric. + //KTX uses eg 'cmd 231', so don't take it if it can't be a seat, but there may be race conditions so we don't want error messages when it might have been a seat. + if (!*e && pnum >= 1 && pnum <= MAX_SPLITS) { client_t *sp; for (sp = host_client; sp; sp = sp->controlled)