diff --git a/engine/Makefile b/engine/Makefile index 96860d9ff..92b217032 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -419,6 +419,7 @@ CLIENT_OBJS = \ cl_tent.o \ cl_cam.o \ cl_screen.o \ + pr_clcmd.o \ cl_ui.o \ cl_ignore.o \ cl_cg.o \ @@ -810,7 +811,7 @@ ifeq ($(FTE_TARGET),vc) D3DCL_OBJS=$(D3DQUAKE_OBJS) $(SPEEX_OBJS) snd_win.o snd_directx.o cd_win.o in_win.o sys_win.o sys_win_threads.o $(D3DGL_OBJS) fs_win32.o $(LTO_END) resources.o $(LTO_START) D3D_EXE_NAME=../fted3dqw$(BITS).exe D3DCL_EXE_NAME=../fted3dclqw$(BITS).exe - D3D_LDFLAGS=$(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib + D3D_LDFLAGS=$(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/" D3DB_DIR=d3d_vc$(BITS) D3DCL_DIR=d3dcl_vc$(BITS) @@ -1062,6 +1063,8 @@ endif SV_DIR?=sv_sdl +-include Makefile_private + .default: help all: rel rel: sv-rel gl-rel mingl-rel diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index ca8e6fe89..803b04989 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -496,7 +496,7 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * bits |= MSG_ReadByte()<<24; if (cl_shownet.ival >= 3) - Con_Printf("%3i: Update %4i 0x%x\n", msg_readcount, entnum, bits); + Con_Printf("%3i: Update %4i 0x%x\n", msg_readcount, entnum, bits); if (bits & UF_RESET) { @@ -506,7 +506,7 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * else if (!olds) { /*reset got lost, probably the data will be filled in later - FIXME: we should probably ignore this entity*/ - Con_DPrintf("New entity without reset\n"); + Con_DPrintf("New entity %i without reset\n", entnum); *news = nullentitystate; // *news = *baseline; } @@ -639,10 +639,18 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * news->trans = MSG_ReadByte(); if (bits & UF_SCALE) news->scale = MSG_ReadByte(); - if (bits & UF_ABSLIGHT) - news->abslight = MSG_ReadByte(); + if (bits & UF_UNUSED3) + { + // news->abslight = MSG_ReadByte(); + } if (bits & UF_DRAWFLAGS) + { news->hexen2flags = MSG_ReadByte(); + if ((news->hexen2flags & MLS_MASKIN) == MLS_ABSLIGHT) + news->abslight = MSG_ReadByte(); + else + news->abslight = 0; + } if (bits & UF_TAGINFO) { news->tagentity = MSGCL_ReadEntity(); @@ -718,6 +726,29 @@ void CLFTE_ParseEntities(void) // Con_Printf("CL: Dropped %i\n", i); // } +#ifdef NQPROT + if (cls.protocol == CP_NETQUAKE) + { + int i; + for (i = 0; i < MAX_SPLITS; i++) + cl.playerview[i].fixangle = false; + cls.netchan.outgoing_sequence = cls.netchan.incoming_unreliable; + cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence; + cls.netchan.outgoing_sequence++; + cl.last_servermessage = realtime; + cl.ackedinputsequence = MSG_ReadLong(); + + if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0])) + cl.numackframes--; + cl.ackframes[cl.numackframes++] = cls.netchan.incoming_sequence; + + cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime; + + if (cl.validsequence != cls.netchan.incoming_sequence-1) + Con_Printf("CLIENT: Dropped a frame\n"); + } +#endif + newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; oldpacket = cl.validsequence&UPDATE_MASK; newp = &cl.frames[newpacket].packet_entities; @@ -725,8 +756,10 @@ void CLFTE_ParseEntities(void) cl.frames[newpacket].invalid = true; - if (!cl.validsequence || cls.netchan.incoming_sequence-cl.validsequence >= UPDATE_BACKUP-1) + if (!cl.validsequence || cls.netchan.incoming_sequence-cl.validsequence >= UPDATE_BACKUP-1 || oldp == newp) { + //yes, this results in a load of invalid packets for a while. + //server is meant to notice and send a reset packet, which causes it to become valid again oldp = &nullp; oldp->num_entities = 0; oldp->max_entities = 0; @@ -787,14 +820,17 @@ void CLFTE_ParseEntities(void) if (removeflag) { if (cl_shownet.ival >= 3) - Con_Printf("%3i: Remove %i @ %i\n", msg_readcount, newnum, cls.netchan.incoming_sequence); + Con_Printf("%3i: Remove %i @ %i\n", msg_readcount, newnum, cls.netchan.incoming_sequence); if (!newnum) { /*removal of world - means forget all entities*/ if (cl_shownet.ival >= 3) - Con_Printf("%3i: Reset all\n", msg_readcount); + Con_Printf("%3i: Reset all\n", msg_readcount); newp->num_entities = 0; + oldp = &nullp; + oldp->num_entities = 0; + oldp->max_entities = 0; isvalid = true; continue; } @@ -1233,7 +1269,6 @@ void DP5_ParseDelta(entity_state_t *s) } } -int cl_latestframenum; void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o( { //the incoming entities do not come in in any order. :( @@ -1252,7 +1287,9 @@ void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o( int oldi, newi, lowesti, lowestv, newremaining; qboolean remove; - cl_latestframenum = MSG_ReadLong(); /*server sequence to be acked*/ + if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0])) + cl.numackframes--; + cl.ackframes[cl.numackframes++] = MSG_ReadLong(); /*server sequence to be acked*/ if (cls.protocol_nq >= CPNQ_DP7) cl.ackedinputsequence = MSG_ReadLong(); /*client input sequence which has been acked*/ @@ -2941,6 +2978,9 @@ void CL_TransitionEntities (void) packnew = &cl.frames[newf].packet_entities; packold = &cl.frames[oldf].packet_entities; +// Con_Printf("%f %f %f\n", packold->servertime, servertime, packnew->servertime); +// Con_Printf("%f %f %f\n", cl.oldgametime, servertime, cl.gametime); + CL_TransitionPacketEntities(newff, packnew, packold, servertime); cl.currentpacktime = servertime; cl.currentpackentities = packnew; @@ -3194,8 +3234,9 @@ void CL_LinkPacketEntities (void) } else if (state->colormap > 0 && state->colormap <= MAX_CLIENTS) { - ent->topcolour = cl.players[state->colormap-1].ttopcolor; - ent->bottomcolour = cl.players[state->colormap-1].tbottomcolor; + ent->playerindex = state->colormap-1; + ent->topcolour = cl.players[ent->playerindex].ttopcolor; + ent->bottomcolour = cl.players[ent->playerindex].tbottomcolor; } // set skin diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 320611ea9..3b34bd578 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -997,7 +997,7 @@ void Name_Callback(struct cvar_s *var, char *oldvalue) void CLNQ_SendCmd(sizebuf_t *buf) { - extern int cl_latestframenum; + int i; // if (cls.signon == 4) { @@ -1008,11 +1008,12 @@ void CLNQ_SendCmd(sizebuf_t *buf) CLNQ_SendMove (&independantphysics[0], 0, buf); } - if (CPNQ_IS_DP && cls.signon == 4) + for (i = 0; i < cl.numackframes; i++) { MSG_WriteByte(buf, clcdp_ackframe); - MSG_WriteLong(buf, cl_latestframenum); + MSG_WriteLong(buf, cl.ackframes[i]); } + cl.numackframes = 0; memset(&independantphysics[0], 0, sizeof(independantphysics[0])); } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 257565d91..0075b3cc4 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -59,7 +59,7 @@ cvar_t hud_tracking_show = CVAR("hud_tracking_show", "1"); cvar_t cl_defaultport = CVARAFD("cl_defaultport", STRINGIFY(PORT_QWSERVER), "port", 0, "The default port to connect to servers.\nQW: "STRINGIFY(PORT_QWSERVER)", NQ: "STRINGIFY(PORT_NQSERVER)", Q2: "STRINGIFY(PORT_Q2SERVER)"."); -cvar_t cfg_save_name = CVARF("cfg_save_name", "fte", CVAR_ARCHIVE); +cvar_t cfg_save_name = CVARF("cfg_save_name", "fte", CVAR_ARCHIVE|CVAR_NOTFROMSERVER); cvar_t cl_splitscreen = CVARD("cl_splitscreen", "0", "Enables splitscreen support. See also: allow_splitscreen, in_rawinput*, the \"p\" command."); @@ -685,6 +685,7 @@ void CL_CheckForResend (void) { Con_TPrintf (TLC_BADSERVERADDRESS); connect_time = -1; + SCR_EndLoadingPlaque(); return; } NET_AdrToString(data, sizeof(data), adr); @@ -754,11 +755,13 @@ void CL_CheckForResend (void) { Con_TPrintf (TLC_BADSERVERADDRESS); connect_time = -1; + SCR_EndLoadingPlaque(); return; } if (!NET_IsClientLegal(&adr)) { Con_TPrintf (TLC_ILLEGALSERVERADDRESS); + SCR_EndLoadingPlaque(); connect_time = -1; return; } diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index 1c945c71e..9c0a7b169 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -68,7 +68,9 @@ typedef enum { SLIST_TEST_EQUAL, SLIST_TEST_GREATER, SLIST_TEST_GREATEREQUAL, - SLIST_TEST_NOTEQUAL + SLIST_TEST_NOTEQUAL, + SLIST_TEST_STARTSWITH, + SLIST_TEST_NOTSTARTSWITH } slist_test_t; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 3990b062e..03edd08f4 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -194,7 +194,7 @@ char *svc_nqstrings[] = "nqsvc_damage", // [qbyte] impact [qbyte] blood [vec3] from "nqsvc_spawnstatic", - "nqOBSOLETE svc_spawnbinary", + "nqsvcfte_spawnstatic2(21)", "nqsvc_spawnbaseline", "nqsvc_temp_entity", // @@ -237,7 +237,34 @@ char *svc_nqstrings[] = "dpsvc_spawnstaticsound2", //59 "dpsvc_trailparticles", //60 "dpsvc_pointparticles", //61 - "dpsvc_pointparticles1" //62 + "dpsvc_pointparticles1", //62 + "NEW PROTOCOL(63)", + "NEW PROTOCOL(64)", + "NEW PROTOCOL(65)", + "nqsvcfte_spawnbaseline2(66)", //66 + "NEW PROTOCOL(67)", + "NEW PROTOCOL(68)", + "NEW PROTOCOL(69)", + "NEW PROTOCOL(70)", + "NEW PROTOCOL(71)", + "NEW PROTOCOL(72)", + "NEW PROTOCOL(73)", + "NEW PROTOCOL(74)", + "NEW PROTOCOL(75)", + "NEW PROTOCOL(76)", + "NEW PROTOCOL(77)", + "NEW PROTOCOL(78)", + "NEW PROTOCOL(79)", + "NEW PROTOCOL(80)", + "NEW PROTOCOL(81)", + "NEW PROTOCOL(82)", + "NEW PROTOCOL(83)", + "NEW PROTOCOL(84)", + "NEW PROTOCOL(85)", + "nqsvcfte_updateentities(86)", + "NEW PROTOCOL(87)", + "NEW PROTOCOL(88)", + }; extern cvar_t requiredownloads, cl_standardchat, msg_filter, cl_countpendingpl, cl_download_mapsrc; @@ -1865,7 +1892,8 @@ void CL_ParseDownload (void) cls.downloadqw = NULL; } CL_DownloadFailed(cls.downloadremotename, true); - CL_CheckOrEnqueDownloadFile(name, localname, DLLF_IGNOREFAILED); + //FIXME: find some safe way to do this and actually test it. we should already know the local name, but we might have gained a .gz or something (this is quakeforge after all). +// CL_CheckOrEnqueDownloadFile(name, localname, DLLF_IGNOREFAILED); return; } @@ -2300,6 +2328,13 @@ void CLQW_ParseServerData (void) float maxspeed, entgrav; + if (cls.downloadmethod == DL_QWPENDING) + { + //if we didn't actually start downloading it yet, cancel the current download. + //this is to avoid qizmo not responding to the download command, resulting in hanging downloads that cause the client to then be unable to connect anywhere simply because someone's skin was set. + CL_DownloadFailed(cls.downloadremotename, true); + } + Con_DPrintf ("Serverdata packet received.\n"); // // wipe the client_state_t struct @@ -2702,7 +2737,24 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. Stats_NewMap(); Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc")); - protover = MSG_ReadLong (); + cls.fteprotocolextensions = 0; + cls.fteprotocolextensions2 = 0; + for(;;) + { + protover = MSG_ReadLong (); + switch(protover) + { + case PROTOCOL_VERSION_FTE: + cls.fteprotocolextensions = MSG_ReadLong(); + continue; + case PROTOCOL_VERSION_FTE2: + cls.fteprotocolextensions2 = MSG_ReadLong(); + continue; + default: + break; + } + break; + } netprim.coordsize = 2; netprim.anglesize = 1; @@ -2779,6 +2831,13 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. { Con_DPrintf("Standard NQ protocols\n"); } + if (cls.fteprotocolextensions & PEXT_FLOATCOORDS) + { + if (netprim.anglesize < 2) + netprim.anglesize = 2; + if (netprim.coordsize < 4) + netprim.coordsize = 4; + } cls.netchan.message.prim = cls.netchan.netprim = netprim; MSG_ChangePrimitives(netprim); @@ -3726,7 +3785,7 @@ void CLQW_ParseStartSoundPacket(void) Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent); #ifdef PEXT_CSQC - if (!CSQC_StartSound(ent, channel, cl.sound_name[sound_num], pos, volume/255.0, attenuation)) + if (!CSQC_StartSound(ent, channel, cl.sound_name[sound_num], pos, volume/255.0, attenuation, 100)) #endif { if (!sound_num) @@ -3874,7 +3933,7 @@ void CLNQ_ParseStartSoundPacket(void) pos[i] = MSG_ReadCoord (); #ifdef PEXT_CSQC - if (!CSQC_StartSound(ent, channel, cl.sound_name[sound_num], pos, volume/255.0, attenuation)) + if (!CSQC_StartSound(ent, channel, cl.sound_name[sound_num], pos, volume/255.0, attenuation, pitchadj)) #endif { if (!sound_num) @@ -4831,10 +4890,12 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) if (memessage) { if (!cl_standardchat.value && (plrflags & TPM_SPECTATOR)) - Q_strncatz(fullchatmessage, "^m^0*^7 ", sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, "^0*^7 ", sizeof(fullchatmessage)); else - Q_strncatz(fullchatmessage, "^m* ", sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, "* ", sizeof(fullchatmessage)); } + else + Q_strncatz(fullchatmessage, "\1", sizeof(fullchatmessage)); #if defined(_WIN32) && !defined(NOMEDIA) TTS_SayChatString(&msg); @@ -4842,15 +4903,15 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) if (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)) // for team chat don't highlight the name, just the brackets { - Q_strncatz(fullchatmessage, va("\1(^[%s%s^d\\player\\%i^])", name_coloured?"^m":"", name, plr-cl.players), sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, va("(^[^7%s%s^d\\player\\%i^])", name_coloured?"^m":"", name, plr-cl.players), sizeof(fullchatmessage)); } else if (cl_standardchat.ival) { - Q_strncatz(fullchatmessage, va("\1^[%s%s^d\\player\\%i^]", name_coloured?"^m":"", name, plr-cl.players), sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, va("^[^7%s%s^d\\player\\%i^]", name_coloured?"^m":"", name, plr-cl.players), sizeof(fullchatmessage)); } else { - Q_strncatz(fullchatmessage, va("\1^[%s^%c%s^d\\player\\%i^]", name_coloured?"^m":"", c, name, plr-cl.players), sizeof(fullchatmessage)); + Q_strncatz(fullchatmessage, va("^[^7%s^%c%s^d\\player\\%i^]", name_coloured?"^m":"", c, name, plr-cl.players), sizeof(fullchatmessage)); } if (!memessage) @@ -5182,7 +5243,7 @@ void CL_DumpPacket(void) { if (pos >= net_message.cursize) Con_Printf("X"); - else if (packet[pos] == 0 || packet[pos] == '\n') + else if (packet[pos] == 0 || packet[pos] == '\t' || packet[pos] == '\r' || packet[pos] == '\n') Con_Printf("."); else Con_Printf("%c", (unsigned char)packet[pos]); @@ -5265,7 +5326,7 @@ void CLQW_ParseServerMessage (void) { default: CL_DumpPacket(); - Host_EndGame ("CL_ParseServerMessage: Illegible server message (%i)", cmd); + Host_EndGame ("CL_ParseServerMessage: Illegible server message (%i@%i)", cmd, msg_readcount-1); return; case svc_time: @@ -5475,7 +5536,7 @@ void CLQW_ParseServerMessage (void) case svc_spawnstatic: CL_ParseStatic (1); break; - case svc_spawnstatic2: + case svcfte_spawnstatic2: CL_ParseStatic (2); break; case svc_temp_entity: @@ -5992,7 +6053,7 @@ qboolean CLNQ_ParseNQPrints(char *s) { while(*s >= '0' && *s <= '9') s++; - if (*s == ' ' && s-start >= 4) + if (*s == ' ' && s-start >= 3) { s++; start = s; @@ -6041,8 +6102,6 @@ void CLNQ_ParseServerMessage (void) // cl.last_servermessage = realtime; CL_ClearProjectiles (); - cls.netchan.nqreliable_allowed = true; - // // if recording demos, copy the message out // @@ -6233,6 +6292,22 @@ void CLNQ_ParseServerMessage (void) CL_ParseBaseline (cl_baselines + i); break; + //PEXT_REPLACEMENTDELTAS + case svcfte_updateentities: + if (cls.signon == 4 - 1) + { // first update is the final signon stage + cls.signon = 4; + CLNQ_SignonReply (); + } + CLFTE_ParseEntities(); + break; + case svcfte_spawnstatic2: + CL_ParseStatic (2); + break; + case svcfte_spawnbaseline2: + CL_ParseBaseline2 (); + break; + case svc_time: cl.playerview[0].oldfixangle = cl.playerview[0].fixangle; VectorCopy(cl.playerview[0].fixangles, cl.playerview[0].oldfixangles); @@ -6240,7 +6315,7 @@ void CLNQ_ParseServerMessage (void) cls.netchan.outgoing_sequence++; cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence-1; - cl.validsequence = cls.netchan.incoming_sequence-1; + cl.validsequence = cls.netchan.incoming_sequence; received_framecount = host_framecount; cl.last_servermessage = realtime; @@ -6267,8 +6342,8 @@ void CLNQ_ParseServerMessage (void) else { // cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; - cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.num_entities=0; - cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime = cl.gametime; + cl.frames[cl.validsequence&UPDATE_MASK].packet_entities.num_entities=0; + cl.frames[cl.validsequence&UPDATE_MASK].packet_entities.servertime = cl.gametime; } break; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 47d496bcb..e760f20f7 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1478,12 +1478,12 @@ void SCR_SetLoadingStage(int stage) loadingfile = NULL; break; case LS_CONNECTION: - SCR_SetLoadingFile("connection..."); + SCR_SetLoadingFile("waiting for connection..."); break; case LS_SERVER: if (scr_con_current > vid.height*scr_consize.value) scr_con_current = vid.height*scr_consize.value; - SCR_SetLoadingFile("server..."); + SCR_SetLoadingFile("starting server..."); break; case LS_CLIENT: SCR_SetLoadingFile("initial state"); @@ -1571,7 +1571,10 @@ void SCR_DrawLoading (void) y += 16; if (loadingfile) + { Draw_FunString(x+8, y+4, loadingfile); + y+=8; + } } else { //hexen2 files @@ -1697,8 +1700,8 @@ void SCR_EndLoadingPlaque (void) scr_disabled_for_loading = false; *levelshotname = '\0'; + SCR_SetLoadingStage(0); scr_drawloading = false; - loading_stage = 0; } void SCR_ImageName (char *mapname) diff --git a/engine/client/client.h b/engine/client/client.h index 137aa16b8..723c7dd76 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -52,7 +52,7 @@ typedef struct vec3_t velocity; int weaponframe; - int modelindex; + unsigned int modelindex; int frame; int skinnum; int effects; @@ -524,6 +524,10 @@ typedef struct double last_ping_request; // while showing scoreboard double last_servermessage; + //list of ent frames that still need to be acked. + int numackframes; + int ackframes[64]; + #ifdef Q2CLIENT q2frame_t q2frame; q2frame_t q2frames[Q2UPDATE_BACKUP]; @@ -1105,7 +1109,7 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid); qboolean CSQC_MouseMove(float xdelta, float ydelta, int devid); qboolean CSQC_MousePosition(float xabs, float yabs, int devid); qboolean CSQC_Accelerometer(float x, float y, float z); -int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation); +int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod); void CSQC_ParseEntities(void); qboolean CSQC_SettingListener(void); diff --git a/engine/client/keys.c b/engine/client/keys.c index a98e0afff..d0efcb4f1 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -609,10 +609,10 @@ void Key_DefaultLinkClicked(char *text, char *info) } return; } - c = Info_ValueForKey(info, "desc"); - if (*c) + c = Info_ValueForKey(info, "menu"); + if (*c && !strchr(c, ';') && !strchr(c, '\n')) { - Con_Footerf(false, "%s", c); + Cbuf_AddText(va("\nmenu_cmd conlink %s\n", c), RESTRICT_LOCAL); return; } c = Info_ValueForKey(info, "connect"); @@ -651,6 +651,12 @@ void Key_DefaultLinkClicked(char *text, char *info) Cbuf_AddText(va("\nimpulse %s\n", c), RESTRICT_LOCAL); return; } + c = Info_ValueForKey(info, "desc"); + if (*c) + { + Con_Footerf(false, "%s", c); + return; + } if (!*info && *text == '/') { Q_strncpyz(key_lines[edit_line]+1, text, sizeof(key_lines[edit_line])-1); diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 4655d0076..1ebac71d2 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -1846,7 +1846,6 @@ dllfunction_t gecko_functions[] = {(void**)&posgk_browser_lock_data, "osgk_browser_lock_data"}, {(void**)&posgk_browser_unlock_data, "osgk_browser_unlock_data"}, - {(void**)&posgk_browser_event_mouse_move, "osgk_browser_event_mouse_move"}, {(void**)&posgk_browser_event_mouse_move, "osgk_browser_event_mouse_move"}, {(void**)&posgk_browser_event_mouse_button, "osgk_browser_event_mouse_button"}, {(void**)&posgk_browser_event_key, "osgk_browser_event_key"}, @@ -4030,3 +4029,4 @@ qboolean Media_PausedDemo(void) {return false;} int filmtexture; #endif + diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 20750d5a9..1dd926f29 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -325,15 +325,6 @@ void M_Menu_Setup_f (void) menu_t *menu; menucustom_t *ci; menubutton_t *b; - static const char *classnames[] = - { - "Paladin", - "Crusader", - "Necromancer", - "Assasin", - "Demoness", - NULL - }; mgt = M_GameType(); if (mgt == MGT_QUAKE2) //quake2 main menu. @@ -414,6 +405,15 @@ void M_Menu_Setup_f (void) (info->teamedit = MC_AddEdit(menu, 64, 56, "Your team", team.string)); if (mgt == MGT_HEXEN2) { + static const char *classnames[] = + { + "Paladin", + "Crusader", + "Necromancer", + "Assasin", + "Demoness", + NULL + }; cvar_t *pc = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2"); (info->classedit = MC_AddCombo(menu, 64, 72, "Your class", (const char **)classnames, pc->ival-1)); } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 3d35d60bf..8fccace52 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -437,6 +437,7 @@ const char *presetexec[] = "gl_specular 0;" "r_loadlit 0;" "r_fastsky 1;" + "r_drawflame 0;" "r_waterstyle 0;" "r_lavastyle 0;" "r_shadow_realtime_dlight 0;" @@ -462,7 +463,7 @@ const char *presetexec[] = "r_lavastyle 1;" "r_nolightdir 0;" - , // normal (faithful) options + , // normal (faithful) options, with content replacement thrown in #ifdef MINIMAL "r_particlesystem classic;" #else @@ -476,6 +477,7 @@ const char *presetexec[] = "gl_load24bit 1;" "r_replacemodels \"md3 md2\";" "r_waterwarp 1;" + "r_drawflame 1;" , // nice options "r_stains 0.75;" diff --git a/engine/client/menu.c b/engine/client/menu.c index a9dd596cc..856481347 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -507,18 +507,24 @@ void M_Menu_Help_f (void) m_state = m_help; help_page = 0; - if (COM_FDepthFile("gfx/help1.lmp", true) < COM_FDepthFile("gfx/menu/help1.lmp", true)) + if (COM_FDepthFile("gfx/help0.lmp", true) <= COM_FDepthFile("gfx/menu/help1.lmp", true)) { helpstyle = "gfx/help%i.lmp"; - num_help_pages = 6; helppagemin=0; } else { helpstyle = "gfx/menu/help%02i.lmp"; - num_help_pages = 5; helppagemin = 1; } + + num_help_pages = 1; + while(num_help_pages < 100) + { + if (!COM_FDepthFile(va(helpstyle, num_help_pages+helppagemin), true)) + break; + num_help_pages++; + } } @@ -1071,7 +1077,7 @@ void M_Draw (int uimenu) return; } - if (m_state == m_none) + if (m_state == m_none || m_state == m_menu_dat) return; if ((!menu_script || scr_con_current) && !m_recursiveDraw) diff --git a/engine/client/menu.h b/engine/client/menu.h index bc64cefb6..558f221b7 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -443,6 +443,7 @@ void MP_Draw(void); void MP_RegisterCvarsAndCmds(void); void MP_Keydown(int key, int unicode); void MP_Keyup(int key, int unicode); +int MP_BuiltinValid(char *name, int num); #define MGT_BAD ~0 #define MGT_QUAKE1 0 diff --git a/engine/client/net_master.c b/engine/client/net_master.c index d5000c670..b10a1c12c 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -537,7 +537,7 @@ int Master_KeyForName(char *keyname) return SLKEY_MAP; else if (!strcmp(keyname, "ping")) return SLKEY_PING; - else if (!strcmp(keyname, "name")) + else if (!strcmp(keyname, "name") || !strcmp(keyname, "hostname")) return SLKEY_NAME; else if (!strcmp(keyname, "address") || !strcmp(keyname, "cname")) return SLKEY_ADDRESS; diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 621205f29..a503b25fe 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -1554,7 +1554,7 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen) if (ptype->dl_radius) { - Q_strncatz(outstr, va("lightradius %g %g\n", ptype->dl_radius), outstrlen); + Q_strncatz(outstr, va("lightradius %g\n", ptype->dl_radius), outstrlen); Q_strncatz(outstr, va("lightradiusfade %g \n", ptype->dl_decay[3]), outstrlen); Q_strncatz(outstr, va("lightrgb %g %g %g\n", ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]), outstrlen); Q_strncatz(outstr, va("lightrgbfade %g %g %g\n", ptype->dl_decay[0], ptype->dl_decay[1], ptype->dl_decay[2]), outstrlen); @@ -4480,40 +4480,45 @@ static void GL_DrawTrifanParticle(int count, particle_t **plist, plooks_t *type) } } -static void R_AddLineSparkParticle(scenetris_t *t, particle_t *p, plooks_t *type) +static void R_AddLineSparkParticle(int count, particle_t **plist, plooks_t *type) { - vec3_t v, cr, o2; - float scale; - - if (cl_numstrisvert+2 > cl_maxstrisvert) +/* + particle_t *p; + while (count--) { - cl_maxstrisvert+=64*2; - cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert); - cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert); - cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); + p = *plist++; + + if (cl_numstrisvert+2 > cl_maxstrisvert) + { + cl_maxstrisvert+=64*2; + cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert); + cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert); + cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); + } + + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+0]); + VectorCopy(p->rgba, cl_strisvertc[cl_numstrisvert+1]); + cl_strisvertc[cl_numstrisvert+1][3] = 0; + Vector2Set(cl_strisvertt[cl_numstrisvert+0], p->s1, p->t1); + Vector2Set(cl_strisvertt[cl_numstrisvert+1], p->s2, p->t2); + + VectorCopy(p->org, cl_strisvertv[cl_numstrisvert+0]); + VectorMA(p->org, -1/10, p->vel, cl_strisvertv[cl_numstrisvert+1]); + + if (cl_numstrisidx+2 > cl_maxstrisidx) + { + cl_maxstrisidx += 64*2; + cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); + } + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 0; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 1; + + cl_numstrisvert += 2; + + t->numvert += 2; + t->numidx += 2; } - - Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+0]); - VectorCopy(p->rgba, cl_strisvertc[cl_numstrisvert+1]); - cl_strisvertc[cl_numstrisvert+1][3] = 0; - Vector2Set(cl_strisvertt[cl_numstrisvert+0], p->s1, p->t1); - Vector2Set(cl_strisvertt[cl_numstrisvert+1], p->s2, p->t2); - - VectorCopy(p->org, cl_strisvertv[cl_numstrisvert+0]); - VectorMA(p->org, -1/10, p->vel, cl_strisvertv[cl_numstrisvert+1]); - - if (cl_numstrisidx+2 > cl_maxstrisidx) - { - cl_maxstrisidx += 64*2; - cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); - } - cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 0; - cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 1; - - cl_numstrisvert += 2; - - t->numvert += 2; - t->numidx += 2; +*/ } static void R_AddTSparkParticle(scenetris_t *t, particle_t *p, plooks_t *type) @@ -4919,9 +4924,9 @@ static void R_AddTexturedParticle(scenetris_t *t, particle_t *p, plooks_t *type) static void PScript_DrawParticleTypes (void) { - void (*sparklineparticles)(scenetris_t *t, particle_t *p, plooks_t *type)=R_AddLineSparkParticle; - void (*sparkfanparticles)(scenetris_t *t, particle_t *p, plooks_t *type)=GL_DrawTrifanParticle; - void (*sparktexturedparticles)(scenetris_t *t, particle_t *p, plooks_t *type)=GL_DrawTexturedSparkParticle; + void (*sparklineparticles)(int count, particle_t **plist, plooks_t *type)=R_AddLineSparkParticle; + void (*sparkfanparticles)(int count, particle_t **plist, plooks_t *type)=GL_DrawTrifanParticle; + void (*sparktexturedparticles)(int count, particle_t **plist, plooks_t *type)=GL_DrawTexturedSparkParticle; qboolean (*tr) (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); void *pdraw, *bdraw; @@ -5590,3 +5595,4 @@ particleengine_t pe_script = #endif #endif + diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 4660b7694..35742f35b 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3153,98 +3153,6 @@ static void QCBUILTIN PF_cs_OpenPortal (pubprogfuncs_t *prinst, struct globalvar #endif } -#ifndef NOMEDIA - -// #487 float(string name) gecko_create( string name ) -static void QCBUILTIN PF_cs_gecko_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *shader = PR_GetStringOfs(prinst, OFS_PARM0); - cin_t *cin; - cin = R_ShaderFindCinematic(shader); - - if (!cin) - G_FLOAT(OFS_RETURN) = 0; - else - G_FLOAT(OFS_RETURN) = 1; -} -// #488 void(string name) gecko_destroy( string name ) -static void QCBUILTIN PF_cs_gecko_destroy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ -} -// #489 void(string name) gecko_navigate( string name, string URI ) -static void QCBUILTIN PF_cs_gecko_navigate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *shader = PR_GetStringOfs(prinst, OFS_PARM0); - char *command = PR_GetStringOfs(prinst, OFS_PARM1); - cin_t *cin; - cin = R_ShaderFindCinematic(shader); - - if (!cin) - return; - - Media_Send_Command(cin, command); -} -// #490 float(string name) gecko_keyevent( string name, float key, float eventtype ) -static void QCBUILTIN PF_cs_gecko_keyevent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *shader = PR_GetStringOfs(prinst, OFS_PARM0); - int key = G_FLOAT(OFS_PARM1); - int eventtype = G_FLOAT(OFS_PARM2); - cin_t *cin; - cin = R_ShaderFindCinematic(shader); - - if (!cin) - return; - Media_Send_KeyEvent(cin, MP_TranslateDPtoFTECodes(key), (key>127)?0:key, eventtype); -} -// #491 void gecko_mousemove( string name, float x, float y ) -static void QCBUILTIN PF_cs_gecko_mousemove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *shader = PR_GetStringOfs(prinst, OFS_PARM0); - float posx = G_FLOAT(OFS_PARM1); - float posy = G_FLOAT(OFS_PARM2); - cin_t *cin; - cin = R_ShaderFindCinematic(shader); - - if (!cin) - return; - Media_Send_MouseMove(cin, posx, posy); -} -// #492 void gecko_resize( string name, float w, float h ) -static void QCBUILTIN PF_cs_gecko_resize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *shader = PR_GetStringOfs(prinst, OFS_PARM0); - float sizex = G_FLOAT(OFS_PARM1); - float sizey = G_FLOAT(OFS_PARM2); - cin_t *cin; - cin = R_ShaderFindCinematic(shader); - if (!cin) - return; - Media_Send_Resize(cin, sizex, sizey); -} -// #493 vector gecko_get_texture_extent( string name ) -static void QCBUILTIN PF_cs_gecko_get_texture_extent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *shader = PR_GetStringOfs(prinst, OFS_PARM0); - float *ret = G_VECTOR(OFS_RETURN); - int sx, sy; - cin_t *cin; - cin = R_ShaderFindCinematic(shader); - if (cin) - { - Media_Send_GetSize(cin, &sx, &sy); - } - else - { - sx = 0; - sy = 0; - } - ret[0] = sx; - ret[1] = sy; - ret[2] = 0; -} -#endif - static void QCBUILTIN PF_cs_droptofloor (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { csqcedict_t *ent; @@ -3284,20 +3192,6 @@ static void QCBUILTIN PF_cs_copyentity (pubprogfuncs_t *prinst, struct globalvar World_LinkEdict (&csqc_world, (wedict_t*)out, false); } -static void QCBUILTIN PF_cl_playingdemo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = !!cls.demoplayback; -} - -static void QCBUILTIN PF_cl_runningserver (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ -#ifdef CLIENTONLY - G_FLOAT(OFS_RETURN) = false; -#else - G_FLOAT(OFS_RETURN) = sv.state != ss_dead; -#endif -} - static void QCBUILTIN PF_cl_getlight (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { vec3_t ambient, diffuse, dir; @@ -3370,24 +3264,6 @@ static void QCBUILTIN PF_rotatevectorsbytag (pubprogfuncs_t *prinst, struct glob VectorCopy(srcorg, retorg); } -static void QCBUILTIN PF_shaderforname (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *str = PR_GetStringOfs(prinst, OFS_PARM0); - char *defaultbody = PF_VarString(prinst, 1, pr_globals); - - shader_t *shad; - - if (*defaultbody) - shad = R_RegisterShader(str, defaultbody); - else - shad = R_RegisterSkin(str, NULL); - if (shad) - G_FLOAT(OFS_RETURN) = shad-r_shaders + 1; - else - G_FLOAT(OFS_RETURN) = 0; -} - - @@ -3671,7 +3547,7 @@ qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state) { func_t func; - if (!state || !state->modelindex) + if (!state || state->modelindex <= 0 || state->modelindex >= MAX_MODELS) { if (csqcdelta_playerents[playernum]) { @@ -4658,8 +4534,10 @@ static struct { {"writetofile", PF_writetofile, 606}, {"isfunction", PF_isfunction, 607}, {"parseentitydata", PF_parseentitydata, 608}, + {"keynumtostring", PF_cl_keynumtostring, 609}, {"findkeysforcommand", PF_cl_findkeysforcommand, 610}, + {"stringtokeynum", PF_cl_stringtokeynum, 614}, {"sprintf", PF_sprintf, 627}, @@ -5661,7 +5539,7 @@ qboolean CSQC_LoadResource(char *resname, char *restype) pr_globals = PR_globals(csqcprogs, PR_CURRENT); (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, resname)); - (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, restype)); + (((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, restype)); PR_ExecuteProgram (csqcprogs, csqcg.loadresource); @@ -5797,7 +5675,7 @@ static void CSQC_EntityCheck(int entnum) } } -int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation) +int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod) { void *pr_globals; csqcedict_t *ent; @@ -5814,6 +5692,7 @@ int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float G_FLOAT(OFS_PARM3) = vol; G_FLOAT(OFS_PARM4) = attenuation; VectorCopy(pos, G_VECTOR(OFS_PARM5)); + G_FLOAT(OFS_PARM6) = attenuation; PR_ExecuteProgram(csqcprogs, csqcg.event_sound); diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index ecde71f30..a5747a6be 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -16,264 +16,6 @@ struct } mp_globs; -int MP_TranslateFTEtoDPCodes(int code) -{ - switch(code) - { - case K_TAB: return 9; - case K_ENTER: return 13; - case K_ESCAPE: return 27; - case K_SPACE: return 32; - case K_BACKSPACE: return 127; - case K_UPARROW: return 128; - case K_DOWNARROW: return 129; - case K_LEFTARROW: return 130; - case K_RIGHTARROW: return 131; - case K_ALT: return 132; - case K_CTRL: return 133; - case K_SHIFT: return 134; - case K_F1: return 135; - case K_F2: return 136; - case K_F3: return 137; - case K_F4: return 138; - case K_F5: return 139; - case K_F6: return 140; - case K_F7: return 141; - case K_F8: return 142; - case K_F9: return 143; - case K_F10: return 144; - case K_F11: return 145; - case K_F12: return 146; - case K_INS: return 147; - case K_DEL: return 148; - case K_PGDN: return 149; - case K_PGUP: return 150; - case K_HOME: return 151; - case K_END: return 152; - case K_KP_HOME: return 160; - case K_KP_UPARROW: return 161; - case K_KP_PGUP: return 162; - case K_KP_LEFTARROW: return 163; - case K_KP_5: return 164; - case K_KP_RIGHTARROW: return 165; - case K_KP_END: return 166; - case K_KP_DOWNARROW: return 167; - case K_KP_PGDN: return 168; - case K_KP_ENTER: return 169; - case K_KP_INS: return 170; - case K_KP_DEL: return 171; - case K_KP_SLASH: return 172; - case K_KP_MINUS: return 173; - case K_KP_PLUS: return 174; - case K_PAUSE: return 255; - case K_JOY1: return 768; - case K_JOY2: return 769; - case K_JOY3: return 770; - case K_JOY4: return 771; - case K_AUX1: return 772; - case K_AUX2: return 773; - case K_AUX3: return 774; - case K_AUX4: return 775; - case K_AUX5: return 776; - case K_AUX6: return 777; - case K_AUX7: return 778; - case K_AUX8: return 779; - case K_AUX9: return 780; - case K_AUX10: return 781; - case K_AUX11: return 782; - case K_AUX12: return 783; - case K_AUX13: return 784; - case K_AUX14: return 785; - case K_AUX15: return 786; - case K_AUX16: return 787; - case K_AUX17: return 788; - case K_AUX18: return 789; - case K_AUX19: return 790; - case K_AUX20: return 791; - case K_AUX21: return 792; - case K_AUX22: return 793; - case K_AUX23: return 794; - case K_AUX24: return 795; - case K_AUX25: return 796; - case K_AUX26: return 797; - case K_AUX27: return 798; - case K_AUX28: return 799; - case K_AUX29: return 800; - case K_AUX30: return 801; - case K_AUX31: return 802; - case K_AUX32: return 803; - case K_MOUSE1: return 512; - case K_MOUSE2: return 513; - case K_MOUSE3: return 514; - case K_MOUSE4: return 517; - case K_MOUSE5: return 518; - case K_MOUSE6: return 519; - case K_MOUSE7: return 520; - case K_MOUSE8: return 521; - case K_MOUSE9: return 522; - case K_MOUSE10: return 523; - case K_MWHEELDOWN: return 515;//K_MOUSE4; - case K_MWHEELUP: return 516;//K_MOUSE5; - default: return code; - } -} - -int MP_TranslateDPtoFTECodes(int code) -{ - switch(code) - { - case 9: return K_TAB; - case 13: return K_ENTER; - case 27: return K_ESCAPE; - case 32: return K_SPACE; - case 127: return K_BACKSPACE; - case 128: return K_UPARROW; - case 129: return K_DOWNARROW; - case 130: return K_LEFTARROW; - case 131: return K_RIGHTARROW; - case 132: return K_ALT; - case 133: return K_CTRL; - case 134: return K_SHIFT; - case 135: return K_F1; - case 136: return K_F2; - case 137: return K_F3; - case 138: return K_F4; - case 139: return K_F5; - case 140: return K_F6; - case 141: return K_F7; - case 142: return K_F8; - case 143: return K_F9; - case 144: return K_F10; - case 145: return K_F11; - case 146: return K_F12; - case 147: return K_INS; - case 148: return K_DEL; - case 149: return K_PGDN; - case 150: return K_PGUP; - case 151: return K_HOME; - case 152: return K_END; - case 160: return K_KP_HOME; - case 161: return K_KP_UPARROW; - case 162: return K_KP_PGUP; - case 163: return K_KP_LEFTARROW; - case 164: return K_KP_5; - case 165: return K_KP_RIGHTARROW; - case 166: return K_KP_END; - case 167: return K_KP_DOWNARROW; - case 168: return K_KP_PGDN; - case 169: return K_KP_ENTER; - case 170: return K_KP_INS; - case 171: return K_KP_DEL; - case 172: return K_KP_SLASH; - case 173: return K_KP_MINUS; - case 174: return K_KP_PLUS; - case 255: return K_PAUSE; - - case 768: return K_JOY1; - case 769: return K_JOY2; - case 770: return K_JOY3; - case 771: return K_JOY4; - case 772: return K_AUX1; - case 773: return K_AUX2; - case 774: return K_AUX3; - case 775: return K_AUX4; - case 776: return K_AUX5; - case 777: return K_AUX6; - case 778: return K_AUX7; - case 779: return K_AUX8; - case 780: return K_AUX9; - case 781: return K_AUX10; - case 782: return K_AUX11; - case 783: return K_AUX12; - case 784: return K_AUX13; - case 785: return K_AUX14; - case 786: return K_AUX15; - case 787: return K_AUX16; - case 788: return K_AUX17; - case 789: return K_AUX18; - case 790: return K_AUX19; - case 791: return K_AUX20; - case 792: return K_AUX21; - case 793: return K_AUX22; - case 794: return K_AUX23; - case 795: return K_AUX24; - case 796: return K_AUX25; - case 797: return K_AUX26; - case 798: return K_AUX27; - case 799: return K_AUX28; - case 800: return K_AUX29; - case 801: return K_AUX30; - case 802: return K_AUX31; - case 803: return K_AUX32; - case 512: return K_MOUSE1; - case 513: return K_MOUSE2; - case 514: return K_MOUSE3; - case 517: return K_MOUSE4; - case 518: return K_MOUSE5; - case 519: return K_MOUSE6; - case 520: return K_MOUSE7; - case 521: return K_MOUSE8; - case 522: return K_MOUSE9; - case 523: return K_MOUSE10; - case 515: return K_MWHEELDOWN;//K_MOUSE4; - case 516: return K_MWHEELUP;//K_MOUSE5; - default: return code; - } -} - -//string findkeysforcommand(string command) = #610; -void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0); - int keynums[2]; - char keyname[512]; - - M_FindKeysForCommand(0, cmdname, keynums); - - keyname[0] = '\0'; - - Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[0])), sizeof(keyname)); - Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[1])), sizeof(keyname)); - - RETURN_TSTRING(keyname); -} - -void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *binding = Key_GetBinding(G_FLOAT(OFS_PARM0)); - RETURN_TSTRING(binding); -} - -void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i; - int modifier; - char *s; - - s = PR_GetStringOfs(prinst, OFS_PARM0); - i = Key_StringToKeynum(s, &modifier); - if (i < 0 || modifier != ~0) - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - i = MP_TranslateFTEtoDPCodes(i); - G_FLOAT(OFS_RETURN) = i; -} - -//string keynumtostring(float keynum) = #609; -void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int code = G_FLOAT(OFS_PARM0); - - code = MP_TranslateDPtoFTECodes (code); - - RETURN_TSTRING(Key_KeynumToString(code)); -} - - - - @@ -375,7 +117,6 @@ void PR_CL_BeginString(pubprogfuncs_t *prinst, float vx, float vy, float szx, fl } } - fontidx--; if (fontidx >= 0 && fontidx < FONT_SLOTS) { int i, j; @@ -383,7 +124,7 @@ void PR_CL_BeginString(pubprogfuncs_t *prinst, float vx, float vy, float szx, fl for (i = 0; i < fontslot[fontidx].sizes; i++) { j = abs(szy - fontslot[fontidx].size[i]); - if (j < fontdiff && fontslot[fontidx].font) + if (j < fontdiff && fontslot[fontidx].font[i]) { fontdiff = j; font = fontslot[fontidx].font[i]; @@ -421,7 +162,8 @@ void PR_ResetFonts(qboolean purge) { for (j = 0; j < fontslot[i].sizes; j++) { - Font_Free(fontslot[i].font[j]); + if (fontslot[i].font[j]) + Font_Free(fontslot[i].font[j]); fontslot[i].font[j] = NULL; } @@ -455,13 +197,13 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g G_FLOAT(OFS_RETURN) = 0; //return default on failure. - if (slotnum == -1 && *slotname) + if (slotnum < 0 && *slotname) slotnum = PR_findnamedfont(slotname, true); - else if (slotnum == -1) + else if (slotnum < 0) slotnum = PR_findnamedfont(facename, false); - if (slotnum == -1) + if (slotnum < 0) slotnum = PR_findnamedfont("", true); - if (slotnum == -1) + if (slotnum < 0) return; //eep. if ((unsigned)slotnum >= FONT_SLOTS) @@ -474,7 +216,8 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g Q_strncpyz(fontslot[slotnum].facename, facename, sizeof(fontslot[slotnum].facename)); for (i = 0; i < fontslot[slotnum].sizes; i++) { - Font_Free(fontslot[slotnum].font[i]); + if (fontslot[slotnum].font[i]) + Font_Free(fontslot[slotnum].font[i]); fontslot[slotnum].font[i] = NULL; } } @@ -497,7 +240,7 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g fontslot[slotnum].sizes++; } } - G_FLOAT(OFS_RETURN) = slotnum + 1; + G_FLOAT(OFS_RETURN) = slotnum; } void QCBUILTIN PF_CL_DrawTextField (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -969,7 +712,9 @@ qboolean M_Vid_GetMode(int num, int *w, int *h); //a bit pointless really void QCBUILTIN PF_cl_getresolution (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { + extern cvar_t vid_fullscreen; float mode = G_FLOAT(OFS_PARM0); + qboolean forfullscreen = (prinst->callargc >= 2)?G_FLOAT(OFS_PARM1):vid_fullscreen.ival; float *ret = G_VECTOR(OFS_RETURN); int w, h; @@ -1158,17 +903,6 @@ static void QCBUILTIN PF_CopyEntity (pubprogfuncs_t *prinst, struct globalvars_s #ifdef CL_MASTER #include "cl_master.h" -typedef enum{ - SLIST_HOSTCACHEVIEWCOUNT, - SLIST_HOSTCACHETOTALCOUNT, - SLIST_MASTERQUERYCOUNT, - SLIST_MASTERREPLYCOUNT, - SLIST_SERVERQUERYCOUNT, - SLIST_SERVERREPLYCOUNT, - SLIST_SORTFIELD, - SLIST_SORTDESCENDING -} hostcacheglobal_t; - void QCBUILTIN PF_M_gethostcachevalue (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { hostcacheglobal_t hcg = G_FLOAT(OFS_PARM0); @@ -1330,16 +1064,22 @@ void QCBUILTIN PF_localsound (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl S_LocalSound (soundname); } -#define skip1 PF_Fixme, -#define skip5 skip1 skip1 skip1 skip1 skip1 -#define skip10 skip5 skip5 -#define skip50 skip10 skip10 skip10 skip10 skip10 -#define skip100 skip50 skip50 - void QCBUILTIN PF_menu_checkextension (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - //yeah, this is a stub... not sure what form extex + char *extname = PR_GetStringOfs(prinst, OFS_PARM0); + int i; G_FLOAT(OFS_RETURN) = 0; + + for (i = 0; i < QSG_Extensions_count; i++) + { + if (!QSG_Extensions[i].name) + continue; + if (!stricmp(extname, QSG_Extensions[i].name)) + { + G_FLOAT(OFS_RETURN) = 1; + break; + } + } } void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1414,6 +1154,35 @@ void QCBUILTIN PF_menu_findchainfloat (pubprogfuncs_t *prinst, struct globalvars RETURN_EDICT(prinst, (void*)chain); } +//entity findchainflags(.float _field, float match); +void QCBUILTIN PF_menu_findchainflags (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i, f; + int s; + menuedict_t *ent, *chain; //note, all edicts share the common header, but don't use it's fields! + eval_t *val; + + chain = (menuedict_t *) *prinst->parms->sv_edicts; + + f = G_INT(OFS_PARM0)+prinst->fieldadjust; + s = G_FLOAT(OFS_PARM1); + + for (i = 1; i < *prinst->parms->sv_num_edicts; i++) + { + ent = (menuedict_t*)EDICT_NUM(prinst, i); + if (ent->isfree) + continue; + if ((int)((float *)ent->fields)[f] & s) + continue; + + val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", NULL); + if (val) + val->edict = EDICT_TO_PROG(prinst, (void*)chain); + chain = ent; + } + + RETURN_EDICT(prinst, (void*)chain); +} void QCBUILTIN PF_etof(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -1522,7 +1291,7 @@ void QCBUILTIN PF_altstr_get(pubprogfuncs_t *prinst, struct globalvars_s *pr_glo } *out = 0; - G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, outstr ); + G_INT( OFS_RETURN ) = (int)PR_TempString( prinst, outstr ); } //string altstr_set(string str, float num, string set) = #85 void QCBUILTIN PF_altstr_set(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1607,321 +1376,280 @@ void QCBUILTIN PF_crypto_getmyidfp(pubprogfuncs_t *prinst, struct globalvars_s * G_INT(OFS_RETURN) = 0; } -builtin_t menu_builtins[] = { -//0 - PF_Fixme, - PF_menu_checkextension, //void checkextension(string ext) = #1; - PF_error, - PF_nonfatalobjerror, - PF_print, - skip1 //void bprint(string text,...) = #5; - skip1 //void sprint(float clientnum, string text,...) = #6; - skip1 //void centerprint(string text,...) = #7; - PF_normalize, //vector normalize(vector v) = #8; - PF_vlen, //float vlen(vector v) = #9; -//10 - PF_vectoyaw,//10 //float vectoyaw(vector v) = #10; - PF_vectoangles,//11 //vector vectoangles(vector v) = #11; - PF_random,//12 - PF_localcmd,//13 - PF_menu_cvar,//14 - PF_menu_cvar_set,//15 - PF_dprint,//16 - PF_ftos,//17 - PF_fabs,//18 - PF_vtos,//19 - - PF_etos,//20 - PF_stof,//21 - PF_Spawn,//22 - PF_Remove_,//23 - PF_FindString,//24 - PF_FindFloat,//25 - PF_menu_findchain,//26 //entity findchainstring(.string _field, string match) = #26; - PF_menu_findchainfloat,//27 //entity findchainfloat(.float _field, float match) = #27; - PF_CL_precache_file,//28 - PF_CL_precache_sound,//29 - -//30 - PF_coredump, //void coredump(void) = #30; - PF_traceon, //void traceon(void) = #31; - PF_traceoff, //void traceoff(void) = #32; - PF_eprint, //void eprint(entity e) = #33; - PF_rint, - PF_floor, - PF_ceil, - PF_nextent, - PF_Sin, - PF_Cos, -//40 - PF_Sqrt, - PF_randomvector, - PF_registercvar, - PF_min, - PF_max, - PF_bound, - PF_pow, - PF_CopyEntity, - PF_fopen, - PF_fclose, -//50 - PF_fgets, - PF_fputs, - PF_strlen, - PF_strcat, - PF_substring, - PF_stov, - PF_dupstring, - PF_forgetstring, - PF_Tokenize, - PF_ArgV, -//60 - PF_isserver, - skip1 //float clientcount(void) = #61; - PF_clientstate, - skip1 //void clientcommand(float client, string s) = #63; - skip1 //void changelevel(string map) = #64; - PF_localsound, - PF_cl_getmousepos, - PF_gettime, - PF_loadfromdata, - PF_loadfromfile, -//70 - PF_mod,//0 - PF_menu_cvar_string,//1 - PF_Fixme,//2 //void crash(void) = #72; - PF_Fixme,//3 //void stackdump(void) = #73; - PF_search_begin,//4 - PF_search_end,//5 - PF_search_getsize ,//6 - PF_search_getfilename,//7 - PF_chr2str,//8 - PF_etof,//9 //float etof(entity ent) = #79; -//80 - PF_ftoe,//10 - PF_IsNotNull, - - - PF_altstr_count, //float altstr_count(string str) = #82; - PF_altstr_prepare, //string altstr_prepare(string str) = #83; - PF_altstr_get, //string altstr_get(string str, float num) = #84; - PF_altstr_set, //string altstr_set(string str, float num, string set) = #85 - - skip1 //altstr_ins - skip1 //findflags - skip1 //findchainflags - PF_cvar_defstring, -//90 - skip10 -//100 - skip100 -//200 - skip10 - skip10 -//220 - skip1 - PF_strstrofs, // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS) - PF_str2chr, // #222 float(string str, float ofs) str2chr (FTE_STRINGS) - PF_chr2str, // #223 string(float c, ...) chr2str (FTE_STRINGS) - PF_strconv, // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS) - PF_strpad, // #225 string(float chars, string s, ...) strpad (FTE_STRINGS) - PF_infoadd, // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS) - PF_infoget, // #227 string(string info, string key) infoget (FTE_STRINGS) - PF_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) - PF_strcasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS) -//230 - PF_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS) - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 -//240 - skip10 - skip50 -//300 - skip10 - skip10 - skip10 - skip10 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - skip1 - PF_isdemo, - skip50 -//400 - skip10 - skip10 - skip10 - skip10 -//440 - PF_buf_create, // #440 float() buf_create (DP_QC_STRINGBUFFERS) - PF_buf_del, // #441 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) - PF_buf_getsize, // #442 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) - PF_buf_copy, // #443 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) - PF_buf_sort, // #444 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) - PF_buf_implode, // #445 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) - PF_bufstr_get, // #446 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) - PF_bufstr_set, // #447 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) - PF_bufstr_add, // #448 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) - PF_bufstr_free, // #449 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) -//450 - PF_Fixme,//0 - PF_CL_is_cached_pic,//1 - PF_CL_precache_pic,//2 - PF_CL_free_pic,//3 - PF_CL_drawcharacter,//4 - PF_CL_drawrawstring,//5 - PF_CL_drawpic,//6 - PF_CL_drawfill,//7 - PF_CL_drawsetcliparea,//8 - PF_CL_drawresetcliparea,//9 - -//460 - PF_CL_drawgetimagesize,//460 - PF_cin_open, // #461 - PF_cin_close, // #462 - PF_cin_setstate, // #463 - PF_cin_getstate, // #464 - PF_cin_restart, // #465 - PF_drawline, // #466 - PF_CL_drawcolouredstring, // #467 - PF_CL_stringwidth, // #468 - PF_CL_drawsubpic, // #469 - -//470 - skip1 // #470 +static struct { + char *name; + builtin_t bifunc; + int ebfsnum; +} BuiltinList[] = { + {"checkextension", PF_menu_checkextension, 1}, + {"error", PF_error, 2}, + {"objerror", PF_nonfatalobjerror, 3}, + {"print", PF_print, 4}, + {"bprint", PF_Fixme, 5}, + {"msprint", PF_Fixme, 6}, + {"cprint", PF_Fixme, 7}, + {"normalize", PF_normalize, 8}, + {"vlen", PF_vlen, 9}, + {"vectoyaw", PF_vectoyaw, 10}, + {"vectoangles", PF_vectoangles, 11}, + {"random", PF_random, 12}, + {"localcmd", PF_localcmd, 13}, + {"cvar", PF_menu_cvar, 14}, + {"cvar_set", PF_menu_cvar_set, 15}, + {"dprint", PF_dprint, 16}, + {"ftos", PF_ftos, 17}, + {"fabs", PF_fabs, 18}, + {"vtos", PF_vtos, 19}, + {"etos", PF_etos, 20}, + {"stof", PF_stof, 21}, + {"spawn", PF_Spawn, 22}, + {"remove", PF_Remove_, 23}, + {"find", PF_FindString, 24}, + {"findfloat", PF_FindFloat, 25}, + {"findchain", PF_menu_findchain, 26}, + {"findchainfloat", PF_menu_findchainfloat, 27}, + {"precache_file", PF_CL_precache_file, 28}, + {"precache_sound", PF_CL_precache_sound, 29}, + {"coredump", PF_coredump, 30}, + {"traceon", PF_traceon, 31}, + {"traceoff", PF_traceoff, 32}, + {"eprint", PF_eprint, 33}, + {"rint", PF_rint, 34}, + {"floor", PF_floor, 35}, + {"ceil", PF_ceil, 36}, + {"nextent", PF_nextent, 37}, + {"sin", PF_Sin, 38}, + {"cos", PF_Cos, 39}, + {"sqrt", PF_Sqrt, 40}, + {"randomvector", PF_randomvector, 41}, + {"registercvar", PF_registercvar, 42}, + {"min", PF_min, 43}, + {"max", PF_max, 44}, + {"bound", PF_bound, 45}, + {"pow", PF_pow, 46}, + {"copyentity", PF_CopyEntity, 47}, + {"fopen", PF_fopen, 48}, + {"fclose", PF_fclose, 49}, + {"fgets", PF_fgets, 50}, + {"fputs", PF_fputs, 51}, + {"strlen", PF_strlen, 52}, + {"strcat", PF_strcat, 53}, + {"substring", PF_substring, 54}, + {"stov", PF_stov, 55}, + {"strzone", PF_dupstring, 56}, + {"strunzone", PF_forgetstring, 57}, + {"tokenize", PF_Tokenize, 58}, + {"argv", PF_ArgV, 59}, + {"isserver", PF_isserver, 60}, + {"clientcount", PF_Fixme, 61}, //float clientcount(void) = #61; + {"clientstate", PF_clientstate, 62}, + {"clientcommand", PF_Fixme, 63}, //void clientcommand(float client, string s) = #63; + {"changelevel", PF_Fixme, 64}, //void changelevel(string map) = #64; + {"localsound", PF_localsound, 65}, + {"getmousepos", PF_cl_getmousepos, 66}, + {"gettime", PF_gettime, 67}, + {"loadfromdata", PF_loadfromdata, 68}, + {"loadfromfile", PF_loadfromfile, 69}, + {"mod", PF_mod, 70}, + {"cvar_string", PF_menu_cvar_string, 71}, + {"crash", PF_Fixme, 72}, //void crash(void) = #72; + {"stackdump", PF_Fixme, 73}, //void stackdump(void) = #73; + {"search_begin", PF_search_begin, 74}, + {"search_end", PF_search_end, 75}, + {"search_getsize", PF_search_getsize, 76}, + {"search_getfilename", PF_search_getfilename, 77}, + {"chr2str", PF_chr2str, 78}, + {"etof", PF_etof, 79}, + {"ftoe", PF_ftoe, 80}, + {"validstring", PF_IsNotNull, 81}, + {"altstr_count", PF_altstr_count, 82}, + {"altstr_prepare", PF_altstr_prepare, 83}, + {"altstr_get", PF_altstr_get, 84}, + {"altstr_set", PF_altstr_set, 85}, + {"altstr_ins", PF_Fixme, 86}, + {"findflags", PF_FindFlags, 87}, + {"findchainflags", PF_menu_findchainflags, 88}, + {"mcvar_defstring", PF_cvar_defstring, 89}, + //gap + {"abort", PF_Abort, 211}, + //gap + {"strstrofs", PF_strstrofs, 221}, + {"str2chr", PF_str2chr, 222}, + {"chr2str", PF_chr2str, 223}, + {"strconv", PF_strconv, 224}, + {"strpad", PF_strpad, 225}, + {"infoadd", PF_infoadd, 226}, + {"infoget", PF_infoget, 227}, + {"strncmp", PF_strncmp, 228}, + {"strcasecmp", PF_strcasecmp, 229}, + {"strncasecmp", PF_strncasecmp, 230}, + //gap + {"shaderforname", PF_shaderforname, 238}, + //gap + {"isdemo", PF_isdemo, 349}, + //gap + {"findfont", PF_CL_findfont, 356}, + {"loadfont", PF_CL_loadfont, 357}, + //gap + {"memalloc", PF_memalloc, 384}, + {"memfree", PF_memfree, 385}, + {"memcpy", PF_memcpy, 386}, + {"memset", PF_memset, 387}, + //gap + {"buf_create", PF_buf_create, 440}, + {"buf_del", PF_buf_del, 441}, + {"buf_getsize", PF_buf_getsize, 442}, + {"buf_copy", PF_buf_copy, 443}, + {"buf_sort", PF_buf_sort, 444}, + {"buf_implode", PF_buf_implode, 445}, + {"bufstr_get", PF_bufstr_get, 446}, + {"bufstr_set", PF_bufstr_set, 447}, + {"bufstr_add", PF_bufstr_add, 448}, + {"bufstr_free", PF_bufstr_free, 449}, + //gap + {"is_cached_pic", PF_CL_is_cached_pic, 451}, + {"precache_pic", PF_CL_precache_pic, 452}, + {"free_pic", PF_CL_free_pic, 453}, + {"drawcharacter", PF_CL_drawcharacter, 454}, + {"drawrawstring", PF_CL_drawrawstring, 455}, + {"drawpic", PF_CL_drawpic, 456}, + {"drawfill", PF_CL_drawfill, 457}, + {"drawsetcliparea", PF_CL_drawsetcliparea, 458}, + {"drawresetcliparea", PF_CL_drawresetcliparea, 459}, + {"drawgetimagesize", PF_CL_drawgetimagesize, 460}, + {"cin_open", PF_cin_open, 461}, + {"cin_close", PF_cin_close, 462}, + {"cin_setstate", PF_cin_setstate, 463}, + {"cin_getstate", PF_cin_getstate, 464}, + {"cin_restart", PF_cin_restart, 465}, + {"drawline", PF_drawline, 466}, + {"drawstring", PF_CL_drawcolouredstring, 467}, + {"stringwidth", PF_CL_stringwidth, 468}, + {"drawsubpic", PF_CL_drawsubpic, 469}, + //gap //MERGES WITH CLIENT+SERVER BUILTIN MAPPINGS BELOW - PF_asin, // #471 - PF_acos, // #472 - PF_atan, // #473 - PF_atan2, // #474 - PF_tan, // #475 - PF_strlennocol, // #476 - PF_strdecolorize, // #477 - PF_strftime, // #478 - PF_tokenizebyseparator, // #479 - -//480 - PF_strtolower, // #480 string(string s) VM_strtolower : DRESK - Return string as lowercase - PF_strtoupper, // #481 string(string s) VM_strtoupper : DRESK - Return string as uppercase - PF_cvar_defstring, // #482 - skip1 // #483 - PF_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE) - PF_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE) - skip1 // #486 - PF_gecko_create, // #487 float gecko_create( string name ) - PF_gecko_destroy, // #488 void gecko_destroy( string name ) - PF_gecko_navigate, // #489 void gecko_navigate( string name, string URI ) - -//490 - PF_gecko_keyevent, // #490 float gecko_keyevent( string name, float key, float eventtype ) - PF_gecko_movemouse, // #491 void gecko_mousemove( string name, float x, float y ) - PF_gecko_resize, // #492 void gecko_resize( string name, float w, float h ) - PF_gecko_get_texture_extent, // #493 vector gecko_get_texture_extent( string name ) - PF_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16) - PF_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE) - skip1 // #496 - skip1 // #497 - skip1 // #498 - skip1 // #499 - -//500 - skip1 // #500 - skip1 // #501 - skip1 // #502 - PF_whichpack, // #503 string(string) whichpack = #503; - skip1 // #504 - skip1 // #505 - skip1 // #506 - skip1 // #507 - skip1 // #508 - skip1 // #509 - -//510 - PF_uri_escape, // #510 string(string in) uri_escape = #510; - PF_uri_unescape, // #511 string(string in) uri_unescape = #511; - PF_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) - PF_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET) - PF_tokenize_console, // #514 - PF_argv_start_index, // #515 - PF_argv_end_index, // #516 - PF_buf_cvarlist, // #517 - PF_cvar_description, // #518 - skip1 // #519 - -//520 - skip10 - skip10 - skip10 - skip50 -//600 - skip1 - PF_cl_setkeydest, - PF_cl_getkeydest, - PF_cl_setmousetarget, - PF_cl_getmousetarget, - PF_callfunction, - PF_writetofile, //void writetofile(float fhandle, entity ent) = #606; - PF_isfunction, - PF_cl_getresolution, - PF_cl_keynumtostring, - PF_cl_findkeysforcommand, + {"asin", PF_asin, 471}, + {"acos", PF_acos, 472}, + {"atan", PF_atan, 473}, + {"atan2", PF_atan2, 474}, + {"tan", PF_tan, 475}, + {"strlennocol", PF_strlennocol, 476}, + {"strdecolorize", PF_strdecolorize, 477}, + {"strftime", PF_strftime, 478}, + {"tokenizebyseparator", PF_tokenizebyseparator, 479}, + {"strtolower", PF_strtolower, 480}, + {"strtoupper", PF_strtoupper, 481}, + {"cvar_defstring", PF_cvar_defstring, 482}, + //gap + {"strreplace", PF_strreplace, 484}, + {"strireplace", PF_strireplace, 485}, + //gap + {"gecko_create", PF_cs_gecko_create, 487}, + {"gecko_destroy", PF_cs_gecko_destroy, 488}, + {"gecko_navigate", PF_cs_gecko_navigate, 489}, + {"gecko_keyevent", PF_cs_gecko_keyevent, 490}, + {"gecko_mousemove", PF_cs_gecko_mousemove, 491}, + {"gecko_resize", PF_cs_gecko_resize, 492}, + {"gecko_get_texture_extent",PF_gecko_get_texture_extent,493}, + {"crc16", PF_crc16, 494}, + {"cvar_type", PF_cvar_type, 495}, + {"numentityfields", PF_numentityfields, 496}, + {"entityfieldname", PF_entityfieldname, 497}, + {"entityfieldtype", PF_entityfieldtype, 498}, + {"getentityfieldstring", PF_getentityfieldstring, 499}, + {"putentityfieldstring", PF_putentityfieldstring, 500}, + {"whichpack", PF_whichpack, 503}, + //gap + {"uri_escape", PF_uri_escape, 510}, + {"uri_unescape", PF_uri_unescape, 511}, + {"num_for_edict", PF_etof, 512}, + {"uri_get", PF_uri_get, 513}, + {"tokenize_console", PF_tokenize_console, 514}, + {"argv_start_index", PF_argv_start_index, 515}, + {"argv_end_index", PF_argv_end_index, 516}, + {"buf_cvarlist", PF_buf_cvarlist, 517}, + {"cvar_description", PF_cvar_description, 518}, + //gap + {"setkeydest", PF_cl_setkeydest, 601}, + {"getkeydest", PF_cl_getkeydest, 602}, + {"setmousetarget", PF_cl_setmousetarget, 603}, + {"getmousetarget", PF_cl_getmousetarget, 604}, + {"callfunction", PF_callfunction, 605}, + {"writetofile", PF_writetofile, 606}, + {"isfunction", PF_isfunction, 607}, + {"getresolution", PF_cl_getresolution, 608}, + {"keynumtostring", PF_cl_keynumtostring, 609}, + {"findkeysforcommand", PF_cl_findkeysforcommand, 610}, #ifdef CL_MASTER - PF_M_gethostcachevalue, - PF_M_gethostcachestring, -#else - skip1 - skip1 + {"gethostcachevalue", PF_M_gethostcachevalue, 611}, + {"gethostcachestring", PF_M_gethostcachestring, 612}, #endif - PF_parseentitydata, //void parseentitydata(entity ent, string data) = #613; + {"parseentitydata", PF_parseentitydata, 613}, - PF_cl_stringtokeynum, + {"stringtokeynum", PF_cl_stringtokeynum, 614}, - PF_M_resethostcachemasks, - PF_M_sethostcachemaskstring, - PF_M_sethostcachemasknumber, - PF_M_resorthostcache, - PF_M_sethostcachesort, - PF_M_refreshhostcache, //600 - PF_M_gethostcachenumber, - PF_M_gethostcacheindexforkey, - PF_M_addwantedhostcachekey, + {"resethostcachemasks", PF_M_resethostcachemasks, 615}, + {"sethostcachemaskstring", PF_M_sethostcachemaskstring,616}, + {"sethostcachemasknumber", PF_M_sethostcachemasknumber,617}, + {"resorthostcache", PF_M_resorthostcache, 618}, + {"sethostcachesort", PF_M_sethostcachesort, 619}, + {"refreshhostcache", PF_M_refreshhostcache, 620}, + {"gethostcachenumber", PF_M_gethostcachenumber, 621}, + {"gethostcacheindexforkey", PF_M_gethostcacheindexforkey,622}, + {"addwantedhostcachekey", PF_M_addwantedhostcachekey, 623}, #ifdef CL_MASTER - PF_M_getextresponse, // #624 - PF_netaddress_resolve, -#else - skip1 - skip1 + {"getextresponse", PF_M_getextresponse, 624}, + {"netaddress_resolve", PF_netaddress_resolve, 625}, #endif - skip1 /*get gamedir info*/ - PF_sprintf, /*sprintf*/ - skip1 /*not listed in dp*/ - skip1 /*not listed in dp*/ - skip1 /*setkeybind*/ //630 - skip1 /*getbindmaps*/ - skip1 /*setbindmaps*/ - PF_crypto_getkeyfp, /*crypto*/ - PF_crypto_getidfp, /*crypto*/ - PF_crypto_getencryptlevel, /*crypto*/ - PF_crypto_getmykeyfp, /*crypto*/ - PF_crypto_getmyidfp, /*crypto #637*/ + //gap + {"sprintf", PF_sprintf, 627}, + //gap + {"setkeybind", PF_Fixme, 630}, + {"getbindmaps", PF_Fixme, 631}, + {"setbindmaps", PF_Fixme, 632}, + {"crypto_getkeyfp", PF_crypto_getkeyfp, 633}, + {"crypto_getidfp", PF_crypto_getidfp, 634}, + {"crypto_getencryptlevel", PF_crypto_getencryptlevel, 635}, + {"crypto_getmykeyfp", PF_crypto_getmykeyfp, 636}, + {"crypto_getmyidfp", PF_crypto_getmyidfp, 637}, + {"digest_hex", PF_digest_hex, 639}, + {"crypto_getmyidstatus", PF_crypto_getmyidfp, 641} }; -int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]); +builtin_t menu_builtins[1024]; +int MP_BuiltinValid(char *name, int num) +{ + int i; + for (i = 0; BuiltinList[i].name; i++) + { + if (BuiltinList[i].ebfsnum == num) + { + if (!strcmp(BuiltinList[i].name, name)) + { + if (/*BuiltinList[i].bifunc == PF_NoMenu ||*/ BuiltinList[i].bifunc == PF_Fixme) + return false; + else + return true; + } + } + } + return false; +} +static void MP_SetupBuiltins(void) +{ + int i; + for (i = 0; i < sizeof(menu_builtins)/sizeof(menu_builtins[0]); i++) + menu_builtins[i] = PF_Fixme; + for (i = 0; BuiltinList[i].bifunc; i++) + { + if (BuiltinList[i].ebfsnum) + menu_builtins[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc; + } +} +void M_Init_Internal (void); void M_DeInit_Internal (void); int inmenuprogs; @@ -2004,6 +1732,7 @@ void VARGS Menu_Abort (char *format, ...) } MP_Shutdown(); + M_Init_Internal(); if (inmenuprogs) //something in the menu caused the problem, so... { @@ -2033,6 +1762,8 @@ qboolean MP_Init (void) M_DeInit_Internal(); + MP_SetupBuiltins(); + memset(&menuc_eval_chain, 0, sizeof(menuc_eval_chain)); @@ -2061,7 +1792,7 @@ qboolean MP_Init (void) menuprogparms.globalbuiltins = menu_builtins;//builtin_t *globalbuiltins; //these are available to all progs - menuprogparms.numglobalbuiltins = menu_numbuiltins; + menuprogparms.numglobalbuiltins = sizeof(menu_builtins) / sizeof(menu_builtins[0]); menuprogparms.autocompile = PR_COMPILEIGNORE;//PR_COMPILEEXISTANDCHANGED;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; @@ -2103,6 +1834,8 @@ qboolean MP_Init (void) mp_globs.drawfont = (float*)PR_FindGlobal(menuprogs, "drawfont", 0, NULL); mp_globs.drawfontscale = (float*)PR_FindGlobal(menuprogs, "drawfontscale", 0, NULL); + PR_AutoCvarSetup(menuprogs); + menuentsize = PR_InitEnts(menuprogs, 8192); @@ -2127,6 +1860,21 @@ qboolean MP_Init (void) return false; } +static void MP_GameCommand_f(void) +{ + void *pr_globals; + func_t gamecommand; + if (!menuprogs) + return; + gamecommand = PR_FindFunction(menuprogs, "GameCommand", PR_ANY); + if (!gamecommand) + return; + + pr_globals = PR_globals(menuprogs, PR_CURRENT); + (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(menuprogs, Cmd_Args())); + PR_ExecuteProgram (menuprogs, gamecommand); +} + void MP_CoreDump_f(void) { if (!menuprogs) @@ -2146,14 +1894,15 @@ void MP_CoreDump_f(void) void MP_Reload_f(void) { - MP_Shutdown(); - MP_Init(); + M_Shutdown(); + M_Reinit(); } void MP_RegisterCvarsAndCmds(void) { Cmd_AddCommand("coredump_menuqc", MP_CoreDump_f); Cmd_AddCommand("menu_restart", MP_Reload_f); + Cmd_AddCommand("menu_cmd", MP_GameCommand_f); Cvar_Register(&forceqmenu, MENUPROGSGROUP); Cvar_Register(&pr_menuqc_coreonerror, MENUPROGSGROUP); @@ -2196,6 +1945,7 @@ void MP_Keydown(int key, int unicode) if (keydown[K_CTRL]) { MP_Shutdown(); + M_Init_Internal(); return; } } @@ -2266,7 +2016,11 @@ qboolean MP_Toggle(void) inmenuprogs++; if (mp_toggle_function) + { + void *pr_globals = PR_globals(menuprogs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = 1; PR_ExecuteProgram(menuprogs, mp_toggle_function); + } inmenuprogs--; return true; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 5a9eac1c7..15bb6a6b6 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -244,7 +244,7 @@ void R2D_Init(void) "}\n" "}\n" ); - shader_menutint = R_RegisterShader("menutint_glsl", + shader_menutint = R_RegisterShader("menutint", "{\n" "if $glsl && gl_menutint_shader != 0\n" "[\n" @@ -610,6 +610,13 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue) #ifdef _WIN32 if (!strcmp(var->string, "?")) { + BOOL (APIENTRY *pChooseFontA)(LPCHOOSEFONTA) = NULL; + dllfunction_t funcs[] = + { + {(void*)&pChooseFontA, "ChooseFontA"}, + {NULL} + }; + qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen); LOGFONT lf = {0}; CHOOSEFONT cf = {sizeof(cf)}; extern HWND mainwindow; @@ -620,20 +627,21 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue) cf.iPointSize = (8 * vid.rotpixelheight)/vid.height; cf.Flags = CF_FORCEFONTEXIST | CF_TTONLY; cf.lpLogFont = &lf; + + Sys_LoadLibrary("Comdlg32.dll", funcs); - if (ChooseFont(&cf)) + if (pChooseFontA && pChooseFontA(&cf)) { char fname[MAX_OSPATH]; - DWORD bufsz = sizeof(fname); char *keyname; keyname = va("%s%s%s (TrueType)", lf.lfFaceName, lf.lfWeight>=FW_BOLD?" Bold":"", lf.lfItalic?" Italic":""); - if (ERROR_SUCCESS == RegGetValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, RRF_RT_REG_SZ, NULL, fname, &bufsz)) + if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname))) { Cvar_Set(var, fname); return; } keyname = va("%s (OpenType)", lf.lfFaceName); - if (ERROR_SUCCESS == RegGetValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, RRF_RT_REG_SZ, NULL, fname, &bufsz)) + if (MyRegGetStringValue(HKEY_LOCAL_MACHINE, WinNT?"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts", keyname, fname, sizeof(fname))) { Cvar_Set(var, fname); return; @@ -1165,3 +1173,4 @@ void R2D_DrawCrosshair(void) #endif + diff --git a/engine/client/renderer.c b/engine/client/renderer.c index eb4477efd..4a902b1e3 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -276,7 +276,7 @@ cvar_t gl_load24bit = SCVARF ("gl_load24bit", "1", cvar_t r_clear = CVARAF("r_clear","0", "gl_clear", 0); -cvar_t gl_max_size = SCVARF ("gl_max_size", "1024", CVAR_RENDERERLATCH); +cvar_t gl_max_size = SCVARF ("gl_max_size", "2048", CVAR_RENDERERLATCH); cvar_t gl_maxshadowlights = SCVARF ("gl_maxshadowlights", "2", CVAR_ARCHIVE); cvar_t gl_menutint_shader = SCVAR ("gl_menutint_shader", "1"); diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index a57395e25..eeeb941a1 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -1978,7 +1978,8 @@ void Win7_TaskListInit(void) } #endif -#if defined(SVNREVISION) +#if defined(SVNREVISION) && !defined(MINIMAL) + #define SVNREVISIONSTR STRINGIFY(SVNREVISION) #if defined(OFFICIAL_RELEASE) #define BUILDTYPE "rel" #else @@ -2003,7 +2004,7 @@ void Win7_TaskListInit(void) #else #define EXETYPE "glqw" #endif -#elif defiend(D3DQUAKE) +#elif defined(D3DQUAKE) #define EXETYPE "d3dqw" #elif defiend(SWQUAKE) #define EXETYPE "swqw" @@ -2012,41 +2013,50 @@ void Win7_TaskListInit(void) #define EXETYPE "qw" #endif -#ifdef UPDATE_URL -void MyRegSetValue(HKEY base, char *keyname, char *valuename, int type, void *data, int datalen) -{ - HKEY subkey; - RegOpenKeyEx(base, keyname, 0, KEY_WRITE, &subkey); - RegSetValueEx(subkey, valuename, 0, type, data, datalen); - RegCloseKey (subkey); -} -void MyRegDeleteKeyValue(HKEY base, char *keyname, char *valuename) -{ - HKEY subkey; - RegOpenKeyEx(base, keyname, 0, KEY_WRITE, &subkey); - RegDeleteValue(subkey, valuename); - RegCloseKey (subkey); -} -void MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen) +qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen) { + qboolean result = false; DWORD resultlen = datalen - 1; HKEY subkey; DWORD type = REG_NONE; - RegOpenKeyEx(base, keyname, 0, KEY_WRITE, &subkey); - RegQueryValueEx(subkey, valuename, NULL, &type, data, &datalen); - RegCloseKey (subkey); + if (RegOpenKeyEx(base, keyname, 0, KEY_WRITE, &subkey) == ERROR_SUCCESS) + { + result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &datalen); + RegCloseKey (subkey); + } if (type == REG_SZ || type == REG_EXPAND_SZ) ((char*)data)[datalen] = 0; else ((char*)data)[0] = 0; + return result; +} + +#ifdef UPDATE_URL + +void MyRegSetValue(HKEY base, char *keyname, char *valuename, int type, void *data, int datalen) +{ + HKEY subkey; + if (RegCreateKeyEx(base, keyname, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) + { + RegSetValueEx(subkey, valuename, 0, type, data, datalen); + RegCloseKey (subkey); + } +} +void MyRegDeleteKeyValue(HKEY base, char *keyname, char *valuename) +{ + HKEY subkey; + if (RegOpenKeyEx(base, keyname, 0, KEY_WRITE, &subkey) == ERROR_SUCCESS) + { + RegDeleteValue(subkey, valuename); + RegCloseKey (subkey); + } } qboolean Update_GetHomeDirectory(char *homedir, int homedirsize) { HMODULE shfolder = LoadLibrary("shfolder.dll"); - DWORD winver = (DWORD)LOBYTE(LOWORD(GetVersion())); if (shfolder) { @@ -2111,7 +2121,7 @@ void Update_Versioninfo_Available(struct dl_download *dl) { if (!strnicmp(linebuf, "Revision: ", 10)) { - if (atoi(linebuf+10) > atoi(SVNREVISION)) + if (atoi(linebuf+10) > atoi(SVNREVISIONSTR)) { struct dl_download *dl; Con_Printf("Downloading update: revision %i\n", atoi(linebuf+10)); @@ -2143,24 +2153,22 @@ void Update_Check(void) qboolean Sys_CheckUpdated(void) { - if (!strcmp(SVNREVISION, "-")) + int ffe = COM_CheckParm("--fromfrontend"); + PROCESS_INFORMATION childinfo; + STARTUPINFO startinfo = {sizeof(startinfo)}; + + if (!strcmp(SVNREVISIONSTR, "-")) return false; //no revision info in this build, meaning its custom built and thus cannot check against the available updated versions. else if (COM_CheckParm("-noupdate") || COM_CheckParm("--noupdate")) return false; else if (!COM_CheckParm("-autoupdate") && !COM_CheckParm("--autoupdate")) return false; - else if (!COM_CheckParm("--fromfrontend")) + else if (!ffe) { + char frontendpath[MAX_OSPATH]; char pendingpath[MAX_OSPATH]; char updatedpath[MAX_QPATH]; - PROCESS_INFORMATION childinfo; - STARTUPINFO startinfo; - char *cmdline = GetCommandLineA(); - - memset(&startinfo, 0, sizeof(startinfo)); - startinfo.cb = sizeof(startinfo); - MyRegGetStringValue(HKEY_CURRENT_USER, "Software\\"FULLENGINENAME, "pending" BUILDTYPE EXETYPE, pendingpath, sizeof(pendingpath)); if (*pendingpath) { @@ -2175,7 +2183,21 @@ qboolean Sys_CheckUpdated(void) if (*updatedpath) { - if (CreateProcess(updatedpath, va("%s --fromfrontend", COM_Parse(cmdline)), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) + GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); + if (CreateProcess(updatedpath, va("--fromfrontend \"%s\" \"%s\" %s", SVNREVISIONSTR, frontendpath, COM_Parse(GetCommandLineA())), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) + return true; + } + } + else + { + char frontendpath[MAX_OSPATH]; + //com_argv[ffe+1] is frontend revision + //com_argv[ffe+2] is frontend location + if (atoi(com_argv[ffe+1]) > atoi(SVNREVISIONSTR)) + { + //ping-pong it back, to make sure we're running the most recent version. + GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); + if (CreateProcess(com_argv[ffe+2], va("--fromfrontend \"%s\" \"%s\" %s", "", "", COM_Parse(GetCommandLineA())), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) return true; } } diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 1c32e9702..ac1201d24 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -1861,6 +1861,13 @@ void Cmd_ForwardToServer_f (void) if (SCR_RSShot()) return; } + if (Q_strcasecmp(Cmd_Argv(1), "pext") == 0 && (cls.protocol != CP_NETQUAKE || cls.protocol_nq != CPNQ_ID || cls.netchan.remote_address.type != NA_LOOPBACK)) + { //don't send any extension flags this if we're using cl_loopbackprotocol nqid, purely for a compat test. + //if you want to record compat-demos, disable extensions instead. + unsigned int fp1 = Net_PextMask(1, cls.protocol == CP_NETQUAKE), fp2 = Net_PextMask(2, cls.protocol == CP_NETQUAKE); + CL_SendClientCommand(true, "pext %#x %#x %#x %#x", PROTOCOL_VERSION_FTE, fp1, PROTOCOL_VERSION_FTE2, fp2); + return; + } if (Q_strcasecmp(Cmd_Argv(1), "ptrack") == 0) { if (!*Cmd_Argv(2)) @@ -2774,6 +2781,12 @@ void Cmd_WriteConfig_f(void) char fname[MAX_OSPATH]; char sysname[MAX_OSPATH]; + if (Cmd_IsInsecure()) + { + Con_Printf ("%s not allowed\n", Cmd_Argv(0)); + return; + } + filename = Cmd_Argv(1); if (!*filename) { diff --git a/engine/common/cmd.h b/engine/common/cmd.h index 48e17f481..102db4f16 100644 --- a/engine/common/cmd.h +++ b/engine/common/cmd.h @@ -133,8 +133,8 @@ void Cmd_Args_Set(char *newargs); #define RESTRICT_RCON rcon_level.ival #define RESTRICT_PROGS RESTRICT_MAX-2 -#define Cmd_FromGamecode() (Cmd_ExecLevel>=RESTRICT_SERVER) //cheat provention -#define Cmd_IsInsecure() (Cmd_ExecLevel>=RESTRICT_INSECURE) //prevention from the server from breaking/crashing/wiping us. +#define Cmd_FromGamecode() (Cmd_ExecLevel>=RESTRICT_SERVER) //cheat provention. block cheats if its not fromgamecode +#define Cmd_IsInsecure() (Cmd_ExecLevel>=RESTRICT_INSECURE) //prevention from the server from breaking/crashing/wiping us. if this returns true, block file access etc. // Parses a single line of text into arguments and tries to execute it // as if it was typed at the console diff --git a/engine/common/common.c b/engine/common/common.c index e520b71e4..e58f0b643 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1921,7 +1921,7 @@ void COM_DefaultExtension (char *path, char *extension, int maxlen) //3 invalid unicode char //4 invalid utf-16 lead/high surrogate //5 invalid utf-16 tail/low surrogate -unsigned int utf8_decode(int *error, const void *in, void **out) +unsigned int utf8_decode(int *error, const void *in, char **out) { //uc is the output unicode char unsigned int uc = 0xfffdu; //replacement character @@ -2406,7 +2406,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t if (*str & 0x80 && utf8 > 0) { //check for utf-8 int decodeerror; - void *end; + char *end; uc = utf8_decode(&decodeerror, str, &end); if (decodeerror) { @@ -2600,8 +2600,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t //we don't support the full 12bit colour depth (only 4-bit CGA) //so find the closest that we do support int best = 1; - float bd = 255*255*255, d; - int c; + float bd = 255*255*255; int r, g, b; if (str[2] >= '0' && str[2] <= '9') r = (str[2]-'0'); diff --git a/engine/common/common.h b/engine/common/common.h index 69196a20f..66a040448 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -293,7 +293,7 @@ void COM_ParsePlusSets (void); typedef unsigned int conchar_t; char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags); conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, qboolean keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator -unsigned int utf8_decode(int *error, const void *in, void **out); +unsigned int utf8_decode(int *error, const void *in, char **out); unsigned int utf8_encode(void *out, unsigned int unicode, int maxlen); char *COM_SkipPath (const char *pathname); diff --git a/engine/common/fs.c b/engine/common/fs.c index f683653c9..c6de483c3 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1447,6 +1447,20 @@ static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probable else Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); + //temp packages also do not nest + if (!istemporary) + { + for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + { + if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew || !searchpathformats[i].loadscan) + continue; + if (loadstuff & (1<next = com_searchpaths; com_searchpaths = search; } - com_fschanged = true; - //temp packages also do not nest - if (!istemporary) - { - for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) - { - if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew || !searchpathformats[i].loadscan) - continue; - if (loadstuff & (1<sock = sock; chan->remote_address = adr; chan->last_received = realtime; +#ifdef NQPROT + chan->nqreliable_allowed = true; +#endif chan->message.data = chan->message_buf; chan->message.allowoverflow = true; @@ -406,6 +409,7 @@ nqprot_t NQNetChan_Process(netchan_t *chan) } chan->incoming_reliable_acknowledged = chan->reliable_sequence; chan->reliable_sequence++; + chan->nqreliable_allowed = true; chan->last_received = realtime; } @@ -415,10 +419,9 @@ nqprot_t NQNetChan_Process(netchan_t *chan) Con_Printf("Future ack recieved\n"); if (showpackets.value) - Con_Printf ("<-- a s=%i a=%i(%i) %i\n" - , chan->outgoing_sequence - , chan->incoming_sequence - , chan->incoming_reliable_sequence + Con_Printf ("in %s a=%i %i\n" + , chan->sock != NS_SERVER?"s2c":"c2s" + , sequence , 0); return NQP_ERROR; //don't try execing the 'payload'. I hate ack packets. @@ -426,7 +429,7 @@ nqprot_t NQNetChan_Process(netchan_t *chan) if (header & NETFLAG_UNRELIABLE) { - if (sequence < chan->incoming_unreliable) + if (sequence <= chan->incoming_unreliable) { Con_DPrintf("Stale datagram recieved\n"); return NQP_ERROR; @@ -452,10 +455,9 @@ nqprot_t NQNetChan_Process(netchan_t *chan) chan->good_count++; if (showpackets.value) - Con_Printf ("<-- u s=%i a=%i(%i) %i\n" - , chan->outgoing_sequence - , chan->incoming_sequence - , chan->incoming_reliable_sequence + Con_Printf ("in %s u=%i %i\n" + , chan->sock != NS_SERVER?"s2c":"c2s" + , chan->incoming_unreliable , net_message.cursize); return NQP_DATAGRAM; } @@ -466,6 +468,11 @@ nqprot_t NQNetChan_Process(netchan_t *chan) runt[0] = BigLong(NETFLAG_ACK | 8); runt[1] = BigLong(sequence); NET_SendPacket (chan->sock, 8, runt, net_from); + if (showpackets.value) + Con_Printf ("out %s a=%i %i\n" + , chan->sock == NS_SERVER?"s2c":"c2s" + , sequence + , 0); chan->last_received = realtime; if (sequence == chan->incoming_reliable_sequence) @@ -489,10 +496,9 @@ nqprot_t NQNetChan_Process(netchan_t *chan) MSG_BeginReading(chan->netprim); if (showpackets.value) - Con_Printf ("<-- r s=%i a=%i(%i) %i\n" - , chan->outgoing_sequence - , chan->incoming_sequence - , chan->incoming_reliable_sequence + Con_Printf ("in %s r=%i %i\n" + , chan->sock != NS_SERVER?"s2c":"c2s" + , sequence , net_message.cursize); return NQP_RELIABLE; //we can read it now } @@ -536,9 +542,12 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) send.cursize = 0; /*unreliables flood out, but reliables are tied to server sequences*/ + if (chan->nqreliable_resendtime < realtime) + chan->nqreliable_allowed = true; if (chan->nqreliable_allowed) { - if (!chan->reliable_length && chan->message.cursize) + //consume the new reliable when we can. + if (!chan->reliable_length && chan->message.cursize && !chan->nqunreliableonly) { memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize); chan->reliable_length = chan->message.cursize; @@ -560,8 +569,8 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) { if (send.cursize + length < send.maxsize) { //throw the unreliable packet into the same one as the reliable (but not sent reliably) - SZ_Write (&send, data, length); - length = 0; +// SZ_Write (&send, data, length); +// length = 0; } *(int*)send_buf = BigLong(NETFLAG_DATA | NETFLAG_EOM | send.cursize); @@ -574,14 +583,15 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) sentsize += send.cursize; if (showpackets.value) - Con_Printf ("--> r s=%i a=%i(%i) %i\n" - , chan->outgoing_sequence - , chan->incoming_sequence - , chan->incoming_reliable_sequence + Con_Printf ("out %s r s=%i %i\n" + , chan->sock == NS_SERVER?"s2c":"c2s" + , chan->reliable_sequence , send.cursize); send.cursize = 0; + + chan->nqreliable_allowed = false; + chan->nqreliable_resendtime = realtime + 0.3; //resend reliables after 0.3 seconds. nq transports suck. } - chan->nqreliable_allowed = false; } //send out the unreliable (if still unsent) @@ -598,8 +608,9 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) sentsize += send.cursize; if (showpackets.value) - Con_Printf ("--> u s=%i %i\n" - , chan->outgoing_unreliable + Con_Printf ("out %s u=%i %i\n" + , chan->sock == NS_SERVER?"s2c":"c2s" + , chan->outgoing_unreliable-1 , send.cursize); send.cursize = 0; } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 6c41074ac..54baf5326 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1,3 +1,5 @@ +//file for builtin implementations relevent to all VMs. + #include "quakedef.h" #if !defined(CLIENTONLY) || defined(CSQC_DAT) || defined(MENU_DAT) @@ -2844,6 +2846,16 @@ static struct { } qctoken[MAXQCTOKENS]; unsigned int qctoken_count; +void tokenize_flush(void) +{ + while(qctoken_count > 0) + { + qctoken_count--; + free(qctoken[qctoken_count].token); + } + qctoken_count = 0; +} + void QCBUILTIN PF_ArgC (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) //85 //float() argc; { G_FLOAT(OFS_RETURN) = qctoken_count; @@ -2908,13 +2920,7 @@ void QCBUILTIN PF_tokenizebyseparator (pubprogfuncs_t *prinst, struct globalvar seps++; } - /*flush the old lot*/ - while(qctoken_count > 0) - { - qctoken_count--; - free(qctoken[qctoken_count].token); - } - qctoken_count = 0; + tokenize_flush(); qctoken[qctoken_count].start = 0; if (*str) @@ -3928,6 +3934,7 @@ void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored) #ifdef TEXTEDITOR Editor_ProgsKilled(progs); #endif + tokenize_flush(); } @@ -3943,7 +3950,8 @@ static void PR_AutoCvarApply(pubprogfuncs_t *prinst, eval_t *val, etype_t type, val->_int = var->ival; break; case ev_string: - prinst->RemoveProgsString(prinst, val->_int); + if (val->_int) + prinst->RemoveProgsString(prinst, val->_int); if (*var->string) val->_int = PR_SetString(prinst, var->string); else @@ -4011,6 +4019,7 @@ void PDECL PR_FoundPrefixedGlobals(pubprogfuncs_t *progfuncs, char *name, eval_t break; case ev_string: vals = PR_GetString(progfuncs, val->string); + val->_int = 0; break; default: return; @@ -4196,6 +4205,7 @@ lh_extension_t QSG_Extensions[] = { {"FTE_ENT_SKIN_CONTENTS"}, //self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder. {"FTE_ENT_UNIQUESPAWNID"}, {"FTE_EXTENDEDTEXTCODES"}, + {"FTE_FORCESHADER", 1, NULL, {"shaderforname"}}, {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, {"FTE_GFX_QUAKE3SHADERS"}, {"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}}, diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index c80651bcf..4d45ea7fe 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -331,6 +331,26 @@ void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cl_playingdemo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cl_runningserver (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_destroy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_navigate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_keyevent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_mousemove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_resize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_cs_gecko_get_texture_extent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +typedef enum{ + SLIST_HOSTCACHEVIEWCOUNT, + SLIST_HOSTCACHETOTALCOUNT, + SLIST_MASTERQUERYCOUNT, + SLIST_MASTERREPLYCOUNT, + SLIST_SERVERQUERYCOUNT, + SLIST_SERVERREPLYCOUNT, + SLIST_SORTFIELD, + SLIST_SORTDESCENDING +} hostcacheglobal_t; +void QCBUILTIN PF_shaderforname (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void search_close_progs(pubprogfuncs_t *prinst, qboolean complain); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 33b6c29bd..cebcc9ebc 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -171,7 +171,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_damage 19 #define svc_spawnstatic 20 -#define svc_spawnstatic2 21 +#define svcfte_spawnstatic2 21 #define svc_spawnbaseline 22 #define svc_temp_entity 23 // variable @@ -541,7 +541,7 @@ enum clcq2_ops_e /*the rest is optional extensions*/ #define UF_ALPHA (1u<<16) #define UF_SCALE (1u<<17) -#define UF_ABSLIGHT (1u<<18) +#define UF_UNUSED3 (1u<<18) #define UF_DRAWFLAGS (1u<<19) #define UF_TAGINFO (1u<<20) #define UF_LIGHT (1u<<21) diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index 8f8f2d132..81d910a3f 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -258,4 +258,5 @@ int D3D9Shader_FindUniform(union programhandle_u *h, int type, char *name) return -1; } -#endif \ No newline at end of file +#endif + diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 6abbbdc9a..26e3ffb26 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -237,6 +237,7 @@ Global {2866F783-6B44-4655-A38D-D53874037454}.Debug|Win32.Build.0 = Debug|Win32 {2866F783-6B44-4655-A38D-D53874037454}.Debug|x64.ActiveCfg = Release|Win32 {2866F783-6B44-4655-A38D-D53874037454}.GLDebug|Win32.ActiveCfg = Debug|Win32 + {2866F783-6B44-4655-A38D-D53874037454}.GLDebug|Win32.Build.0 = Debug|Win32 {2866F783-6B44-4655-A38D-D53874037454}.GLDebug|x64.ActiveCfg = Debug|Win32 {2866F783-6B44-4655-A38D-D53874037454}.GLRelease|Win32.ActiveCfg = Release|Win32 {2866F783-6B44-4655-A38D-D53874037454}.GLRelease|x64.ActiveCfg = Release|Win32 diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index f824181d3..73f0e6fc6 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -12007,6 +12007,10 @@ /> + + diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index dccf36236..cf485ad45 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -71,7 +71,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "n -= 1.0 - 4.0/256.0;\n" "#ifdef RIPPLEMAP\n" -"n += texture2D(s_t3, stc)*3;\n" +"n += texture2D(s_t3, stc).rgb*3.0;\n" "#endif\n" //the fresnel term decides how transparent the water should be @@ -414,23 +414,50 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "!!permu FRAMEBLEND\n" "!!permu SKELETAL\n" "!!permu FOG\n" +"!!cvarf r_glsl_offsetmapping_scale\n" +"!!cvarf gl_specular\n" //standard shader used for models. //must support skeletal and 2-way vertex blending or Bad Things Will Happen. //the vertex shader is responsible for calculating lighting values. +"#ifdef UPPERLOWER\n" +"#define UPPER\n" +"#define LOWER\n" +"#endif\n" + "varying vec2 tc;\n" "varying vec3 light;\n" +"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"varying vec3 eyevector;\n" +"#endif\n" + + + + "#ifdef VERTEX_SHADER\n" "#include \"sys/skeletal.h\"\n" "attribute vec2 v_texcoord;\n" "uniform vec3 e_light_dir;\n" "uniform vec3 e_light_mul;\n" "uniform vec3 e_light_ambient;\n" +"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"uniform vec3 e_eyepos;\n" +"#endif\n" "void main ()\n" "{\n" +"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n" +"vec3 n, s, t, w;\n" +"gl_Position = skeletaltransform_wnst(w,n,s,t);\n" +"vec3 eyeminusvertex = e_eyepos - w.xyz;\n" +"eyevector.x = -dot(eyeminusvertex, s.xyz);\n" +"eyevector.y = dot(eyeminusvertex, t.xyz);\n" +"eyevector.z = dot(eyeminusvertex, n.xyz);\n" +"#else\n" "vec3 n;\n" "gl_Position = skeletaltransform_n(n);\n" +"#endif\n" + "light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n" "tc = v_texcoord;\n" "}\n" @@ -449,24 +476,54 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FULLBRIGHT\n" "uniform sampler2D s_t3;\n" "#endif\n" + +"#if defined(SPECULAR)\n" +"uniform sampler2D s_t4;\n" +"uniform sampler2D s_t5;\n" +"uniform float cvar_gl_specular;\n" +"#endif\n" + +"#ifdef OFFSETMAPPING\n" +"#include \"sys/offsetmapping.h\"\n" +"#endif\n" + + + "uniform vec4 e_colourident;\n" "void main ()\n" "{\n" "vec4 col, sp;\n" + +"#ifdef OFFSETMAPPING\n" +"vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n" +"#define tc tcoffsetmap\n" +"#endif\n" + "col = texture2D(s_t0, tc);\n" "#ifdef UPPER\n" "vec4 uc = texture2D(s_t2, tc);\n" -"col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a);\n" +"col.rgb += uc.rgb*e_uppercolour*uc.a;\n" "#endif\n" "#ifdef LOWER\n" "vec4 lc = texture2D(s_t1, tc);\n" -"col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a);\n" +"col.rgb += lc.rgb*e_lowercolour*lc.a;\n" "#endif\n" "col.rgb *= light;\n" + +"#if defined(SPECULAR)\n" +"vec3 bumps = normalize(vec3(texture2D(s_t4, tc)) - 0.5);\n" +"vec4 specs = texture2D(s_t5, tc);\n" + +"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0));\n" +"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n" +"col.rgb += cvar_gl_specular * spec * specs.rgb;\n" +"#endif\n" + "#ifdef FULLBRIGHT\n" "vec4 fb = texture2D(s_t3, tc);\n" "col.rgb = mix(col.rgb, fb.rgb, fb.a);\n" "#endif\n" + "gl_FragColor = fog4(col * e_colourident);\n" "}\n" "#endif\n" @@ -1366,6 +1423,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND {QR_OPENGL, 110, "rtlight", "!!permu BUMP\n" "!!permu SKELETAL\n" +"!!permu UPPERLOWER\n" "!!permu FOG\n" "!!cvarf r_glsl_offsetmapping_scale\n" @@ -1383,6 +1441,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#extension GL_ARB_texture_gather : enable\n" "#endif\n" +"#ifdef UPPERLOWER\n" +"#define UPPER\n" +"#define LOWER\n" +"#endif\n" + "varying vec2 tcbase;\n" "varying vec3 lightvector;\n" @@ -1431,20 +1494,20 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" "#include \"sys/fog.h\"\n" -"uniform sampler2D s_t0;\n" +"uniform sampler2D s_t0; //diffuse\n" "#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n" -"uniform sampler2D s_t1;\n" +"uniform sampler2D s_t1; //normalmap\n" "#endif\n" "#ifdef SPECULAR\n" -"uniform sampler2D s_t2;\n" +"uniform sampler2D s_t2; //specular\n" "#endif\n" "#ifdef CUBEPROJ\n" -"uniform samplerCube s_t3;\n" +"uniform samplerCube s_t3; //projected cubemap\n" "#endif\n" "#ifdef PCF\n" "#ifdef CUBESHADOW\n" -"uniform samplerCubeShadow s_t4;\n" +"uniform samplerCubeShadow s_t4; //shadowmap\n" "#else\n" "#if 0//def GL_ARB_texture_gather\n" "uniform sampler2D s_t4;\n" @@ -1453,6 +1516,14 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "#endif\n" "#endif\n" +"#ifdef LOWER\n" +"uniform sampler2D s_t5; //pants colours\n" +"uniform vec3 e_lowercolour;\n" +"#endif\n" +"#ifdef UPPER\n" +"uniform sampler2D s_t6; //shirt colours\n" +"uniform vec3 e_uppercolour;\n" +"#endif\n" "uniform float l_lightradius;\n" @@ -1494,7 +1565,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND //assume z is the major axis (ie: forward from the light) "vec3 t = shadowcoord;\n" "float ma = dir.z;\n" -"vec4 axis = vec4(1.0, 1.0, 1.0, 0.0);\n" +"vec3 axis = vec3(1.0, 1.0, 1.0);\n" "if (dir.x > ma)\n" "{\n" "ma = dir.x;\n" @@ -1566,6 +1637,14 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#define tcbase tcoffsetmap\n" "#endif\n" "vec3 bases = vec3(texture2D(s_t0, tcbase));\n" +"#ifdef UPPER\n" +"vec4 uc = texture2D(s_t6, tcbase);\n" +"bases.rgb += uc.rgb*e_uppercolour*uc.a;\n" +"#endif\n" +"#ifdef LOWER\n" +"vec4 lc = texture2D(s_t5, tcbase);\n" +"bases.rgb += lc.rgb*e_lowercolour*lc.a;\n" +"#endif\n" "#if defined(BUMP) || defined(SPECULAR)\n" "vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\n" "#endif\n" @@ -1716,7 +1795,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "uniform sampler2D s_t0;/*$currentrender*/\n" "uniform sampler2D s_t1;/*warp image*/\n" "uniform sampler2D s_t2;/*edge image*/\n" -"uniform vec3 e_rendertexturescale;\n" +"uniform vec4 e_rendertexturescale;\n" "uniform float cvar_r_waterwarp;\n" "void main ()\n" "{\n" diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 1e40030a8..259b3f6ab 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -634,6 +634,7 @@ enum { WARN_UNSAFEFUNCTIONRETURNTYPE, WARN_MISSINGOPTIONAL, WARN_SYSTEMCRC, + WARN_CONDITIONALTYPEMISMATCH, ERR_PARSEERRORS, //caused by qcc_pr_parseerror being called. @@ -875,22 +876,21 @@ extern int numtemps; typedef char PATHSTRING[MAX_DATA_PATH]; -extern PATHSTRING *precache_sounds; -extern int *precache_sounds_block; -extern int *precache_sounds_used; +typedef struct +{ + PATHSTRING name; + int block; + int used; + int fileline; + char *filename; +} precache_t; +extern precache_t *precache_sound; extern int numsounds; - -extern PATHSTRING *precache_textures; -extern int *precache_textures_block; +extern precache_t *precache_texture; extern int numtextures; - -extern PATHSTRING *precache_models; -extern int *precache_models_block; -extern int *precache_models_used; +extern precache_t *precache_model; extern int nummodels; - -extern PATHSTRING *precache_files; -extern int *precache_files_block; +extern precache_t *precache_file; extern int numfiles; typedef struct qcc_includechunk_s { diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 4fe4d1370..4269d8cfb 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1973,7 +1973,7 @@ QCC_def_t *QCC_PR_Statement (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_ if (statements[numstatements-1].c == var_a->ofs) { static QCC_def_t nvara; - if (statements[numstatements-1].op == OP_NOT_F) + if (statements[numstatements-1].op == OP_NOT_F && QCC_OPCodeValid(&pr_opcodes[OP_IF_F])) op = &pr_opcodes[OP_IF_F]; else op = &pr_opcodes[OP_IF_I]; @@ -2812,16 +2812,16 @@ void QCC_PrecacheSound (QCC_def_t *e, int ch) if (!*n) return; for (i=0 ; i= '1' && ch <= '9') - precache_sounds_block[i] = ch - '0'; + precache_sound[i].block = ch - '0'; else - precache_sounds_block[i] = 1; + precache_sound[i].block = 1; numsounds++; } @@ -2839,25 +2839,27 @@ void QCC_PrecacheModel (QCC_def_t *e, int ch) if (!*n) return; for (i=0 ; i= '1' && ch <= '9') - precache_models_block[i] = ch - '0'; + precache_model[i].block = ch - '0'; else - precache_models_block[i] = 1; + precache_model[i].block = 1; } return; } if (nummodels == QCC_MAX_MODELS) return; // QCC_Error ("PrecacheModels: nummodels == MAX_MODELS"); - strcpy (precache_models[i], n); + strcpy (precache_model[i].name, n); if (ch >= '1' && ch <= '9') - precache_models_block[i] = ch - '0'; + precache_model[i].block = ch - '0'; else - precache_models_block[i] = 1; + precache_model[i].block = 1; + precache_model[i].filename = strings+s_file; + precache_model[i].fileline = pr_source_line; nummodels++; } @@ -2875,16 +2877,19 @@ void QCC_SetModel (QCC_def_t *e) if (!*n) return; for (i=0 ; i= '1' && ch <= '9') - precache_textures_block[i] = ch - '0'; + precache_texture[i].block = ch - '0'; else - precache_textures_block[i] = 1; + precache_texture[i].block = 1; numtextures++; } @@ -2929,16 +2934,16 @@ void QCC_PrecacheFile (QCC_def_t *e, int ch) if (!*n) return; for (i=0 ; i= '1' && ch <= '9') - precache_files_block[i] = ch - '0'; + precache_file[i].block = ch - '0'; else - precache_files_block[i] = 1; + precache_file[i].block = 1; numfiles++; } @@ -2947,16 +2952,16 @@ void QCC_PrecacheFileOptimised (char *n, int ch) int i; for (i=0 ; i= '1' && ch <= '9') - precache_files_block[i] = ch - '0'; + precache_file[i].block = ch - '0'; else - precache_files_block[i] = 1; + precache_file[i].block = 1; numfiles++; } @@ -5853,6 +5858,97 @@ pbool QCC_PR_StatementBlocksMatch(QCC_dstatement_t *p1, int p1count, QCC_dstatem return true; } +//vanilla qc only has an OP_IFNOT_I, others will be emulated as required, so we tend to need to emulate other opcodes. +QCC_dstatement_t *QCC_Generate_OP_IF(QCC_def_t *e) +{ + QCC_dstatement_t *st; + switch(e->type->type) + { + //int/pointer types + case ev_entity: + case ev_field: + case ev_function: + case ev_pointer: + case ev_integer: + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &st)); + break; + + //emulated types + case ev_string: + QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if (string) tests for null, not empty."); + if (flag_ifstring) + { + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, NULL, &st)); + break; + } + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &st)); + break; + case ev_float: + if (flag_iffloat || QCC_OPCodeValid(&pr_opcodes[OP_IF_F])) + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &st)); + else + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &st)); + break; + case ev_vector: + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], QCC_PR_Statement (&pr_opcodes[OP_NOT_V], e, NULL, NULL), NULL, &st)); + break; + + case ev_variant: + case ev_struct: + case ev_union: + case ev_void: + default: + QCC_PR_ParseWarning(WARN_CONDITIONALTYPEMISMATCH, "conditional type mismatch: %s", basictypenames[e->type->type]); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &st)); + break; + } + return st; +} +QCC_dstatement_t *QCC_Generate_OP_IFNOT(QCC_def_t *e) +{ + QCC_dstatement_t *st; + switch(e->type->type) + { + //int/pointer types + case ev_entity: + case ev_field: + case ev_function: + case ev_pointer: + case ev_integer: + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, NULL, &st)); + break; + + //emulated types + case ev_string: + QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if (string) tests for null, not empty"); + if (flag_ifstring) + { + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, NULL, &st)); + break; + } + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, NULL, &st)); + break; + case ev_float: + if (flag_iffloat || QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F])) + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, NULL, &st)); + else + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, NULL, &st)); + break; + case ev_vector: + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], QCC_PR_Statement (&pr_opcodes[OP_NOT_V], e, NULL, NULL), NULL, &st)); + break; + + case ev_variant: + case ev_struct: + case ev_union: + case ev_void: + default: + QCC_PR_ParseWarning(WARN_CONDITIONALTYPEMISMATCH, "conditional type mismatch: %s", basictypenames[e->type->type]); + QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, NULL, &st)); + break; + } + return st; +} /* ============ PR_ParseStatement @@ -5960,15 +6056,8 @@ void QCC_PR_ParseStatement (void) else patch1 = NULL; } - else if (!typecmp( e->type, type_string) && flag_ifstring) //special case, as strings are now pointers, not offsets from string table - { - QCC_PR_ParseWarning(WARN_IFSTRING_USED, "while(string) can result in bizzare behaviour"); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch1)); - } - else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) //special case, as negative 0 is also zero - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1)); else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1)); + patch1 = QCC_Generate_OP_IFNOT(e); } QCC_PR_Expect (")"); //after the line number is noted.. QCC_PR_ParseStatement (); @@ -6111,16 +6200,7 @@ void QCC_PR_ParseStatement (void) } else { - if (!typecmp( e->type, type_string) && flag_ifstring) - { - QCC_PR_ParseWarning(WARN_IFSTRING_USED, "do {} while(string) can result in bizzare behaviour"); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, NULL, &patch2)); - } - else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, NULL, &patch2)); - else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, NULL, &patch2)); - + patch2 = QCC_Generate_OP_IF(e); patch2->b = patch1 - patch2; } @@ -6205,27 +6285,11 @@ void QCC_PR_ParseStatement (void) if (negate) { - if (!typecmp( e->type, type_string) && flag_ifstring) - { - QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if not(string) can result in bizzare behaviour"); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_S], e, 0, &patch1)); - } - else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_F], e, 0, &patch1)); - else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IF_I], e, 0, &patch1)); + patch1 = QCC_Generate_OP_IF(e); } else { - if (!typecmp( e->type, type_string) && flag_ifstring) - { - QCC_PR_ParseWarning(WARN_IFSTRING_USED, "if (string) can result in bizzare behaviour"); - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch1)); - } - else if (!typecmp( e->type, type_float) && (flag_iffloat||QCC_OPCodeValid(&pr_opcodes[OP_IFNOT_F]))) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch1)); - else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch1)); + patch1 = QCC_Generate_OP_IFNOT(e); } QCC_PR_Expect (")"); //close bracket is after we save the statement to mem (so debugger does not show the if statement as being on the line after @@ -6487,12 +6551,7 @@ void QCC_PR_ParseStatement (void) } else { - if (e->type->type == ev_string) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_S], e, 0, &patch3)); - else if (e->type->type == ev_float) - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_F], e, 0, &patch3)); - else - QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_IFNOT_I], e, 0, &patch3)); + patch3 = QCC_Generate_OP_IFNOT(e); } patch3->b = &statements[pr_cases[i]] - patch3; } @@ -9017,7 +9076,8 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *def, QCC_type_t *type } } - if (!pr_scope || def->constant) + tmp->references++; + if (!pr_scope || def->constant || def->isstatic) { if (!tmp->constant) QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "initializer is not constant"); diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 6973370c4..78f08c5e1 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -1446,7 +1446,7 @@ void QCC_PR_LexString (void) } } if (len) - QCC_PR_ParseWarning(WARN_NOTUTF8, "String constant is not valid utf-8\n"); + QCC_PR_ParseWarning(WARN_NOTUTF8, "String constant is not valid utf-8"); } return; } diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index 1640725bb..7694bfbe5 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -887,6 +887,8 @@ void EditorReload(editor_t *editor) QCC_ReadFile(editor->filename, file, flen); file[flen] = 0; } + else + file = NULL; SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0); @@ -894,15 +896,18 @@ void EditorReload(editor_t *editor) Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane)); Edit_ReplaceSel(editor->editpane,""); - if (!fl_autohighlight) + if (file) { - GUIPrint(editor->editpane, file); + if (!fl_autohighlight) + { + GUIPrint(editor->editpane, file); + } + else + { + GUIFormattingPrint(editor->editpane, file); + } + free(file); } - else - { - GUIFormattingPrint(editor->editpane, file); - } - free(file); editor->modified = false; stat(editor->filename, &sbuf); @@ -1888,16 +1893,7 @@ int GUIprintf(const char *msg, ...) return 0; } - if (strstr(buf, "warning: ")) - { - if (outstatus < 1) - { - TreeView_SetBkColor(projecttree, RGB(255, 255, 0)); - outstatus = 1; - } - col = RGB(128, 128, 0); - } - else if (strstr(buf, "error: ")) + if (strstr(buf, ": error")) { if (outstatus < 2) { @@ -1906,6 +1902,15 @@ int GUIprintf(const char *msg, ...) } col = RGB(255, 0, 0); } + else if (strstr(buf, ": warning")) + { + if (outstatus < 1) + { + TreeView_SetBkColor(projecttree, RGB(255, 255, 0)); + outstatus = 1; + } + col = RGB(128, 128, 0); + } else col = RGB(0, 0, 0); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 6c2c7dcad..65517b390 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -77,23 +77,16 @@ int numfielddefs; //typedef char PATHSTRING[MAX_DATA_PATH]; -PATHSTRING *precache_sounds; -int *precache_sounds_block; -int *precache_sounds_used; +precache_t *precache_sound; int numsounds; -PATHSTRING *precache_textures; -int *precache_textures_block; -int *precache_textures_block; +precache_t *precache_texture; int numtextures; -PATHSTRING *precache_models; -int *precache_models_block; -int *precache_models_used; +precache_t *precache_model; int nummodels; -PATHSTRING *precache_files; -int *precache_files_block; +precache_t *precache_file; int numfiles; extern int numCompilerConstants; @@ -988,10 +981,10 @@ pbool QCC_WriteData (int crc) for (i = 0; i < nummodels; i++) { - if (!precache_models_used[i]) - QCC_PR_Warning(WARN_EXTRAPRECACHE, NULL, 0, "Model %s was precached but not directly used", precache_models[i]); - else if (!precache_models_block[i]) - QCC_PR_Warning(WARN_NOTPRECACHED, NULL, 0, "Model %s was used but not precached", precache_models[i]); + if (!precache_model[i].used) + QCC_PR_Warning(WARN_EXTRAPRECACHE, precache_model[i].filename, precache_model[i].fileline, "Model %s was precached but not directly used", precache_model[i].name); + else if (!precache_model[i].block) + QCC_PR_Warning(WARN_NOTPRECACHED, precache_model[i].filename, precache_model[i].fileline, "Model %s was used but not precached", precache_model[i].name); } //PrintStrings (); //PrintFunctions (); @@ -2438,33 +2431,33 @@ void _QCC_CopyFiles (int blocknum, int copytype, char *srcdir, char *destdir) for (i=0 ; i> 1); + } if (volume < 0) //erm... return; @@ -2990,8 +2998,9 @@ static void QCBUILTIN PF_sound (pubprogfuncs_t *prinst, struct globalvars_s *pr_ volume = 255; if (flags & 1) - channel |= 8; + channel |= 256; + //shift the reliable flag to 256 instead. SVQ1_StartSound ((wedict_t*)entity, channel, sample, volume, attenuation, pitchadj); } @@ -8721,6 +8730,100 @@ static void QCBUILTIN PF_SendPacket(pubprogfuncs_t *prinst, struct globalvars_s #endif BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"fixme", PF_Fixme, 0, 0, 0, 0, "void()"}, + +#ifndef SERVERONLY + //begin menu-only 'standard' + {"checkextension", PF_Fixme, 0, 0, 0, 1, "float(string ext)"}, + {"error", PF_Fixme, 0, 0, 0, 2, "void(string err,...)"}, + {"objerror", PF_Fixme, 0, 0, 0, 3, "void(string err,...)"}, + {"print", PF_Fixme, 0, 0, 0, 4, "void(string text,...)"}, + {"bprint", PF_Fixme, 0, 0, 0, 5, "void(string text,...)"}, + {"msprint", PF_Fixme, 0, 0, 0, 6, "void(float clientnum, string text,...)"}, + {"cprint", PF_Fixme, 0, 0, 0, 7, "void(string text,...)"}, + {"normalize", PF_Fixme, 0, 0, 0, 8, "vector(vector)"}, + {"vlen", PF_Fixme, 0, 0, 0, 9, "float(vector)"}, + {"vectoyaw", PF_Fixme, 0, 0, 0, 10, "float(vector)"}, + {"vectoangles", PF_Fixme, 0, 0, 0, 11, "vector(vector)"}, + {"random", PF_Fixme, 0, 0, 0, 12, "float()"}, + {"localcmd", PF_Fixme, 0, 0, 0, 13, "void(string)"}, + {"cvar", PF_Fixme, 0, 0, 0, 14, "float(string name)"}, + {"cvar_set", PF_Fixme, 0, 0, 0, 15, "void(string name, string value)"}, + {"dprint", PF_Fixme, 0, 0, 0, 16, "void(string text)"}, + {"ftos", PF_Fixme, 0, 0, 0, 17, "string(float)"}, + {"fabs", PF_Fixme, 0, 0, 0, 18, "float(float)"}, + {"vtos", PF_Fixme, 0, 0, 0, 19, "string(vector)"}, + {"etos", PF_Fixme, 0, 0, 0, 20, "string(entity)"}, + {"stof", PF_Fixme, 0, 0, 0, 21, "float(string)"}, + {"spawn", PF_Fixme, 0, 0, 0, 22, "entity()"}, + {"remove", PF_Fixme, 0, 0, 0, 23, "void(entity)"}, + {"find", PF_Fixme, 0, 0, 0, 24, "entity(entity start, .string field, string match)"}, + {"findfloat", PF_Fixme, 0, 0, 0, 25, "entity(entity start, .__variant field, __variant match)"}, + {"findchain", PF_Fixme, 0, 0, 0, 26, "entity(.string field, string match)"}, + {"findchainfloat", PF_Fixme, 0, 0, 0, 27, "entity(.__variant field, __variant match)"}, + {"precache_file", PF_Fixme, 0, 0, 0, 28, "string(string file)"}, + {"precache_sound", PF_Fixme, 0, 0, 0, 29, "string(string sample)"}, + {"coredump", PF_Fixme, 0, 0, 0, 30, "void()"}, + {"traceon", PF_Fixme, 0, 0, 0, 31, "void()"}, + {"traceoff", PF_Fixme, 0, 0, 0, 32, "void()"}, + {"eprint", PF_Fixme, 0, 0, 0, 33, "void(entity)"}, + {"rint", PF_Fixme, 0, 0, 0, 34, "float(float)"}, + {"floor", PF_Fixme, 0, 0, 0, 35, "float(float)"}, + {"ceil", PF_Fixme, 0, 0, 0, 36, "float(float)"}, + {"nextent", PF_Fixme, 0, 0, 0, 37, "entity(entity)"}, + {"sin", PF_Fixme, 0, 0, 0, 38, "float(float)"}, + {"cos", PF_Fixme, 0, 0, 0, 39, "float(float)"}, + {"sqrt", PF_Fixme, 0, 0, 0, 40, "float(float)"}, + {"randomvector", PF_Fixme, 0, 0, 0, 41, "vector()"}, + {"registercvar", PF_Fixme, 0, 0, 0, 42, "float(string name, string value, float flags)"}, + {"min", PF_Fixme, 0, 0, 0, 43, "float(float,...)"}, + {"max", PF_Fixme, 0, 0, 0, 44, "float(float,...)"}, + {"bound", PF_Fixme, 0, 0, 0, 45, "float(float min,float value,float max)"}, + {"pow", PF_Fixme, 0, 0, 0, 46, "float(float,float)"}, + {"copyentity", PF_Fixme, 0, 0, 0, 47, "void(entity src, entity dst)"}, + {"fopen", PF_Fixme, 0, 0, 0, 48, "float(string filename, float mode)"}, + {"fclose", PF_Fixme, 0, 0, 0, 49, "void(float fhandle)"}, + {"fgets", PF_Fixme, 0, 0, 0, 50, "string(float fhandle)"}, + {"fputs", PF_Fixme, 0, 0, 0, 51, "void(float fhandle, string s)"}, + {"strlen", PF_Fixme, 0, 0, 0, 52, "float(string)"}, + {"strcat", PF_Fixme, 0, 0, 0, 53, "string(string, optional string, optional string, optional string, optional string, optional string, optional string, optional string)"}, + {"substring", PF_Fixme, 0, 0, 0, 54, "string(string s, float start, float length)"}, + {"stov", PF_Fixme, 0, 0, 0, 55, "vector(string)"}, + {"strzone", PF_Fixme, 0, 0, 0, 56, "string(string)"}, + {"strunzone", PF_Fixme, 0, 0, 0, 57, "void(string)"}, + {"tokenize", PF_Fixme, 0, 0, 0, 58, "float(string)"}, + {"argv", PF_Fixme, 0, 0, 0, 59, "string(float)"}, + {"isserver", PF_Fixme, 0, 0, 0, 60, "float()"}, + {"clientcount", PF_Fixme, 0, 0, 0, 61, "float()"}, + {"clientstate", PF_Fixme, 0, 0, 0, 62, "float()"}, + {"clientcommand", PF_Fixme, 0, 0, 0, 63, "void(float client, string s)"}, + {"changelevel", PF_Fixme, 0, 0, 0, 64, "void(string map)"}, + {"localsound", PF_Fixme, 0, 0, 0, 65, "void(string sample)"}, + {"getmousepos", PF_Fixme, 0, 0, 0, 66, "vector()"}, + {"gettime", PF_Fixme, 0, 0, 0, 67, "float()"}, + {"loadfromdata", PF_Fixme, 0, 0, 0, 68, "void(string data)"}, + {"loadfromfile", PF_Fixme, 0, 0, 0, 69, "void(string data)"}, + {"mod", PF_Fixme, 0, 0, 0, 70, "float(float val, float m)"}, + {"cvar_string", PF_Fixme, 0, 0, 0, 71, "string(string name)"}, + {"crash", PF_Fixme, 0, 0, 0, 72, "void()"}, + {"stackdump", PF_Fixme, 0, 0, 0, 73, "void()"}, + {"search_begin", PF_Fixme, 0, 0, 0, 74, "float(string pattern, float caseinsensitive, float quiet)"}, + {"search_end", PF_Fixme, 0, 0, 0, 75, "void(float handle)"}, + {"search_getsize", PF_Fixme, 0, 0, 0, 76, "float(float handle)"}, + {"search_getfilename",PF_Fixme, 0, 0, 0, 77, "string(float handle, float num)"}, + {"etof", PF_Fixme, 0, 0, 0, 79, "float(entity)"}, + {"ftoe", PF_Fixme, 0, 0, 0, 80, "entity(float)"}, + {"validstring", PF_Fixme, 0, 0, 0, 81, "float(string)"}, + {"altstr_count", PF_Fixme, 0, 0, 0, 82, "float(string str)"}, + {"altstr_prepare", PF_Fixme, 0, 0, 0, 83, "string(string str)"}, + {"altstr_get", PF_Fixme, 0, 0, 0, 84, "string(string str, float num)"}, + {"altstr_set", PF_Fixme, 0, 0, 0, 85, "string(string str, float num, string set) "}, + {"altstr_ins", PF_Fixme, 0, 0, 0, 86, "string(string str, float num, string set)"}, + {"findflags", PF_Fixme, 0, 0, 0, 87, "entity(entity start, .float field, float match)"}, + {"findchainflags", PF_Fixme, 0, 0, 0, 88, "entity(.float field, float match)"}, + {"mcvar_defstring", PF_Fixme, 0, 0, 0, 89, "string(string name) " STUB}, + //end menu-only 'standard' +#endif + //nq qw h2 ebfs {"ignore", PF_Ignore, 0, 0, 0, 0, "void()"}, {"makevectors", PF_makevectors, 1, 1, 1, 0, "void(vector vang)"}, {"setorigin", PF_setorigin, 2, 2, 2, 0, "void(entity e, vector o)"}, @@ -9117,7 +9220,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //2d (immediate) operations {"drawline", PF_Fixme, 0, 0, 0, 315, "void(float width, vector pos1, vector pos2)"},// (EXT_CSQC) {"iscachedpic", PF_Fixme, 0, 0, 0, 316, "float(string name)"},// (EXT_CSQC) - {"precache_pic", PF_Fixme, 0, 0, 0, 317, "string(string name, float trywad)"},// (EXT_CSQC) + {"precache_pic", PF_Fixme, 0, 0, 0, 317, "string(string name, optional float trywad)"},// (EXT_CSQC) {"draw_getimagesize",PF_Fixme, 0, 0, 0, 318, "vector(string picname)"},// (EXT_CSQC) {"freepic", PF_Fixme, 0, 0, 0, 319, "void(string name)"},// (EXT_CSQC) //320 @@ -9208,7 +9311,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //DP_QC_COPYENTITY {"copyentity", PF_copyentity, 0, 0, 0, 400, "void(entity from, entity to)"},// (DP_QC_COPYENTITY) //DP_SV_SETCOLOR - {"setcolors", PF_setcolors, 0, 0, 0, 401, "void(entity from, entity to)"},// + {"setcolors", PF_setcolors, 0, 0, 0, 401, "void(entity from, entity to)"},//DP_SV_SETCOLOR //DP_QC_FINDCHAIN {"findchain", PF_sv_findchain, 0, 0, 0, 402, "entity(.string field, string match)"},// (DP_QC_FINDCHAIN) //DP_QC_FINDCHAINFLOAT @@ -9262,6 +9365,41 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"getsurfacetexture",PF_getsurfacetexture,0, 0, 0, 437, "string(entity e, float s)"},// (DP_QC_GETSURFACE) {"getsurfacenearpoint",PF_getsurfacenearpoint,0,0, 0, 438, "float(entity e, vector p)"},// (DP_QC_GETSURFACE) {"getsurfaceclippedpoint",PF_getsurfaceclippedpoint,0,0,0, 439, "vector(entity e, float s, vector p)" STUB},// (DP_QC_GETSURFACE) + +#ifndef SERVERONLY + //begin menu-only + {"buf_create", PF_Fixme, 0, 0, 0, 440, "float()"},//DP_QC_STRINGBUFFERS + {"buf_del", PF_Fixme, 0, 0, 0, 441, "void(float bufhandle)"},//DP_QC_STRINGBUFFERS + {"buf_getsize", PF_Fixme, 0, 0, 0, 442, "float(float bufhandle)"},//DP_QC_STRINGBUFFERS + {"buf_copy", PF_Fixme, 0, 0, 0, 443, "void(float bufhandle_from, float bufhandle_to)"},//DP_QC_STRINGBUFFERS + {"buf_sort", PF_Fixme, 0, 0, 0, 444, "void(float bufhandle, float sortpower, float backward)"},//DP_QC_STRINGBUFFERS + {"buf_implode", PF_Fixme, 0, 0, 0, 445, "string(float bufhandle, string glue)"},//DP_QC_STRINGBUFFERS + {"bufstr_get", PF_Fixme, 0, 0, 0, 446, "string(float bufhandle, float string_index)"},//DP_QC_STRINGBUFFERS + {"bufstr_set", PF_Fixme, 0, 0, 0, 447, "void(float bufhandle, float string_index, string str)"},//DP_QC_STRINGBUFFERS + {"bufstr_add", PF_Fixme, 0, 0, 0, 448, "float(float bufhandle, string str, float order)"},//DP_QC_STRINGBUFFERS + {"bufstr_free", PF_Fixme, 0, 0, 0, 449, "void(float bufhandle, float string_index)"},//DP_QC_STRINGBUFFERS + {"iscachedpic", PF_Fixme, 0, 0, 0, 451, "float(string name)"},// (EXT_CSQC) + {"precache_pic", PF_Fixme, 0, 0, 0, 452, "string(string name, optional float trywad)"},// (EXT_CSQC) + {"freepic", PF_Fixme, 0, 0, 0, 453, "void(string name)"},// (EXT_CSQC) + {"drawcharacter", PF_Fixme, 0, 0, 0, 454, "float(vector position, float character, vector scale, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???]) + {"drawrawstring", PF_Fixme, 0, 0, 0, 455, "float(vector position, string text, vector scale, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???]) + {"drawpic", PF_Fixme, 0, 0, 0, 456, "float(vector position, string pic, vector size, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???]) + {"drawfill", PF_Fixme, 0, 0, 0, 457, "float(vector position, vector size, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???]) + {"drawsetcliparea", PF_Fixme, 0, 0, 0, 458, "void(float x, float y, float width, float height)"},// (EXT_CSQC_???) + {"drawresetcliparea",PF_Fixme, 0, 0, 0, 459, "void(void)"},// (EXT_CSQC_???) + {"drawgetimagesize",PF_Fixme, 0, 0, 0, 460, "vector(string picname)"},// (EXT_CSQC) + {"cin_open", PF_Fixme, 0, 0, 0, 461, "float(string file, string id)" STUB}, + {"cin_close", PF_Fixme, 0, 0, 0, 462, "void(string id)" STUB}, + {"cin_setstate", PF_Fixme, 0, 0, 0, 463, "void(string id, float newstate)" STUB}, + {"cin_getstate", PF_Fixme, 0, 0, 0, 464, "float(string id)" STUB}, + {"cin_restart", PF_Fixme, 0, 0, 0, 465, "void(string file)" STUB}, + {"drawline", PF_Fixme, 0, 0, 0, 466, "void(float width, vector pos1, vector pos2)"},// (EXT_CSQC) + {"drawstring", PF_Fixme, 0, 0, 0, 467, "float(vector position, string text, vector scale, vector rgb, float alpha, float flag)"},// #326 + {"stringwidth", PF_Fixme, 0, 0, 0, 468, "float(string text, float usecolours, optional vector fontsize)"},// EXT_CSQC_'DARKPLACES' + {"drawsubpic", PF_Fixme, 0, 0, 0, 469, "void(vector pos, vector sz, string pic, vector srcpos, vector srcsz, vector rgb, float alpha, float flag)"},// #328 EXT_CSQC_'DARKPLACES' + //end menu-only +#endif + //begin non-menu {"clientcommand", PF_clientcommand, 0, 0, 0, 440, "void(entity e, string s)"},// (KRIMZON_SV_PARSECLIENTCOMMAND) {"tokenize", PF_Tokenize, 0, 0, 0, 441, "float(string s)"},// (KRIMZON_SV_PARSECLIENTCOMMAND) {"argv", PF_ArgV, 0, 0, 0, 442, "string(float n)"},// (KRIMZON_SV_PARSECLIENTCOMMAND @@ -9292,6 +9430,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"bufstr_set", PF_bufstr_set, 0, 0, 0, 467, "void(float bufhandle, float string_index, string str)"},//DP_QC_STRINGBUFFERS {"bufstr_add", PF_bufstr_add, 0, 0, 0, 468, "float(float bufhandle, string str, float order)"},//DP_QC_STRINGBUFFERS {"bufstr_free", PF_bufstr_free, 0, 0, 0, 469, "void(float bufhandle, float string_index)"},//DP_QC_STRINGBUFFERS + //end non-menu + // {"undefined", PF_Fixme, 0, 0, 0, 470, ""}, //MENU VM BUILTINS SHARE THE BELOW BUILTINS {"asin", PF_asin, 0, 0, 0, 471, "float(float s)"},//DP_QC_ASINACOSATANATAN2TAN @@ -9344,8 +9484,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"buf_cvarlist", PF_buf_cvarlist, 0, 0, 0, 517, "void(float strbuf)" STUB}, {"cvar_description",PF_cvar_description,0, 0, 0, 518, "string(string cvarname)"}, {"gettime", PF_Fixme, 0, 0, 0, 519, "float(optional float timetype)"}, -// {"keynumtostring", PF_Fixme, 0, 0, 0, 520, "string(float keynum)"}, -// {"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, "string(string command, optional float bindmap)"}, + {"keynumtostring", PF_Fixme, 0, 0, 0, 520, "string(float keynum)"}, + {"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, "string(string command, optional float bindmap)"}, // {"initparticlespawner",PF_Fixme, 0, 0, 0, 522, "void(float max_themes)"}, // {"resetparticle", PF_Fixme, 0, 0, 0, 523, "void()"}, // {"particletheme", PF_Fixme, 0, 0, 0, 524, "void(float theme)"}, @@ -9373,31 +9513,31 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"physics_addforce",PF_Ignore, 0, 0, 0, 541, "void(entity e, vector force, vector relative_ofs)" STUB}, {"physics_addtorque",PF_Ignore, 0, 0, 0, 542, "void(entity e, vector torque)" STUB}, -// {"setkeydest", PF_Fixme, 0, 0, 0, 601, "void(float dest)"}, -// {"getkeydest", PF_Fixme, 0, 0, 0, 602, "float()"}, -// {"setmousetarget", PF_Fixme, 0, 0, 0, 603, "void(float trg)"}, -// {"getmousetarget", PF_Fixme, 0, 0, 0, 604, "float()"}, + {"setkeydest", PF_Fixme, 0, 0, 0, 601, "void(float dest)"}, + {"getkeydest", PF_Fixme, 0, 0, 0, 602, "float()"}, + {"setmousetarget", PF_Fixme, 0, 0, 0, 603, "void(float trg)"}, + {"getmousetarget", PF_Fixme, 0, 0, 0, 604, "float()"}, {"callfunction", PF_callfunction, 0, 0, 0, 605, "void(.../*, string funcname*/)"}, {"writetofile", PF_writetofile, 0, 0, 0, 606, "void(float fh, entity e)"}, {"isfunction", PF_isfunction, 0, 0, 0, 607, "float(string s)"}, -// {"getresolution", PF_Fixme, 0, 0, 0, 608, "vector(float number, optional float forfullscreen)"}, -// {"keynumtostring", PF_Fixme, 0, 0, 0, 609, "string(float keynum)"}, -// {"findkeysforcommand",PF_Fixme, 0, 0, 0, 610, "string()"}, -// {"gethostcachevalue",PF_Fixme, 0, 0, 0, 611, "float(float type)"}, -// {"gethostcachestring",PF_Fixme, 0, 0, 0, 612, "string(float type, float hostnr)"}, + {"getresolution", PF_Fixme, 0, 0, 0, 608, "vector(float vidmode, optional float forfullscreen)"}, + {"keynumtostring", PF_Fixme, 0, 0, 0, 609, "string(float keynum)"}, + {"findkeysforcommand",PF_Fixme, 0, 0, 0, 610, "string(string command, optional float bindmap)"}, + {"gethostcachevalue",PF_Fixme, 0, 0, 0, 611, "float(float type)"}, + {"gethostcachestring",PF_Fixme, 0, 0, 0, 612, "string(float type, float hostnr)"}, {"parseentitydata", PF_parseentitydata, 0, 0, 0, 613, "void(entity e, string s)"}, -// {"stringtokeynum", PF_Fixme, 0, 0, 0, 614, "float(string key)"}, -// {"resethostcachemasks",PF_Fixme, 0, 0, 0, 615, "void()"}, -// {"sethostcachemaskstring",PF_Fixme, 0, 0, 0, 616, "void(float mask, float fld, string str, float op)"}, -// {"sethostcachemasknumber",PF_Fixme, 0, 0, 0, 617, "void(float mask, float fld, float num, float op)"}, -// {"resorthostcache", PF_Fixme, 0, 0, 0, 618, "void()"}, -// {"sethostcachesort",PF_Fixme, 0, 0, 0, 619, "void(float fld, float descending)"}, -// {"refreshhostcache",PF_Fixme, 0, 0, 0, 620, "void()"}, -// {"gethostcachenumber",PF_Fixme, 0, 0, 0, 621, "float(float fld, float hostnr)"}, -// {"gethostcacheindexforkey",PF_Fixme, 0, 0, 0, 622, "float(string key)"}, -// {"addwantedhostcachekey",PF_Fixme, 0, 0, 0, 623, "void(string key)"}, -// {"getextresponse", PF_Fixme, 0, 0, 0, 624, "string()"}, -// {"netaddress_resolve",PF_Fixme, 0, 0, 0, 625, "string(string, float)"}, + {"stringtokeynum", PF_Fixme, 0, 0, 0, 614, "float(string key)"}, + {"resethostcachemasks",PF_Fixme, 0, 0, 0, 615, "void()"}, + {"sethostcachemaskstring",PF_Fixme, 0, 0, 0, 616, "void(float mask, float fld, string str, float op)"}, + {"sethostcachemasknumber",PF_Fixme, 0, 0, 0, 617, "void(float mask, float fld, float num, float op)"}, + {"resorthostcache", PF_Fixme, 0, 0, 0, 618, "void()"}, + {"sethostcachesort",PF_Fixme, 0, 0, 0, 619, "void(float fld, float descending)"}, + {"refreshhostcache",PF_Fixme, 0, 0, 0, 620, "void()"}, + {"gethostcachenumber",PF_Fixme, 0, 0, 0, 621, "float(float fld, float hostnr)"}, + {"gethostcacheindexforkey",PF_Fixme, 0, 0, 0, 622, "float(string key)"}, + {"addwantedhostcachekey",PF_Fixme, 0, 0, 0, 623, "void(string key)"}, + {"getextresponse", PF_Fixme, 0, 0, 0, 624, "string()"}, + {"netaddress_resolve",PF_Fixme, 0, 0, 0, 625, "string(string, float)"}, // {"getgamedirinfo", PF_Fixme, 0, 0, 0, 626, "string(float n, float prop)"}, {"sprintf", PF_sprintf, 0, 0, 0, 627, "string(string fmt, ...)"}, {"getsurfacenumtriangles",PF_getsurfacenumtriangles,0,0,0, 628, "float(entity e, float s)"}, @@ -9405,15 +9545,15 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs // {"setkeybind", PF_Fixme, 0, 0, 0, 630, "float(float key, string bind, optional float bindmap)"}, // {"getbindmaps", PF_Fixme, 0, 0, 0, 631, "vector()"}, // {"setbindmaps", PF_Fixme, 0, 0, 0, 632, "float(vector bm)"}, -// {"crypto_getkeyfp", PF_Fixme, 0, 0, 0, 633, "string(string addr)"}, -// {"crypto_getidfp", PF_Fixme, 0, 0, 0, 634, "string(string addr)"}, -// {"crypto_getencryptlevel",PF_Fixme, 0, 0, 0, 635, "string(string addr)"}, -// {"crypto_getmykeyfp",PF_Fixme, 0, 0, 0, 636, "string(string addr)"}, -// {"crypto_getmyidfp",PF_Fixme, 0, 0, 0, 637, "string(float addr)"}, + {"crypto_getkeyfp", PF_Fixme, 0, 0, 0, 633, "string(string addr)" STUB}, + {"crypto_getidfp", PF_Fixme, 0, 0, 0, 634, "string(string addr)" STUB}, + {"crypto_getencryptlevel",PF_Fixme, 0, 0, 0, 635, "string(string addr)" STUB}, + {"crypto_getmykeyfp",PF_Fixme, 0, 0, 0, 636, "string(string addr)" STUB}, + {"crypto_getmyidfp",PF_Fixme, 0, 0, 0, 637, "string(float addr)" STUB}, // {"VM_CL_RotateMoves",PF_Fixme, 0, 0, 0, 638, ""}, {"digest_hex", PF_digest_hex, 0, 0, 0, 639, "string(string digest, string data, ...)"}, // {"V_CalcRefdef", PF_Fixme, 0, 0, 0, 640, "void(entity e)"}, - {"crypto_getmyidstatus",PF_Fixme, 0, 0, 0, 641, "float(float i)"}, + {"crypto_getmyidstatus",PF_Fixme, 0, 0, 0, 641, "float(float i)" STUB}, //end dp extras @@ -9729,11 +9869,15 @@ svextqcfields PR_RegisterFieldVar(svprogfuncs, 0, NULL, 0,0); } +//targets #define QW 1 #define NQ 2 #define CS 4 -#define FTE 8 -#define ALL (QW|NQ|CS) +#define MENU 8 +#define H2 16 +//mere flags +#define FTE 32 +#define ALL (QW|NQ|CS|MENU) #define CORE typedef struct { @@ -9745,6 +9889,7 @@ typedef struct char *valuestr; qboolean misc; } knowndef_t; +#include "cl_master.h" void PR_DumpPlatform_f(void) { #ifdef SERVERONLY @@ -9764,7 +9909,7 @@ void PR_DumpPlatform_f(void) /*this list is here to ensure that the file can be used as a valid initial qc file (ignoring precompiler options)*/ knowndef_t knowndefs[] = { - {"self", "entity", QW|NQ|CS}, + {"self", "entity", QW|NQ|CS|MENU}, {"other", "entity", QW|NQ|CS}, {"world", "entity", QW|NQ|CS}, {"time", "float", QW|NQ|CS}, @@ -9812,7 +9957,7 @@ void PR_DumpPlatform_f(void) {"ClientDisconnect", "void()", QW|NQ}, {"SetNewParms", "void()", QW|NQ}, {"SetChangeParms", "void()", QW|NQ}, - {"end_sys_globals", "void", QW|NQ|CS}, + {"end_sys_globals", "void", QW|NQ|CS|MENU}, {"modelindex", ".float", QW|NQ|CS}, {"absmin, absmax", ".vector", QW|NQ|CS}, @@ -9901,7 +10046,7 @@ void PR_DumpPlatform_f(void) {"noise1", ".string", QW|NQ}, {"noise2", ".string", QW|NQ}, {"noise3", ".string", QW|NQ}, - {"end_sys_fields", "void", QW|NQ|CS}, + {"end_sys_fields", "void", QW|NQ|CS|MENU}, #define comfieldfloat(name) {#name, ".float", FL}, #define comfieldvector(name) {#name, ".vector", FL}, @@ -9911,7 +10056,7 @@ void PR_DumpPlatform_f(void) #define FL QW|NQ comqcfields #undef FL -#define FL ALL +#define FL QW|NQ|CS comextqcfields #undef FL #define FL QW|NQ @@ -9926,12 +10071,61 @@ void PR_DumpPlatform_f(void) #undef comfieldstring #undef comfieldfunction - {"physics_mode", "var float", QW|NQ|CS, 2}, - {"gamespeed", "float", CS}, - {"drawfont", "float", CS}, + {"SpectatorConnect", "noref void()", QW|NQ}, + {"SpectatorDisconnect", "noref void()", QW|NQ}, + {"SpectatorThink", "noref void()", QW|NQ}, + {"SV_ParseClientCommand", "noref void()", QW|NQ}, + {"SV_ParseConnectionlessPacket", "noref void()", QW|NQ}, + {"SV_PausedTic", "noref void()", QW|NQ}, + {"SV_ShouldPause", "noref void()", QW|NQ}, + {"ClassChangeWeapon", "noref void()", H2}, + {"SV_RunClientCommand", "noref void()", QW|NQ}, + {"SV_AddDebugPolygons", "noref void()", QW|NQ}, + {"SV_PlayerPhysics", "noref void()", QW|NQ}, + {"EndFrame", "noref void()", QW|NQ}, + /* //mvdsv compat + {"UserInfo_Changed", "//noref void()", QW}, + {"localinfoChanged", "//noref void()", QW}, + {"ChatMessage", "//noref void()", QW}, + {"UserCmd", "//noref void()", QW}, + {"ConsoleCmd", "//noref void()", QW}, + */ - {"TRUE", "const float", QW|NQ|CS, 1}, - {"FALSE", "const float", QW|NQ|CS, 0}, + {"CSQC_Init", "noref void(float apilevel, string enginename, float engineversion)", CS}, + {"CSQC_WorldLoaded", "noref void()", CS}, + {"CSQC_Shutdown", "noref void()", CS}, + {"CSQC_UpdateView", "noref void(float vwidth, float vheight, float notmenu)", CS}, + {"CSQC_Parse_StuffCmd", "noref void(string msg)", CS}, + {"CSQC_Parse_CenterPrint", "noref float(string msg)", CS}, + {"CSQC_Parse_Print", "noref void(string printmsg, float printlvl)", CS}, + {"CSQC_InputEvent", "noref float(float evtype, float scanx, float chary, float devid)", CS}, + {"CSQC_Input_Frame", "noref void()", CS}, + {"CSQC_ConsoleCommand", "noref float(string cmd)", CS}, + {"CSQC_ConsoleLink", "noref float(string text, string info)", CS}, + {"CSQC_Ent_Update", "noref void()", CS}, + {"CSQC_Ent_Remove", "noref void()", CS}, + {"CSQC_Event_Sound", "noref float(float entnum, float channel, float soundname, float vol, float attenuation, vector pos, float pitchmod)", CS}, +// {"CSQC_ServerSound", "//void()", CS}, + {"CSQC_LoadResource", "noref float(string resname, string restype)", CS}, + {"CSQC_Parse_TempEntity", "noref void()", CS}, + + {"GameCommand", "noref void(string cmdtext)", CS|MENU}, + + {"m_init", "void()", MENU}, + {"m_shutdown", "void()", MENU}, + {"m_draw", "void()", MENU}, + {"m_keydown", "void(float scan, float chr)", MENU}, + {"m_keyup", "void(float scan, float chr)", MENU}, + {"m_toggle", "void(float mode)", MENU}, + + {"physics_mode", "var float", QW|NQ|CS, 2}, + {"gamespeed", "float", CS}, + {"drawfontscale", "var vector", CS|MENU, 0, "'1 1 0'"}, + {"drawfont", "float", CS|MENU}, + {"FONT_DEFAULT", "const float", CS|MENU, 0}, + + {"TRUE", "const float", ALL, 1}, + {"FALSE", "const float", ALL, 0}, {"MOVETYPE_NONE", "const float", QW|NQ|CS, MOVETYPE_NONE}, {"MOVETYPE_WALK", "const float", QW|NQ|CS, MOVETYPE_WALK}, @@ -10014,17 +10208,17 @@ void PR_DumpPlatform_f(void) {"PVSF_IGNOREPVS", "const float", QW|NQ, PVSF_IGNOREPVS}, {"PVSF_NOREMOVE", "const float", QW|NQ, PVSF_NOREMOVE}, - {"INFOKEY_P_IP", "const string", QW|NQ, 0, "ip"}, - {"INFOKEY_P_REALIP", "const string", QW|NQ, 0, "realip"}, - {"INFOKEY_P_CSQCACTIVE","const string", QW|NQ, 0, "csqcactive"}, - {"INFOKEY_P_PING", "const string", QW|NQ, 0, "ping"}, - {"INFOKEY_P_SVPING", "const string", QW|NQ, 0, "svping"}, - {"INFOKEY_P_GUID", "const string", QW|NQ, 0, "guid"}, - {"INFOKEY_P_CHALLENGE", "const string", QW|NQ, 0, "challenge"}, - {"INFOKEY_P_USERID", "const string", QW|NQ, 0, "*userid"}, - {"INFOKEY_P_DOWNLOADPCT","const string",QW|NQ, 0, "download"}, - {"INFOKEY_P_TRUSTLEVEL","const string", QW|NQ, 0, "trustlevel"}, - {"INFOKEY_P_PROTOCOL", "const string", QW|NQ, 0, "protocol"}, + {"INFOKEY_P_IP", "const string", QW|NQ, 0, "\"ip\""}, + {"INFOKEY_P_REALIP", "const string", QW|NQ, 0, "\"realip\""}, + {"INFOKEY_P_CSQCACTIVE","const string", QW|NQ, 0, "\"csqcactive\""}, + {"INFOKEY_P_PING", "const string", QW|NQ, 0, "\"ping\""}, + {"INFOKEY_P_SVPING", "const string", QW|NQ, 0, "\"svping\""}, + {"INFOKEY_P_GUID", "const string", QW|NQ, 0, "\"guid\""}, + {"INFOKEY_P_CHALLENGE", "const string", QW|NQ, 0, "\"challenge\""}, + {"INFOKEY_P_USERID", "const string", QW|NQ, 0, "\"*userid\""}, + {"INFOKEY_P_DOWNLOADPCT","const string",QW|NQ, 0, "\"download\""}, + {"INFOKEY_P_TRUSTLEVEL","const string", QW|NQ, 0, "\"trustlevel\""}, + {"INFOKEY_P_PROTOCOL", "const string", QW|NQ, 0, "\"protocol\""}, // edict.flags {"FL_FLY", "const float", QW|NQ|CS, FL_FLY}, @@ -10137,9 +10331,9 @@ void PR_DumpPlatform_f(void) {"CLIENTTYPE_BOT", "const float", QW|NQ, CLIENTTYPE_BOT}, {"CLIENTTYPE_NOTACLIENT","const float",QW|NQ, CLIENTTYPE_NOTACLIENT}, - {"FILE_READ", "const float", QW|NQ|CS, FRIK_FILE_READ}, - {"FILE_APPEND", "const float", QW|NQ|CS, FRIK_FILE_APPEND}, - {"FILE_WRITE", "const float", QW|NQ|CS, FRIK_FILE_WRITE}, + {"FILE_READ", "const float", ALL, FRIK_FILE_READ}, + {"FILE_APPEND", "const float", ALL, FRIK_FILE_APPEND}, + {"FILE_WRITE", "const float", ALL, FRIK_FILE_WRITE}, {"FILE_READNL", "const float", QW|NQ|CS, FRIK_FILE_READNL}, {"FILE_MMAP_READ", "const float", QW|NQ|CS, FRIK_FILE_MMAP_READ}, {"FILE_MMAP_RW", "const float", QW|NQ|CS, FRIK_FILE_MMAP_RW}, @@ -10188,6 +10382,25 @@ void PR_DumpPlatform_f(void) {"TEREDIT_MESH_ADD", "const float", CS, ter_mesh_add}, {"TEREDIT_MESH_KILL", "const float", CS, ter_mesh_kill}, {"TEREDIT_TINT", "const float", CS, ter_tint}, + + {"SLIST_HOSTCACHEVIEWCOUNT", "const float", MENU, SLIST_HOSTCACHEVIEWCOUNT}, + {"SLIST_HOSTCACHETOTALCOUNT", "const float", MENU, SLIST_HOSTCACHETOTALCOUNT}, + {"SLIST_MASTERQUERYCOUNT", "const float", MENU, SLIST_MASTERQUERYCOUNT}, + {"SLIST_MASTERREPLYCOUNT", "const float", MENU, SLIST_MASTERREPLYCOUNT}, + {"SLIST_SERVERQUERYCOUNT", "const float", MENU, SLIST_SERVERQUERYCOUNT}, + {"SLIST_SERVERREPLYCOUNT", "const float", MENU, SLIST_SERVERREPLYCOUNT}, + {"SLIST_SORTFIELD", "const float", MENU, SLIST_SORTFIELD}, + {"SLIST_SORTDESCENDING", "const float", MENU, SLIST_SORTDESCENDING}, + {"SLIST_TEST_CONTAINS", "const float", MENU, SLIST_TEST_CONTAINS}, + {"SLIST_TEST_NOTCONTAIN", "const float", MENU, SLIST_TEST_NOTCONTAIN}, + {"SLIST_TEST_LESSEQUAL", "const float", MENU, SLIST_TEST_LESSEQUAL}, + {"SLIST_TEST_LESS", "const float", MENU, SLIST_TEST_LESS}, + {"SLIST_TEST_EQUAL", "const float", MENU, SLIST_TEST_EQUAL}, + {"SLIST_TEST_GREATER", "const float", MENU, SLIST_TEST_GREATER}, + {"SLIST_TEST_GREATEREQUAL", "const float", MENU, SLIST_TEST_GREATEREQUAL}, + {"SLIST_TEST_NOTEQUAL", "const float", MENU, SLIST_TEST_NOTEQUAL}, + {"SLIST_TEST_STARTSWITH", "const float", MENU, SLIST_TEST_STARTSWITH}, + {"SLIST_TEST_NOTSTARTSWITH", "const float", MENU, SLIST_TEST_NOTSTARTSWITH}, NULL }; @@ -10202,6 +10415,10 @@ void PR_DumpPlatform_f(void) targ |= CS; if (!stricmp(Cmd_Argv(i), "-Tqw")) targ |= QW; + if (!stricmp(Cmd_Argv(i), "-Tmenu")) + targ |= MENU; + if (!stricmp(Cmd_Argv(i), "-Th2")) + targ |= H2; if (!stricmp(Cmd_Argv(i), "-Fdefines")) defines = true; if (!stricmp(Cmd_Argv(i), "-Fnodefines")) @@ -10210,7 +10427,7 @@ void PR_DumpPlatform_f(void) fname = Cmd_Argv(++i); } if (!(targ & ALL)) - targ |= ALL; + targ |= (QW|NQ|CS|MENU); if (!*fname) fname = "fteextensions"; @@ -10233,6 +10450,7 @@ void PR_DumpPlatform_f(void) "-Tnq - dump specifically NQ fields\n" "-Tqw - dump specifically QW fields\n" "-Tcs - dump specifically CSQC fields\n" + "-Tmenu - dump specifically menuqc fields\n" "-Fdefines - generate #defines instead of constants\n" "-O - write to a different qc file\n" "*/\n" @@ -10243,23 +10461,55 @@ void PR_DumpPlatform_f(void) VFS_PRINTF(f, "#pragma warning error Q101 /*too many parms*/\n"); VFS_PRINTF(f, "#pragma warning error Q105 /*too few parms*/\n"); VFS_PRINTF(f, "#pragma warning error Q208 /*system crc unknown*/\n"); + VFS_PRINTF(f, "#pragma warning enable F301 /*non-utf-8 strings*/\n"); + VFS_PRINTF(f, "#pragma warning enable F302 /*uninitialised locals*/\n"); if (targ&FTE) VFS_PRINTF(f, "#pragma target FTE\n"); if ((targ&ALL) == CS) - VFS_PRINTF(f, "#define CSQC\n"); + VFS_PRINTF(f, "#ifndef CSQC\n" + "#define CSQC\n" + "#endif\n" + ); else if ((targ&ALL) == NQ) - VFS_PRINTF(f, "#define NETQUAKE\n" - "#define SSQC\n" + VFS_PRINTF(f, "#ifndef NETQUAKE\n" + "#define NETQUAKE\n" + "#endif\n" + "#ifndef NQSSQC\n" + "#define NQSSQC\n" + "#endif\n" + "#ifndef SSQC\n" + "#define SSQC\n" + "#endif\n" ); else if ((targ&ALL) == QW) - VFS_PRINTF(f, "#define QUAKEWORLD\n" - "#define SSQC\n" + VFS_PRINTF(f, "#ifndef QUAKEWORLD\n" + "#define QUAKEWORLD\n" + "#endif\n" + "#ifndef QWSSQC\n" + "#define QWSSQC\n" + "#endif\n" + "#ifndef SSQC\n" + "#define SSQC\n" + "#endif\n" + ); + else if ((targ&ALL) == MENU) + VFS_PRINTF(f, "#ifndef MENU\n" + "#define MENU\n" + "#endif\n" ); else - VFS_PRINTF(f, "#if !defined(CSQC) && !defined(SSQC)\n" + VFS_PRINTF(f, "#if !defined(CSQC) && !defined(NQSSQC) && !defined(QWSSQC)&& !defined(MENU)\n" + "#ifdef QUAKEWORLD\n" + "#define QWSSQC\n" + "#else\n" + "#define NQSSQC\n" + "#endif\n" + "#endif\n" + "#if !defined(SSQC) && (defined(QWSSQC) || defined(NQSSQC))\n" "#define SSQC\n" - "#endif\n"); + "#endif\n" + ); for (i = 0; knowndefs[i].name; i++) { @@ -10270,43 +10520,70 @@ void PR_DumpPlatform_f(void) } } - d = ALL; + d = ALL & ~targ; for (i = 0; knowndefs[i].name; i++) { nd = (knowndefs[i].module & targ) | (~targ & ALL); - if (nd != d) + if (!(nd & targ)) + continue; + if ((nd&targ) != (d&targ)) { - if (!(nd & targ)) - continue; - - if (d != ALL) + if (d != (ALL & ~targ)) VFS_PRINTF(f, "#endif\n"); - d = nd; - - switch(d) + if (((nd | (~targ)) & ALL) == ALL) + d = ALL & ~targ; //every part of the target is specified, so don't do the ifdef thing. + else { - case 0: - continue; - case QW: - VFS_PRINTF(f, "#if defined(SSQC) && !defined(NETQUAKE)\n"); - break; - case NQ: - VFS_PRINTF(f, "#if defined(SSQC) && defined(NETQUAKE)\n"); - break; - case QW|NQ: - VFS_PRINTF(f, "#ifdef SSQC\n"); - break; - case CS: - VFS_PRINTF(f, "#ifdef CSQC\n"); - break; - case QW|CS: - VFS_PRINTF(f, "#if defined(CSQC) || (defined(SSQC) && !defined(NETQUAKE))\n"); - break; - case NQ|CS: - VFS_PRINTF(f, "#if defined(CSQC) || (defined(SSQC) && defined(NETQUAKE))\n"); - break; - case ALL: - break; + d = nd; + switch(d & (ALL & targ)) + { + case 0: + continue; + case QW: + VFS_PRINTF(f, "#if defined(QWSSQC)\n"); + break; + case NQ: + VFS_PRINTF(f, "#if defined(NQSSQC)\n"); + break; + case QW|NQ: + VFS_PRINTF(f, "#ifdef SSQC\n"); + break; + case CS: + VFS_PRINTF(f, "#ifdef CSQC\n"); + break; + case QW|CS: + VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC)\n"); + break; + case NQ|CS: + VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC)\n"); + break; + case NQ|CS|QW: + VFS_PRINTF(f, "#if defined(CSQC) || defined(SSQC)\n"); + break; + case MENU: + VFS_PRINTF(f, "#ifdef MENU\n"); + break; + case QW|MENU: + VFS_PRINTF(f, "#if defined(QWSSQC) || defined(MENU)\n"); + break; + case NQ|MENU: + VFS_PRINTF(f, "#if defined(NQSSQC) || defined(MENU)\n"); + break; + case QW|NQ|MENU: + VFS_PRINTF(f, "#if defined(SSQC) || defined(MENU)\n"); + break; + case CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"); + break; + case QW|CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); + break; + case NQ|CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); + break; + case ALL: + break; + } } } if (!strcmp(knowndefs[i].type, "const float")) @@ -10319,13 +10596,13 @@ void PR_DumpPlatform_f(void) else if (!strcmp(knowndefs[i].type, "const string")) { if (defines) - VFS_PRINTF(f, "#define %s \"%s\"\n", knowndefs[i].name, knowndefs[i].valuestr); + VFS_PRINTF(f, "#define %s %s\n", knowndefs[i].name, knowndefs[i].valuestr); else - VFS_PRINTF(f, "%s %s = \"%s\";\n", knowndefs[i].type, knowndefs[i].name, knowndefs[i].valuestr); + VFS_PRINTF(f, "%s %s = %s;\n", knowndefs[i].type, knowndefs[i].name, knowndefs[i].valuestr); } else if (knowndefs[i].valuestr) { - VFS_PRINTF(f, "%s %s = \"%s\";\n", knowndefs[i].type, knowndefs[i].name, knowndefs[i].valuestr); + VFS_PRINTF(f, "%s %s = %s;\n", knowndefs[i].type, knowndefs[i].name, knowndefs[i].valuestr); } else if (knowndefs[i].value) { @@ -10334,10 +10611,6 @@ void PR_DumpPlatform_f(void) else VFS_PRINTF(f, "%s %s;\n", knowndefs[i].type, knowndefs[i].name); } - if (d != ALL) - VFS_PRINTF(f, "#endif\n"); - - d = ALL; for (i = 0; BuiltinList[i].name; i++) { if (BuiltinList[i].obsolete) @@ -10349,67 +10622,103 @@ void PR_DumpPlatform_f(void) idx = BuiltinList[i].nqnum; else if (BuiltinList[i].qwnum) idx = BuiltinList[i].qwnum; + else if (BuiltinList[i].h2num) + idx = BuiltinList[i].h2num; else idx = 0; nd = 0; - if (BuiltinList[i].ebfsnum == idx) - nd |= NQ|QW; - if (BuiltinList[i].nqnum == idx) - nd |= NQ; - if (BuiltinList[i].qwnum == idx) - nd |= QW; + + if (BuiltinList[i].bifunc != PF_Fixme && BuiltinList[i].bifunc != PF_Ignore) + { + if (BuiltinList[i].ebfsnum == idx) + nd |= NQ|QW; + if (BuiltinList[i].nqnum == idx) + nd |= NQ; + if (BuiltinList[i].qwnum == idx) + nd |= QW; + if (BuiltinList[i].h2num == idx) + nd |= H2; + } if (idx) { if (PR_CSQC_BuiltinValid(BuiltinList[i].name, idx)) - { nd |= CS; - if (BuiltinList[i].bifunc == PF_Fixme || BuiltinList[i].bifunc == PF_Ignore) - nd &= CS; /*csqc only*/ - } - else + if (MP_BuiltinValid(BuiltinList[i].name, idx)) + nd |= MENU; + + if (!nd) { - if (BuiltinList[i].bifunc == PF_Fixme || BuiltinList[i].bifunc == PF_Ignore) - { - /*neither*/ - BuiltinList[i].obsolete = true; - nd = d; /*don't switch ifdefs*/ - } + /*no idea what its for*/ + BuiltinList[i].obsolete = true; + nd = d; /*don't switch ifdefs*/ } - if (nd != d) + nd |= (~targ & ALL); + if (!(nd & targ)) + continue; + if ((nd&targ) != (d&targ)) { - if (!(nd & targ)) - continue; - - if (d != ALL) + if (d != (ALL & ~targ)) VFS_PRINTF(f, "#endif\n"); - d = nd; - switch(d) + if (((nd | (~targ)) & ALL) == ALL) + d = ALL & ~targ; + else { - case 0: - continue; - case QW: - VFS_PRINTF(f, "#if defined(SSQC) && !defined(NETQUAKE)\n"); - break; - case NQ: - VFS_PRINTF(f, "#if defined(SSQC) && defined(NETQUAKE)\n"); - break; - case QW|NQ: - VFS_PRINTF(f, "#ifdef SSQC\n"); - break; - case CS: - VFS_PRINTF(f, "#ifdef CSQC\n"); - break; - case QW|CS: - VFS_PRINTF(f, "#if defined(CSQC) || (defined(SSQC) && !defined(NETQUAKE))\n"); - break; - case NQ|CS: - VFS_PRINTF(f, "#if defined(CSQC) || (defined(SSQC) && defined(NETQUAKE))\n"); - break; - case ALL: - break; + d = nd; + switch(d & (ALL & targ)) + { + case 0: + continue; + case QW: + VFS_PRINTF(f, "#if defined(QWSSQC)\n"); + break; + case NQ: + VFS_PRINTF(f, "#if defined(NQSSQC)\n"); + break; + case QW|NQ: + VFS_PRINTF(f, "#ifdef SSQC\n"); + break; + case CS: + VFS_PRINTF(f, "#ifdef CSQC\n"); + break; + case QW|CS: + VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC)\n"); + break; + case NQ|CS: + VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC)\n"); + break; + case NQ|CS|QW: + VFS_PRINTF(f, "#if defined(CSQC) || defined(SSQC)\n"); + break; + case MENU: + VFS_PRINTF(f, "#ifdef MENU\n"); + break; + case QW|MENU: + VFS_PRINTF(f, "#if defined(QWSSQC) || defined(MENU)\n"); + break; + case NQ|MENU: + VFS_PRINTF(f, "#if defined(NQSSQC) || defined(MENU)\n"); + break; + case QW|NQ|MENU: + VFS_PRINTF(f, "#if defined(SSQC) || defined(MENU)\n"); + break; + case CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(MENU)\n"); + break; + case QW|CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(QWSSQC) || defined(MENU)\n"); + break; + case NQ|CS|MENU: + VFS_PRINTF(f, "#if defined(CSQC) || defined(NQSSQC) || defined(MENU)\n"); + break; + case ALL: + break; + default: + VFS_PRINTF(f, "#if 0 //???\n"); + break; + } } } VFS_PRINTF(f, "%s%s %s = #%u;", BuiltinList[i].obsolete?"//":"", BuiltinList[i].prototype, BuiltinList[i].name, idx); @@ -10435,7 +10744,7 @@ void PR_DumpPlatform_f(void) VFS_PRINTF(f, "\n"); } } - if (d != ALL) + if (d != (ALL & ~targ)) VFS_PRINTF(f, "#endif\n"); diff --git a/engine/server/savegame.c b/engine/server/savegame.c index a5c241863..e5cd8022e 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -907,6 +907,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame) // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); + sv.spawned_observer_slots--; } } } diff --git a/engine/server/server.h b/engine/server/server.h index 3cc4c3292..c5c14df23 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -142,6 +142,7 @@ typedef struct int allocated_client_slots; //number of slots available. (used mostly to stop single player saved games cacking up) int spawned_client_slots; //number of PLAYER slots which are active (ie: putclientinserver was called) + int spawned_observer_slots; model_t *models[MAX_MODELS]; qbyte *pvs, *phs; // fully expanded and decompressed @@ -1081,6 +1082,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse); void SV_PostRunCmd(void); void SV_SendClientPrespawnInfo(client_t *client); +void SV_ClientProtocolExtensionsChanged(client_t *client); //sv_master.c void SVM_Think(int port); diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index a26c88655..bb8f0f85c 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -603,12 +603,12 @@ void SV_Map_f (void) gametype->flags |= CVAR_SERVERINFO; Cvar_ForceSet(gametype, level); - gametype = Cvar_Get("g_gametype", "0", CVAR_LATCH|CVAR_SERVERINFO, "Q3 compatability"); + gametype = Cvar_Get("g_gametype", "", CVAR_LATCH|CVAR_SERVERINFO, "Q3 compatability"); gametype->callback = gtcallback; if (wasspmap) Cvar_ForceSet(gametype, "2");//singleplayer else if (gametype->value == 2) - Cvar_ForceSet(gametype, "0");//force to ffa deathmatch + Cvar_ForceSet(gametype, "");//force to ffa deathmatch } #endif @@ -628,7 +628,7 @@ void SV_Map_f (void) { /*pass the new map's name as an extension, so appropriate loading screens can be shown*/ if (ISNQCLIENT(host_client)) - SV_StuffcmdToClient(host_client, va("restart \"%s\"\n", level)); + SV_StuffcmdToClient(host_client, va("reconnect \"%s\"\n", level)); else SV_StuffcmdToClient(host_client, va("changing \"%s\"\n", level)); } @@ -647,6 +647,11 @@ void SV_Map_f (void) for (i=0, host_client = svs.clients ; isentents.num_entities = 0; + host_client->ratetime = 0; + if (host_client->pendingentbits) + host_client->pendingentbits[0] = UF_REMOVE; if (host_client->controller) continue; if (host_client->state>=cs_connected) diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 8852f3b7e..1f0e9d052 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -841,7 +841,7 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to if (to->hexen2flags != from->hexen2flags) bits |= UF_DRAWFLAGS; if (to->abslight != from->abslight) - bits |= UF_ABSLIGHT; + bits |= UF_DRAWFLAGS; if (to->colormod[0]!=from->colormod[0]||to->colormod[1]!=from->colormod[1]||to->colormod[2]!=from->colormod[2]) bits |= UF_COLORMOD; @@ -1014,10 +1014,16 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_ MSG_WriteByte(msg, state->trans); if (bits & UF_SCALE) MSG_WriteByte(msg, state->scale); - if (bits & UF_ABSLIGHT) - MSG_WriteByte(msg, state->abslight); + if (bits & UF_UNUSED3) + { +// MSG_WriteByte(msg, ); + } if (bits & UF_DRAWFLAGS) + { MSG_WriteByte(msg, state->hexen2flags); + if ((state->hexen2flags & MLS_MASKIN) == MLS_ABSLIGHT) + MSG_WriteByte(msg, state->abslight); + } if (bits & UF_TAGINFO) { MSG_WriteEntity(msg, state->tagentity); @@ -1091,16 +1097,28 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t unsigned int *resendbits; unsigned int *resendnum; unsigned int outno, outmax; - qboolean reset = (client->delta_sequence == -1) || (client->pendingentbits[0] & UF_REMOVE); + int sequence; + + if (ISNQCLIENT(client)) + sequence = client->netchan.outgoing_unreliable; + else + sequence = client->netchan.incoming_sequence; + + if (!client->pendingentbits) + return; + + if (client->delta_sequence <= 0) + client->pendingentbits[0] = UF_REMOVE; //if we're clearing the list and starting from scratch, just wipe all lingering state - if (reset) + if (client->pendingentbits[0] & UF_REMOVE) { - for (j = 0; j < client->sentents.max_entities; j++) + for (j = 0; j < client->sentents.num_entities; j++) { client->sentents.entities[j].number = 0; client->pendingentbits[j] = 0; } + client->pendingentbits[0] = UF_REMOVE; } //expand client's entstate list @@ -1113,6 +1131,8 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t memset(&client->sentents.entities[client->sentents.max_entities], 0, sizeof(client->sentents.entities[0]) * (j - client->sentents.max_entities)); client->sentents.max_entities = j; } + if (j > client->sentents.num_entities) + client->sentents.num_entities = j; } /*figure out the entitys+bits that changed (removed and active)*/ @@ -1142,13 +1162,16 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t } else { + //its valid, make sure we don't have a stale/resent remove, and do a cheap reset due to uncertainty. + if (client->pendingentbits[j] & UF_REMOVE) + client->pendingentbits[j] = (client->pendingentbits[j] & ~UF_REMOVE) | UF_RESET2; client->pendingentbits[j] |= SVFTE_DeltaCalcBits(o, n); } *o = *n; j++; } /*gaps are dead entities*/ - for (; j < client->sentents.max_entities; j++) + for (; j < client->sentents.num_entities; j++) { o = &client->sentents.entities[j]; if (o->number) @@ -1163,18 +1186,21 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t } /*cache frame info*/ - resendbits = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].resendentbits; - resendnum = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].resendentnum; + resendbits = client->frameunion.frames[sequence & UPDATE_MASK].resendentbits; + resendnum = client->frameunion.frames[sequence & UPDATE_MASK].resendentnum; outno = 0; - outmax = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].entities.max_entities; + outmax = client->frameunion.frames[sequence & UPDATE_MASK].entities.max_entities; /*start writing the packet*/ MSG_WriteByte (msg, svcfte_updateentities); + if (ISNQCLIENT(client)) + { + MSG_WriteLong(msg, client->netchan.incoming_unreliable); + } +// Con_Printf("Gen sequence %i\n", sequence); MSG_WriteFloat(msg, sv.world.physicstime); - if (reset) /*if we're resetting, the client will see 'remove world' which should be handled as a special case*/ - MSG_WriteShort(msg, 0x8000); - for(j = 0; j < client->sentents.max_entities; j++) + for(j = 0; j < client->sentents.num_entities; j++) { bits = client->pendingentbits[j]; if (!(bits & ~UF_RESET2)) //skip while there's nothing to send (skip reset2 if there's no other changes, its only to reduce chances of the client getting 'new' entities containing just an origin)*/ @@ -1186,10 +1212,10 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t client->pendingentbits[j] = 0; if (bits & UF_REMOVE) - { + { //if reset is set, then reset was set eroneously. SV_EmitDeltaEntIndex(msg, j, true, true); resendbits[outno] = UF_REMOVE; -// Con_Printf("REMOVE %i @ %i\n", j, client->netchan.incoming_sequence); +// Con_Printf("REMOVE %i @ %i\n", j, sequence); } else if (client->sentents.entities[j].number) /*only send a new copy of the ent if they actually have one already*/ { @@ -1198,7 +1224,7 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t /*if reset2, then this is the second packet sent to the client and should have a forced reset (but which isn't tracked)*/ resendbits[outno] = bits & ~UF_RESET2; bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, j)->baseline, &client->sentents.entities[j]); -// Con_Printf("RESET2 %i @ %i\n", j, client->netchan.incoming_sequence); +// Con_Printf("RESET2 %i @ %i\n", j, sequence); } else if (bits & UF_RESET) { @@ -1206,7 +1232,7 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t client->pendingentbits[j] = UF_RESET2; bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, j)->baseline, &client->sentents.entities[j]); resendbits[outno] = UF_RESET; -// Con_Printf("RESET %i @ %i\n", j, client->netchan.incoming_sequence); +// Con_Printf("RESET %i @ %i\n", j, sequence); } else resendbits[outno] = bits; @@ -1218,8 +1244,8 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t } MSG_WriteShort(msg, 0); - client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].entities.num_entities = outno; - client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].sequence = client->netchan.incoming_sequence; + client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities = outno; + client->frameunion.frames[sequence & UPDATE_MASK].sequence = sequence; } /* @@ -3389,12 +3415,13 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore #ifdef NQPROT if (ISNQCLIENT(client)) { - if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) + if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { - SVDP_EmitEntitiesUpdate(client, pack, msg); - SV_EmitCSQCUpdate(client, msg, svcdp_csqcentities); - return; + SVFTE_EmitPacketEntities(client, pack, msg); + client->netchan.incoming_sequence++; } + else if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) + SVDP_EmitEntitiesUpdate(client, pack, msg); else { for (e = 0; e < pack->num_entities; e++) @@ -3404,10 +3431,9 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore SVNQ_EmitEntityState(msg, &pack->entities[e]); } client->netchan.incoming_sequence++; - - SV_EmitCSQCUpdate(client, msg, svcfte_csqcentities); - return; } + SV_EmitCSQCUpdate(client, msg, svcdp_csqcentities); + return; } #endif diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 1cf1a7112..927fcb3a2 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -134,7 +134,7 @@ cvar_t sv_loadentfiles = CVAR("sv_loadentfiles", "1"); cvar_t sv_maxrate = CVAR("sv_maxrate", "30000"); cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "100000", "sv_maxdownloadrate", 0); -cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO); +cvar_t sv_minping = CVARF("sv_minping", "", CVAR_SERVERINFO); cvar_t sv_bigcoords = CVARFD("sv_bigcoords", "", CVAR_SERVERINFO, "Uses floats for coordinates instead of 16bit values. Affects clients thusly:\nQW: enforces a mandatory protocol extension\nDP: enables DPP7 protocol support\nNQ: uses RMQ protocol (protocol 999)."); cvar_t sv_calcphs = CVARFD("sv_calcphs", "2", CVAR_LATCH, "Enables culling of sound effects. 0=always skip phs. Sounds are globally broadcast. 1=always generate phs. Sounds are always culled. On large maps the phs will be dumped to disk. 2=On large single-player maps, generation of phs is skipped. Otherwise like option 1."); @@ -184,19 +184,18 @@ cvar_t maxspectators = CVARF("maxspectators", "8", CVAR_SERVERINFO); #ifdef SERVERONLY cvar_t deathmatch = CVARF("deathmatch", "1", CVAR_SERVERINFO); // 0, 1, or 2 #else -cvar_t deathmatch = CVARF("deathmatch", "0", CVAR_SERVERINFO); // 0, 1, or 2 +cvar_t deathmatch = CVARF("deathmatch", "", CVAR_SERVERINFO); // 0, 1, or 2 #endif cvar_t coop = CVARF("coop", "" , CVAR_SERVERINFO); cvar_t skill = CVARF("skill", "" , CVAR_SERVERINFO); // 0, 1, 2 or 3 cvar_t spawn = CVARF("spawn", "" , CVAR_SERVERINFO); cvar_t watervis = CVARF("watervis", "" , CVAR_SERVERINFO); cvar_t rearview = CVARF("rearview", "" , CVAR_SERVERINFO); -cvar_t allow_luma = CVARF("allow_luma", "1", CVAR_SERVERINFO); +cvar_t allow_luma = CVARF("allow_luma", "", CVAR_SERVERINFO); #pragma warningmsg("Remove this some time") -cvar_t allow_bump = CVARF("allow_bump", "1", CVAR_SERVERINFO); cvar_t allow_skybox = CVARF("allow_skybox", "", CVAR_SERVERINFO); cvar_t sv_allow_splitscreen = CVARF("allow_splitscreen","",CVAR_SERVERINFO); -cvar_t fbskins = CVARF("fbskins", "1", CVAR_SERVERINFO); //to get rid of lame fuhquake fbskins +cvar_t fbskins = CVARF("fbskins", "", CVAR_SERVERINFO); //to get rid of lame fuhquake fbskins cvar_t mirrors = CVARF("mirrors", "" , CVAR_SERVERINFO); cvar_t sv_motd[] ={ CVAR("sv_motd1", ""), @@ -523,12 +522,14 @@ void SV_DropClient (client_t *drop) PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect); sv.spawned_client_slots--; } - else if (SpectatorDisconnect) + else { - // call the prog function for removing a client - // this will set the body to a dead frame, among other things + // call the prog function for removing a client + // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, drop->edict); - PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); + if (SpectatorDisconnect) + PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); + sv.spawned_observer_slots--; } } @@ -621,6 +622,7 @@ void SV_DropClient (client_t *drop) } drop->laggedpacket_last = NULL; + drop->pendingentbits = NULL; if (drop->frameunion.frames) //union of the same sort of structure { Z_Free(drop->frameunion.frames); @@ -1710,6 +1712,129 @@ static void SV_CheckRecentCrashes(client_t *tellclient) } #endif + +void SV_ClientProtocolExtensionsChanged(client_t *client) +{ + int i; + int maxpacketentities; + extern cvar_t pr_maxedicts; + client->maxmodels = 256; + + if (client->fteprotocolextensions & PEXT_256PACKETENTITIES) + maxpacketentities = MAX_EXTENDED_PACKET_ENTITIES; + else + maxpacketentities = MAX_STANDARD_PACKET_ENTITIES; //true for qw,q2 + + if (ISQWCLIENT(client)) //readd? + { + if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) + { + //you need to reconnect for this to update, of course. so make sure its not *too* low... + client->max_net_ents = bound(512, pr_maxedicts.ival, MAX_EDICTS); + client->maxmodels = MAX_MODELS; //protocol limited to 14 bits. + } + else + { + client->max_net_ents = 512; + if (client->fteprotocolextensions & PEXT_ENTITYDBL) + client->max_net_ents += 512; + if (client->fteprotocolextensions & PEXT_ENTITYDBL2) + client->max_net_ents += 1024; + } + + if (client->fteprotocolextensions & PEXT_MODELDBL) + client->maxmodels = MAX_MODELS; + } + else if (ISDPCLIENT(client)) + { + client->max_net_ents = bound(512, pr_maxedicts.ival, 32768); + client->maxmodels = 1024; //protocol limit of 16 bits. 15 bits for late precaches. client limit of 1k + + client->datagram.maxsize = sizeof(host_client->datagram_buf); + } + else if (client->protocol == SCP_FITZ666) + { + client->max_net_ents = bound(512, pr_maxedicts.ival, 32768); //fitzquake supports 65535, but our writeentity builtin works differently. + client->maxmodels = 1024; + maxpacketentities = 512; + + client->datagram.maxsize = sizeof(host_client->datagram_buf); + } + else + { + client->datagram.maxsize = MAX_NQDATAGRAM; //vanilla limit + client->max_net_ents = bound(512, pr_maxedicts.ival, 600); + } + + client->pendingentbits = NULL; + + //initialise the client's frames, based on that client's protocol + switch(client->protocol) + { +#ifdef Q3SERVER + case SCP_QUAKE3: + Huff_PreferedCompressionCRC(); + if (client->frameunion.q3frames) + Z_Free(client->frameunion.q3frames); + client->frameunion.q3frames = Z_Malloc(Q3UPDATE_BACKUP*sizeof(*client->frameunion.q3frames)); + break; +#endif + +#ifdef Q2SERVER + case SCP_QUAKE2: + // build a new connection + // accept the new client + // this is the only place a client_t is ever initialized + client->frameunion.q2frames = client->frameunion.q2frames; //don't touch these. + if (client->frameunion.q2frames) + Z_Free(client->frameunion.q2frames); + + client->frameunion.q2frames = Z_Malloc(sizeof(q2client_frame_t)*Q2UPDATE_BACKUP); + break; +#endif + + default: + client->frameunion.frames = client->frameunion.frames; //don't touch these. + if (client->frameunion.frames) + Z_Free(client->frameunion.frames); + + if ((client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))// || ISDPCLIENT(&temp)) + { + char *ptr; + int maxents = client->max_net_ents;//maxpacketentities; /*this is the max number of ents updated per frame. we can't track more, so...*/ + ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+ + sizeof(*client->pendingentbits)*client->max_net_ents+ + sizeof(unsigned int)*maxents*UPDATE_BACKUP+ + sizeof(unsigned int)*maxents*UPDATE_BACKUP); + client->frameunion.frames = (void*)ptr; + ptr += sizeof(*client->frameunion.frames)*UPDATE_BACKUP; + client->pendingentbits = (void*)ptr; + ptr += sizeof(*client->pendingentbits)*client->max_net_ents; + for (i = 0; i < UPDATE_BACKUP; i++) + { + client->frameunion.frames[i].entities.max_entities = maxents; + client->frameunion.frames[i].resendentnum = (void*)ptr; + ptr += sizeof(*client->frameunion.frames[i].resendentnum)*maxents; + client->frameunion.frames[i].resendentbits = (void*)ptr; + ptr += sizeof(*client->frameunion.frames[i].resendentbits)*maxents; + } + + //make sure the reset is sent. + client->pendingentbits[0] = UF_REMOVE; + } + else + { + client->frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); + for (i = 0; i < UPDATE_BACKUP; i++) + { + client->frameunion.frames[i].entities.max_entities = maxpacketentities; + client->frameunion.frames[i].entities.entities = (entity_state_t*)(client->frameunion.frames+UPDATE_BACKUP) + i*client->frameunion.frames[i].entities.max_entities; + } + } + break; + } +} + /* ================== SVC_DirectConnect @@ -1749,15 +1874,13 @@ client_t *SVC_DirectConnect(void) char basic[80]; qboolean redirect = false; - int maxpacketentities; - int numssclients = 1; int protocol; unsigned int protextsupported=0; unsigned int protextsupported2=0; - extern cvar_t pr_maxedicts, sv_protocol_nq; + extern cvar_t sv_protocol_nq; char *name; @@ -1940,13 +2063,6 @@ client_t *SVC_DirectConnect(void) } msg_badread=false; - - - if (protextsupported & PEXT_256PACKETENTITIES) - maxpacketentities = MAX_EXTENDED_PACKET_ENTITIES; - else - maxpacketentities = MAX_STANDARD_PACKET_ENTITIES; - /*allow_splitscreen applies only to non-local clients, so that clients have only one enabler*/ if (!sv_allow_splitscreen.ival && net_from.type != NA_LOOPBACK) numssclients = 1; @@ -2043,41 +2159,6 @@ client_t *SVC_DirectConnect(void) newcl->protocol = protocol; Q_strncpyz(newcl->guid, guid, sizeof(newcl->guid)); - newcl->maxmodels = 256; - if (protocol == SCP_QUAKEWORLD) //readd? - { - if (newcl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) - { - //you need to reconnect for this to update, of course. so make sure its not *too* low... - newcl->max_net_ents = bound(512, pr_maxedicts.ival, MAX_EDICTS); - newcl->maxmodels = MAX_MODELS; //protocol limited to 14 bits. - } - else - { - newcl->max_net_ents = 512; - if (newcl->fteprotocolextensions & PEXT_ENTITYDBL) - newcl->max_net_ents += 512; - if (newcl->fteprotocolextensions & PEXT_ENTITYDBL2) - newcl->max_net_ents += 1024; - } - - if (newcl->fteprotocolextensions & PEXT_MODELDBL) - newcl->maxmodels = MAX_MODELS; - } - else if (ISDPCLIENT(newcl)) - { - newcl->max_net_ents = bound(512, pr_maxedicts.ival, 32768); - newcl->maxmodels = 1024; //protocol limit of 16 bits. 15 bits for late precaches. client limit of 1k - } - else if (newcl->protocol == SCP_FITZ666) - { - newcl->max_net_ents = bound(512, pr_maxedicts.ival, 32768); //fitzquake supports 65535, but our writeentity builtin works differently. - newcl->maxmodels = 1024; - maxpacketentities = 512; - } - else - newcl->max_net_ents = bound(512, pr_maxedicts.ival, 600); - if (sv.msgfromdemo) newcl->wasrecorded = true; @@ -2331,73 +2412,12 @@ client_t *SVC_DirectConnect(void) break; } - //initialise the client's frames, based on that client's protocol - switch(temp.protocol) + if (newcl->frameunion.frames) { -#ifdef Q3SERVER - case SCP_QUAKE3: - Huff_PreferedCompressionCRC(); - if (temp.frameunion.q3frames) - Z_Free(temp.frameunion.q3frames); - temp.frameunion.q3frames = Z_Malloc(Q3UPDATE_BACKUP*sizeof(*temp.frameunion.q3frames)); - break; -#endif - -#ifdef Q2SERVER - case SCP_QUAKE2: - // build a new connection - // accept the new client - // this is the only place a client_t is ever initialized - temp.frameunion.q2frames = newcl->frameunion.q2frames; //don't touch these. - if (temp.frameunion.q2frames) - Z_Free(temp.frameunion.q2frames); - - temp.frameunion.q2frames = Z_Malloc(sizeof(q2client_frame_t)*Q2UPDATE_BACKUP); - break; -#endif - - default: - temp.frameunion.frames = newcl->frameunion.frames; //don't touch these. - if (temp.frameunion.frames) - { - Con_Printf("Debug: frames were set?\n"); - Z_Free(temp.frameunion.frames); - } - - if ((temp.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))// || ISDPCLIENT(&temp)) - { - char *ptr; - int maxents = temp.max_net_ents;//maxpacketentities; /*this is the max number of ents updated per frame. we can't track more, so...*/ - ptr = Z_Malloc( sizeof(client_frame_t)*UPDATE_BACKUP+ - sizeof(*temp.pendingentbits)*temp.max_net_ents+ - sizeof(unsigned int)*maxents*UPDATE_BACKUP+ - sizeof(unsigned int)*maxents*UPDATE_BACKUP); - temp.frameunion.frames = (void*)ptr; - ptr += sizeof(*temp.frameunion.frames)*UPDATE_BACKUP; - temp.pendingentbits = (void*)ptr; - ptr += sizeof(*temp.pendingentbits)*temp.max_net_ents; - for (i = 0; i < UPDATE_BACKUP; i++) - { - temp.frameunion.frames[i].entities.max_entities = maxents; - temp.frameunion.frames[i].resendentnum = (void*)ptr; - ptr += sizeof(*temp.frameunion.frames[i].resendentnum)*maxents; - temp.frameunion.frames[i].resendentbits = (void*)ptr; - ptr += sizeof(*temp.frameunion.frames[i].resendentbits)*maxents; - } - } - else - { - temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); - for (i = 0; i < UPDATE_BACKUP; i++) - { - temp.frameunion.frames[i].entities.max_entities = maxpacketentities; - temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities; - } - } - break; + Con_Printf("Client frame info was set\n"); + Z_Free(newcl->frameunion.frames); } - { char *n, *t; n = newcl->name; @@ -2448,6 +2468,8 @@ client_t *SVC_DirectConnect(void) newcl->datagram.prim = svs.netprim; newcl->netchan.message.prim = svs.netprim; + SV_ClientProtocolExtensionsChanged(newcl); + // spectator mode can ONLY be set at join time newcl->spectator = spectator; @@ -2562,7 +2584,12 @@ client_t *SVC_DirectConnect(void) { SV_AcceptMessage (protocol); - if (redirect) + if (ISNQCLIENT(newcl)) + { + //FIXME: we should delay this until we actually have a name. + SV_BroadcastPrintf(PRINT_LOW, "New client connected\n", newcl->name); + } + else if (redirect) { } else if (newcl->spectator) @@ -3941,7 +3968,7 @@ float SV_Frame (void) #ifndef SERVERONLY isidle = !isDedicated && sv.allocated_client_slots == 1 && key_dest != key_game && cls.state == ca_active; /*server is effectively paused if there are no clients*/ - if (sv.spawned_client_slots == 0) + if (sv.spawned_client_slots == 0 && sv.spawned_observer_slots == 0 && (cls.state != ca_connected)) isidle = true; if ((sv.paused & 4) != (isidle?4:0)) sv.paused ^= 4; @@ -4210,7 +4237,6 @@ void SV_InitLocal (void) Cvar_Register (&rearview, cvargroup_serverinfo); Cvar_Register (&mirrors, cvargroup_serverinfo); Cvar_Register (&allow_luma, cvargroup_serverinfo); - Cvar_Register (&allow_bump, cvargroup_serverinfo); Cvar_Register (&allow_skybox, cvargroup_serverinfo); Cvar_Register (&sv_allow_splitscreen, cvargroup_serverinfo); Cvar_Register (&fbskins, cvargroup_serverinfo); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 5947e4590..c947683ec 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -57,15 +57,15 @@ cvar_t sv_gameplayfix_noairborncorpse = SCVAR( "sv_gameplayfix_noairborncorpse", cvar_t sv_gameplayfix_multiplethinks = CVARD( "sv_gameplayfix_multiplethinks", "1", "Enables multiple thinks per entity per frame so small nextthink times are accurate. QuakeWorld mods expect a value of 1."); cvar_t sv_sound_watersplash = CVAR( "sv_sound_watersplash", "misc/h2ohit1.wav"); cvar_t sv_sound_land = CVAR( "sv_sound_land", "demon/dland2.wav"); -cvar_t sv_stepheight = CVARAF("pm_stepheight", "18", - "sv_stepheight", CVAR_SERVERINFO); +cvar_t sv_stepheight = CVARAFD("pm_stepheight", "", + "sv_stepheight", CVAR_SERVERINFO, "If empty, the value 18 will be used instead."); -cvar_t pm_ktjump = SCVARF("pm_ktjump", "0", CVAR_SERVERINFO); -cvar_t pm_bunnyspeedcap = SCVARF("pm_bunnyspeedcap", "0", CVAR_SERVERINFO); -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_ktjump = SCVARF("pm_ktjump", "", CVAR_SERVERINFO); +cvar_t pm_bunnyspeedcap = SCVARF("pm_bunnyspeedcap", "", CVAR_SERVERINFO); +cvar_t pm_slidefix = SCVARF("pm_slidefix", "", CVAR_SERVERINFO); +cvar_t pm_slidyslopes = SCVARF("pm_slidyslopes", "", CVAR_SERVERINFO); +cvar_t pm_airstep = SCVARF("pm_airstep", "", CVAR_SERVERINFO); +cvar_t pm_walljump = SCVARF("pm_walljump", "", CVAR_SERVERINFO); #define cvargroup_serverphysics "server physics variables" void WPhys_Init(void) diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 9f2825297..c39248fb2 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -876,9 +876,17 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sam int qwflags; int i; qboolean use_phs; - qboolean reliable = false; + qboolean reliable; int requiredextensions = 0; + if (channel & 256) + { + channel -= 256; + reliable = true; + } + else + reliable = false; + if (volume < 0 || volume > 255) { Con_Printf ("SV_StartSound: volume = %i", volume); @@ -891,7 +899,7 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sam return; } - if (channel < 0 || channel > 15) + if (channel < 0 || channel > 255) { Con_Printf ("SV_StartSound: channel = %i", channel); return; @@ -914,17 +922,11 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sam return; } - if ((channel & 8) || !sv_phs.value) // no PHS flag - { - if (channel & 8) - reliable = true; // sounds that break the phs are reliable + if (reliable || !sv_phs.value) // no PHS flag use_phs = false; - } else use_phs = attenuation!=0; - channel = (channel & 7) | ((channel & 0x1f0) >> 1); - // if (channel == CHAN_BODY || channel == CHAN_VOICE) // reliable = true; @@ -1187,6 +1189,8 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) #endif client_t *split; int pnum=0; + int weaponmodelindex = 0; + qboolean nqjunk = true; // send the chokecount for r_netgraph if (ISQWCLIENT(client)) @@ -1221,10 +1225,13 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) ent = client->edict; - MSG_WriteByte (msg, svc_time); - MSG_WriteFloat(msg, sv.world.physicstime); - client->nextservertimeupdate = sv.world.physicstime; -// Con_Printf("%f\n", sv.world.physicstime); + if (!(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) + { + MSG_WriteByte (msg, svc_time); + MSG_WriteFloat(msg, sv.world.physicstime); + client->nextservertimeupdate = sv.world.physicstime; +// Con_Printf("%f\n", sv.world.physicstime); + } bits = 0; @@ -1242,9 +1249,27 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) #define SU_INWATER (1<<11) // no data follows, the bit is it #define SU_WEAPONFRAME (1<<12) #define SU_ARMOR (1<<13) -#define SU_WEAPON (1<<14) +#define SU_WEAPONMODEL (1<<14) #define SU_EXTEND1 (1<<15) +#define FITZSU_WEAPONMODEL2 (1<<16) // 1 byte, this is .weaponmodel & 0xFF00 (second byte) +#define FITZSU_ARMOR2 (1<<17) // 1 byte, this is .armorvalue & 0xFF00 (second byte) +#define FITZSU_AMMO2 (1<<18) // 1 byte, this is .currentammo & 0xFF00 (second byte) +#define FITZSU_SHELLS2 (1<<19) // 1 byte, this is .ammo_shells & 0xFF00 (second byte) +#define FITZSU_NAILS2 (1<<20) // 1 byte, this is .ammo_nails & 0xFF00 (second byte) +#define FITZSU_ROCKETS2 (1<<21) // 1 byte, this is .ammo_rockets & 0xFF00 (second byte) +#define FITZSU_CELLS2 (1<<22) // 1 byte, this is .ammo_cells & 0xFF00 (second byte) +#define FITZSU_EXTEND2 (1<<23) // another byte to follow + +#define FITZSU_WEAPONFRAME2 (1<<24) // 1 byte, this is .weaponframe & 0xFF00 (second byte) +#define FITZSU_WEAPONALPHA (1<<25) // 1 byte, this is alpha for weaponmodel, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT +#define FITZSU_UNUSED26 (1<<26) +#define FITZSU_UNUSED27 (1<<27) +#define FITZSU_UNUSED28 (1<<28) +#define FITZSU_UNUSED29 (1<<29) +#define FITZSU_UNUSED30 (1<<30) +#define FITZSU_EXTEND3 (1<<31) // another byte to follow, future expansion + if (ent->v->view_ofs[2] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT; @@ -1277,17 +1302,55 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) bits |= (SU_VELOCITY1<v->weaponframe) - bits |= SU_WEAPONFRAME; + if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) + { + //bits &= ~SU_ITEMS; + nqjunk = false; + } + else + { + nqjunk = true; - if (ent->v->armorvalue) - bits |= SU_ARMOR; + if (ent->v->weaponframe) + bits |= SU_WEAPONFRAME; -// if (ent->v->weapon) - bits |= SU_WEAPON; + if (ent->v->armorvalue) + bits |= SU_ARMOR; - if (bits >= 65536) + weaponmodelindex = SV_ModelIndex(ent->v->weaponmodel + svprogfuncs->stringtable); + + if (weaponmodelindex) + bits |= SU_WEAPONMODEL; + + if (client->protocol == SCP_FITZ666) + { + if (weaponmodelindex & 0xff00) + bits |= FITZSU_WEAPONMODEL2; + if ((int)ent->v->armorvalue & 0xff00) + bits |= FITZSU_ARMOR2; + if ((int)ent->v->currentammo & 0xff00) + bits |= FITZSU_AMMO2; + if ((int)ent->v->ammo_shells & 0xff00) + bits |= FITZSU_SHELLS2; + if ((int)ent->v->ammo_nails & 0xff00) + bits |= FITZSU_NAILS2; + if ((int)ent->v->ammo_rockets & 0xff00) + bits |= FITZSU_ROCKETS2; + if ((int)ent->v->ammo_cells & 0xff00) + bits |= FITZSU_CELLS2; + if ((int)ent->v->weaponframe & 0xff00) + bits |= FITZSU_WEAPONFRAME2; + if (ent->xv->alpha && ent->xv->alpha < 1) + bits |= FITZSU_WEAPONALPHA; + } + } + + if (bits >= (1u<<16)) bits |= SU_EXTEND1; + if (bits >= (1u<<24)) + bits |= FITZSU_EXTEND2; + if (bits >= (1ull<<32)) + bits |= FITZSU_EXTEND3; // send the data @@ -1316,48 +1379,54 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) if (bits & SU_ITEMS) MSG_WriteLong (msg, items); - if (client->protocol == SCP_DARKPLACES6 || client->protocol == SCP_DARKPLACES7) - return; - if (bits & SU_WEAPONFRAME) MSG_WriteByte (msg, ent->v->weaponframe); if (bits & SU_ARMOR) { - if (ent->v->armorvalue>255) + if (ent->v->armorvalue>255 && !(bits & FITZSU_ARMOR2)) MSG_WriteByte (msg, 255); else MSG_WriteByte (msg, ent->v->armorvalue); } - if (bits & SU_WEAPON) - MSG_WriteByte (msg, SV_ModelIndex(ent->v->weaponmodel + svprogfuncs->stringtable)); + if (bits & SU_WEAPONMODEL) + MSG_WriteByte (msg, weaponmodelindex); - MSG_WriteShort (msg, ent->v->health); - MSG_WriteByte (msg, ent->v->currentammo); - MSG_WriteByte (msg, ent->v->ammo_shells); - MSG_WriteByte (msg, ent->v->ammo_nails); - MSG_WriteByte (msg, ent->v->ammo_rockets); - MSG_WriteByte (msg, ent->v->ammo_cells); - - //if (other && other->v->weapon) - //MSG_WriteByte (msg, other->v->weapon); - //else - //{ - - if (standard_quake) + if (nqjunk) { - MSG_WriteByte (msg, ent->v->weapon); - } - else - { - for(i=0;i<32;i++) + MSG_WriteShort (msg, ent->v->health); + MSG_WriteByte (msg, ent->v->currentammo); + MSG_WriteByte (msg, ent->v->ammo_shells); + MSG_WriteByte (msg, ent->v->ammo_nails); + MSG_WriteByte (msg, ent->v->ammo_rockets); + MSG_WriteByte (msg, ent->v->ammo_cells); + + if (standard_quake) { - if ( ((int)ent->v->weapon) & (1<v->weapon); + } + else + { + for(i=0;i<32;i++) { - MSG_WriteByte (msg, i); - break; + if ( ((int)ent->v->weapon) & (1<> 8); + if (bits & FITZSU_ARMOR2) MSG_WriteByte (msg, (int)ent->v->armorvalue >> 8); + if (bits & FITZSU_AMMO2) MSG_WriteByte (msg, (int)ent->v->currentammo >> 8); + if (bits & FITZSU_SHELLS2) MSG_WriteByte (msg, (int)ent->v->ammo_shells >> 8); + if (bits & FITZSU_NAILS2) MSG_WriteByte (msg, (int)ent->v->ammo_nails >> 8); + if (bits & FITZSU_ROCKETS2) MSG_WriteByte (msg, (int)ent->v->ammo_rockets >> 8); + if (bits & FITZSU_CELLS2) MSG_WriteByte (msg, (int)ent->v->ammo_cells >> 8); + if (bits & FITZSU_WEAPONFRAME2) MSG_WriteByte (msg, (int)ent->v->weaponframe >> 8); + if (bits & FITZSU_WEAPONALPHA) MSG_WriteByte (msg, ent->xv->alpha*255); + // } #endif } @@ -2332,29 +2401,50 @@ void SV_SendClientMessages (void) continue; } +#ifdef NQPROT // only send messages if the client has sent one // and the bandwidth is not choked if (ISNQCLIENT(c)) - { //nq clients get artificial choke too - c->send_message = false; - if (c->nextservertimeupdate != pt && c->state != cs_zombie) + { + //tread carefully with NQ: + //while loading models etc, NQ will error out if it receives anything that it wasn't expecting. + //we should still send unreliable nops whenever we want as a keepalive (and we may need to in order to wake up the client). + //other unreliables are disallowed when connecting, due to sync issues. + //reliables may be sent only if some other code has said that its okay (to avoid stray name changes killing clients). + if (c->state == cs_connected) { - c->send_message = c->netchan.nqreliable_allowed = true; + if (c->nextservertimeupdate > pt + 6) + c->nextservertimeupdate = 0; - if (c->state == cs_connected && !c->datagram.cursize && !c->netchan.message.cursize) + c->netchan.nqunreliableonly = !c->send_message; + c->datagram.cursize = 0; + if (!c->send_message && c->nextservertimeupdate < pt) { - if (c->nextservertimeupdate < pt) - { //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 = pt+5; - } + if (c->nextservertimeupdate) + MSG_WriteByte(&c->datagram, svc_nop); + c->nextservertimeupdate = pt+5; + } + c->send_message = true; + //we can still send an outgoing packet if something set send_message. This should really only be svnq_new_f and friends. + } + else + { + if (c->nextservertimeupdate > pt + 0.5*2) + c->nextservertimeupdate = 0; + + c->netchan.nqunreliableonly = false; + c->send_message = false; + //nq sends one packet only for each server physics frame + if (c->nextservertimeupdate < pt && c->state != cs_zombie) + { + c->send_message = true; + c->nextservertimeupdate = pt; } } } + //qw servers will set send_message on packet reception. +#endif + if (!c->send_message) continue; c->send_message = false; // try putting this after choke? diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 5f31a62ae..f82c79497 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -423,9 +423,12 @@ void SVNQ_New_f (void) extern cvar_t coop; char message[2048]; int i; - int maxents; + int maxplayers = 0; + int op; extern cvar_t pr_maxedicts; + unsigned int protext1 = 0, protext2 = 0, protmain = 0, protfl = 0; + host_client->send_message = true; if (host_client->redirect) { char *msg = va("connect \"%s\"\n", sv_fullredirect.string); @@ -477,20 +480,17 @@ void SVNQ_New_f (void) } } - MSG_WriteByte (&host_client->netchan.message, svc_serverdata); + protext1 = host_client->fteprotocolextensions; + protext2 = host_client->fteprotocolextensions2; + protmain = NQ_PROTOCOL_VERSION; + protfl = 0; + //force floatcoords as required. + if (sv.nqdatagram.prim.coordsize >= 4) + protext1 |= PEXT_FLOATCOORDS; + else + protext1 &= ~PEXT_FLOATCOORDS; - if (host_client->fteprotocolextensions) - { - MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION_FTE); - MSG_WriteLong (&host_client->netchan.message, host_client->fteprotocolextensions); - } - if (host_client->fteprotocolextensions2) - { - MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION_FTE2); - MSG_WriteLong (&host_client->netchan.message, host_client->fteprotocolextensions2); - } - - maxents = host_client->max_net_ents; + op = host_client->protocol; switch(host_client->protocol) { #ifdef NQPROT @@ -500,47 +500,35 @@ void SVNQ_New_f (void) SV_LogPlayer(host_client, "new (NQ)"); if (sv.nqdatagram.prim.anglesize != 1 || sv.nqdatagram.prim.coordsize != 2 || host_client->protocol == SCP_FITZ666) { - int rmqfl = + protfl = ((sv.nqdatagram.prim.coordsize==4)?RMQFL_FLOATCOORD:0) | ((sv.nqdatagram.prim.anglesize==2)?RMQFL_SHORTANGLE:0); host_client->protocol = SCP_FITZ666; /*mneh, close enough, the rmq stuff is just modifiers*/ - host_client->datagram.maxsize = sizeof(host_client->datagram_buf); - if (rmqfl) + if (protfl) { - MSG_WriteLong (&host_client->netchan.message, RMQ_PROTOCOL_VERSION); - MSG_WriteLong (&host_client->netchan.message, rmqfl); + protext1 &= ~PEXT_FLOATCOORDS; //never report floatcoords when using rmq protocol, as the base protocol allows us to be more specific anyway. + protmain = RMQ_PROTOCOL_VERSION; } else - { - MSG_WriteLong (&host_client->netchan.message, FITZ_PROTOCOL_VERSION); - } - - host_client->maxmodels = 1024; + protmain = FITZ_PROTOCOL_VERSION; } else { host_client->protocol = (host_client->protocol==SCP_PROQUAKE)?SCP_PROQUAKE:SCP_NETQUAKE; //identical other than the client->server angles - if (host_client->protocol==SCP_PROQUAKE) - host_client->max_net_ents = bound(512, pr_maxedicts.ival, 32767); //modified engines will all want to use proquake's improved aiming protocol. - else //if this breaks your client, upgrade. - host_client->max_net_ents = bound(512, pr_maxedicts.ival, 600); - MSG_WriteLong (&host_client->netchan.message, NQ_PROTOCOL_VERSION); - host_client->datagram.maxsize = MAX_NQDATAGRAM; - - host_client->maxmodels = 256; + protmain = NQ_PROTOCOL_VERSION; } - MSG_WriteByte (&host_client->netchan.message, (sv.allocated_client_slots>16)?16:sv.allocated_client_slots); + maxplayers = 16; break; case SCP_DARKPLACES6: SV_LogPlayer(host_client, "new (DP6)"); - MSG_WriteLong (&host_client->netchan.message, DP6_PROTOCOL_VERSION); - MSG_WriteByte (&host_client->netchan.message, sv.allocated_client_slots); + protmain = DP6_PROTOCOL_VERSION; + maxplayers = 255; break; case SCP_DARKPLACES7: SV_LogPlayer(host_client, "new (DP7)"); - MSG_WriteLong (&host_client->netchan.message, DP7_PROTOCOL_VERSION); - MSG_WriteByte (&host_client->netchan.message, sv.allocated_client_slots); + protmain = DP7_PROTOCOL_VERSION; + maxplayers = 255; break; #endif default: @@ -548,9 +536,24 @@ void SVNQ_New_f (void) break; } - //the protocol limits were recalculated to avoid any nasty surprises when things default to forcing a protocol - if (maxents != host_client->max_net_ents && !(host_client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) - host_client->max_net_ents = maxents; + MSG_WriteByte (&host_client->netchan.message, svc_serverdata); + if (protext1) + { + MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION_FTE); + MSG_WriteLong (&host_client->netchan.message, protext1); + } + if (protext2) + { + MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION_FTE2); + MSG_WriteLong (&host_client->netchan.message, protext2); + } + MSG_WriteLong (&host_client->netchan.message, protmain); + if (protmain == RMQ_PROTOCOL_VERSION) + MSG_WriteLong (&host_client->netchan.message, protfl); + MSG_WriteByte (&host_client->netchan.message, (sv.allocated_client_slots>maxplayers)?maxplayers:sv.allocated_client_slots); + + if (op != host_client->protocol) + SV_ClientProtocolExtensionsChanged(host_client); if (!coop.value && deathmatch.value) MSG_WriteByte (&host_client->netchan.message, GAME_DEATHMATCH); @@ -950,7 +953,7 @@ void SV_SendClientPrespawnInfo(client_t *client) started = false; //allows stalling for the soundlist command, for compat. - if (host_client->prespawn_idx & 0x80000000) + if (client->prespawn_idx & 0x80000000) return; while (client->netchan.message.cursize < (client->netchan.message.maxsize/2)) @@ -993,7 +996,7 @@ void SV_SendClientPrespawnInfo(client_t *client) MSG_WriteByte (&client->netchan.message, (client->prespawn_idx&0xff)?client->prespawn_idx:0xff); if (!(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) - host_client->prespawn_idx |= 0x80000000; + client->prespawn_idx |= 0x80000000; } } if (client->prespawn_stage == PRESPAWN_MODELLIST) @@ -1001,7 +1004,7 @@ void SV_SendClientPrespawnInfo(client_t *client) started = false; //allows stalling for the soundlist command, for compat. - if (host_client->prespawn_idx & 0x80000000) + if (client->prespawn_idx & 0x80000000) return; while (client->netchan.message.cursize < (client->netchan.message.maxsize/2)) @@ -1078,7 +1081,7 @@ void SV_SendClientPrespawnInfo(client_t *client) MSG_WriteByte (&client->netchan.message, (client->prespawn_idx&0xff)?client->prespawn_idx:0xff); if (!(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)) - host_client->prespawn_idx |= 0x80000000; + client->prespawn_idx |= 0x80000000; } } @@ -1171,7 +1174,7 @@ void SV_SendClientPrespawnInfo(client_t *client) if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { - MSG_WriteByte(&client->netchan.message, svc_spawnstatic2); + MSG_WriteByte(&client->netchan.message, svcfte_spawnstatic2); SVFTE_EmitBaseline(state, false, &client->netchan.message); continue; } @@ -1180,7 +1183,7 @@ void SV_SendClientPrespawnInfo(client_t *client) /*if it uses some new feature, use the updated spawnstatic*/ if (state->hexen2flags || state->trans || state->modelindex >= 256 || state->frame > 255 || state->scale || state->abslight) { - MSG_WriteByte(&client->netchan.message, svc_spawnstatic2); + MSG_WriteByte(&client->netchan.message, svcfte_spawnstatic2); SVQW_WriteDelta(&nullentitystate, state, &client->netchan.message, true, client->fteprotocolextensions); continue; } @@ -1317,8 +1320,18 @@ void SV_SendClientPrespawnInfo(client_t *client) if (!client->prespawn_idx) { //we'll spawn the client and then send all the updating stuff only when we know the channel is clear, by pinging the client for it. - MSG_WriteByte (&client->netchan.message, svc_stufftext); - MSG_WriteString (&client->netchan.message, va("cmd spawn %i\n",svs.spawncount) ); + 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_Byte (client, 2); + } + else + { + char *cmd = va("cmd spawn %i\n",svs.spawncount); + ClientReliableWrite_Begin(client, svc_stufftext, 2+strlen(cmd)); + ClientReliableWrite_String(client, cmd); + } client->prespawn_idx++; } } @@ -1627,6 +1640,7 @@ void SV_Begin_Core(client_t *split) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); PR_ExecuteProgram (svprogfuncs, SpectatorConnect); } + sv.spawned_observer_slots++; } else { @@ -3591,11 +3605,20 @@ void SV_SetInfo_f (void) if (basic || (client->fteprotocolextensions & PEXT_BIGUSERINFOS)) { ClientReliableWrite_Begin(client, svc_setinfo, 1+1+strlen(key)+1+strlen(val)+1); - ClientReliableWrite_Char(client, i); + ClientReliableWrite_Byte(client, i); ClientReliableWrite_String(client, key); ClientReliableWrite_String(client, val); } } + if (ISNQCLIENT(client)) + { + if (!strcmp(key, "name")) + { + ClientReliableWrite_Begin(client, svc_updatename, 1+1+strlen(val)+1); + ClientReliableWrite_Byte(client, i); + ClientReliableWrite_String(client, val); + } + } } if (sv.mvdrecording) @@ -4104,6 +4127,7 @@ void Cmd_Join_f (void) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); if (SpectatorDisconnect) PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); + sv.spawned_observer_slots--; SV_SetUpClientEdict (host_client, host_client->edict); @@ -4230,6 +4254,7 @@ void Cmd_Observe_f (void) } else sv_player->v->movetype = MOVETYPE_NOCLIP; + sv.spawned_observer_slots++; // send notification to all clients host_client->old_frags = host_client->edict->v->frags; @@ -4416,9 +4441,6 @@ void SVNQ_Spawn_f (void) ClientReliableWrite_Byte (host_client, STAT_MONSTERS); ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters); - - - SZ_Write (&host_client->netchan.message, sv.signon.data, sv.signon.cursize); MSG_WriteByte (&host_client->netchan.message, svc_signonnum); MSG_WriteByte (&host_client->netchan.message, 3); @@ -4462,6 +4484,7 @@ void SVNQ_Begin_f (void) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, SpectatorConnect); } + sv.spawned_observer_slots++; } else { @@ -4531,9 +4554,6 @@ void SVNQ_Begin_f (void) MSG_WriteAngle (&host_client->netchan.message, 0 ); } - - - SZ_Write (&host_client->netchan.message, sv.signon.data, sv.signon.cursize); // MSG_WriteByte (&host_client->netchan.message, svc_signonnum); // MSG_WriteByte (&host_client->netchan.message, 4); @@ -4661,6 +4681,10 @@ void SV_Pext_f(void) } } + Con_DPrintf("%s now using pext: %x, %x\n", host_client->name, host_client->fteprotocolextensions, host_client->fteprotocolextensions2); + + SV_ClientProtocolExtensionsChanged(host_client); + if (ISNQCLIENT(host_client)) SVNQ_New_f(); else @@ -6014,6 +6038,25 @@ done: SV_ClientPrintf(host_client, PRINT_HIGH, "qcrequest \"%s\" not supported\n", rname); } +void SV_AckEntityFrame(client_t *cl, int framenum) +{ +#ifdef PEXT_CSQC + if (cl->lastsequence_acknowledged + UPDATE_BACKUP > framenum) + { + int i; + Con_DPrintf("SV: Acked %i\n", framenum); + for (i = cl->lastsequence_acknowledged+1; i < framenum; i++) + SV_CSQC_DroppedPacket(cl, i); + } + else + { + /*too much loss, we don't know what was sent when, so reset the entire entity state*/ + SV_CSQC_DropAll(cl); + } +#endif + cl->lastsequence_acknowledged = framenum; +} + /* =================== SV_ExecuteClientMessage @@ -6064,19 +6107,6 @@ void SV_ExecuteClientMessage (client_t *cl) } } } -#ifdef PEXT_CSQC - if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged) - { - for (i = cl->lastsequence_acknowledged+1; i < cl->netchan.incoming_acknowledged; i++) - SV_CSQC_DroppedPacket(cl, i); - } - else - { - /*too much loss, we don't know what was sent when, so reset the entire entity state*/ - SV_CSQC_DropAll(cl); - } -#endif - cl->lastsequence_acknowledged = cl->netchan.incoming_acknowledged; if (sv_antilag.ival) { @@ -6374,9 +6404,15 @@ haveannothergo: SV_VoiceReadPacket(); break; #endif + case clcdp_ackframe: + cl->delta_sequence = MSG_ReadLong(); + SV_AckEntityFrame(cl, cl->delta_sequence); + break; } } + SV_AckEntityFrame(cl, cl->netchan.incoming_acknowledged); + host_client = NULL; sv_player = NULL; } @@ -6571,6 +6607,20 @@ void SVNQ_ReadClientMove (usercmd_t *move) frame->ping_time = sv.time - cltime; + if (frame->ping_time*1000 > sv_minping.value+1) + { + host_client->delay -= 0.001; + if (host_client->delay < 0) + host_client->delay = 0; + } + if (frame->ping_time*1000 < sv_minping.value) + { + host_client->delay += 0.001; + if (host_client->delay > 1) + host_client->delay = 1; + } + + // read current angles for (i=0 ; i<3 ; i++) { @@ -6731,8 +6781,13 @@ void SVNQ_ExecuteClientMessage (client_t *cl) sv_player = cl->edict; break; + case clc_qcrequest: + SV_ReadQCRequest(); + break; + case clcdp_ackframe: cl->delta_sequence = MSG_ReadLong(); + SV_AckEntityFrame(cl, cl->delta_sequence); break; case clcdp_ackdownloaddata: SV_DarkPlacesDownloadAck(cl); diff --git a/engine/shaders/glsl/defaultskin.glsl b/engine/shaders/glsl/defaultskin.glsl index b60a07aa6..fb91484c4 100644 --- a/engine/shaders/glsl/defaultskin.glsl +++ b/engine/shaders/glsl/defaultskin.glsl @@ -3,23 +3,50 @@ !!permu FRAMEBLEND !!permu SKELETAL !!permu FOG +!!cvarf r_glsl_offsetmapping_scale +!!cvarf gl_specular //standard shader used for models. //must support skeletal and 2-way vertex blending or Bad Things Will Happen. //the vertex shader is responsible for calculating lighting values. +#ifdef UPPERLOWER +#define UPPER +#define LOWER +#endif + varying vec2 tc; varying vec3 light; +#if defined(SPECULAR) || defined(OFFSETMAPPING) +varying vec3 eyevector; +#endif + + + + #ifdef VERTEX_SHADER #include "sys/skeletal.h" attribute vec2 v_texcoord; uniform vec3 e_light_dir; uniform vec3 e_light_mul; uniform vec3 e_light_ambient; +#if defined(SPECULAR) || defined(OFFSETMAPPING) +uniform vec3 e_eyepos; +#endif void main () { +#if defined(SPECULAR)||defined(OFFSETMAPPING) + vec3 n, s, t, w; + gl_Position = skeletaltransform_wnst(w,n,s,t); + vec3 eyeminusvertex = e_eyepos - w.xyz; + eyevector.x = -dot(eyeminusvertex, s.xyz); + eyevector.y = dot(eyeminusvertex, t.xyz); + eyevector.z = dot(eyeminusvertex, n.xyz); +#else vec3 n; gl_Position = skeletaltransform_n(n); +#endif + light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul); tc = v_texcoord; } @@ -38,24 +65,54 @@ uniform vec3 e_uppercolour; #ifdef FULLBRIGHT uniform sampler2D s_t3; #endif + +#if defined(SPECULAR) +uniform sampler2D s_t4; +uniform sampler2D s_t5; +uniform float cvar_gl_specular; +#endif + +#ifdef OFFSETMAPPING +#include "sys/offsetmapping.h" +#endif + + + uniform vec4 e_colourident; void main () { vec4 col, sp; + +#ifdef OFFSETMAPPING + vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector); +#define tc tcoffsetmap +#endif + col = texture2D(s_t0, tc); #ifdef UPPER vec4 uc = texture2D(s_t2, tc); - col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a); + col.rgb += uc.rgb*e_uppercolour*uc.a; #endif #ifdef LOWER vec4 lc = texture2D(s_t1, tc); - col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a); + col.rgb += lc.rgb*e_lowercolour*lc.a; #endif col.rgb *= light; + +#if defined(SPECULAR) + vec3 bumps = normalize(vec3(texture2D(s_t4, tc)) - 0.5); + vec4 specs = texture2D(s_t5, tc); + + vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0)); + float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a); + col.rgb += cvar_gl_specular * spec * specs.rgb; +#endif + #ifdef FULLBRIGHT vec4 fb = texture2D(s_t3, tc); col.rgb = mix(col.rgb, fb.rgb, fb.a); #endif + gl_FragColor = fog4(col * e_colourident); } #endif diff --git a/engine/shaders/glsl/rtlight.glsl b/engine/shaders/glsl/rtlight.glsl index 875b80809..83ba78e20 100644 --- a/engine/shaders/glsl/rtlight.glsl +++ b/engine/shaders/glsl/rtlight.glsl @@ -1,5 +1,6 @@ !!permu BUMP !!permu SKELETAL +!!permu UPPERLOWER !!permu FOG !!cvarf r_glsl_offsetmapping_scale @@ -17,6 +18,11 @@ #extension GL_ARB_texture_gather : enable #endif +#ifdef UPPERLOWER +#define UPPER +#define LOWER +#endif + varying vec2 tcbase; varying vec3 lightvector; @@ -65,20 +71,20 @@ void main () #ifdef FRAGMENT_SHADER #include "sys/fog.h" -uniform sampler2D s_t0; +uniform sampler2D s_t0; //diffuse #if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) -uniform sampler2D s_t1; +uniform sampler2D s_t1; //normalmap #endif #ifdef SPECULAR -uniform sampler2D s_t2; +uniform sampler2D s_t2; //specular #endif #ifdef CUBEPROJ -uniform samplerCube s_t3; +uniform samplerCube s_t3; //projected cubemap #endif #ifdef PCF #ifdef CUBESHADOW -uniform samplerCubeShadow s_t4; +uniform samplerCubeShadow s_t4; //shadowmap #else #if 0//def GL_ARB_texture_gather uniform sampler2D s_t4; @@ -87,6 +93,14 @@ uniform sampler2DShadow s_t4; #endif #endif #endif +#ifdef LOWER +uniform sampler2D s_t5; //pants colours +uniform vec3 e_lowercolour; +#endif +#ifdef UPPER +uniform sampler2D s_t6; //shirt colours +uniform vec3 e_uppercolour; +#endif uniform float l_lightradius; @@ -128,7 +142,7 @@ float ShadowmapFilter(void) //assume z is the major axis (ie: forward from the light) vec3 t = shadowcoord; float ma = dir.z; - vec4 axis = vec4(1.0, 1.0, 1.0, 0.0); + vec3 axis = vec3(1.0, 1.0, 1.0); if (dir.x > ma) { ma = dir.x; @@ -200,6 +214,14 @@ void main () #define tcbase tcoffsetmap #endif vec3 bases = vec3(texture2D(s_t0, tcbase)); +#ifdef UPPER + vec4 uc = texture2D(s_t6, tcbase); + bases.rgb += uc.rgb*e_uppercolour*uc.a; +#endif +#ifdef LOWER + vec4 lc = texture2D(s_t5, tcbase); + bases.rgb += lc.rgb*e_lowercolour*lc.a; +#endif #if defined(BUMP) || defined(SPECULAR) vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5); #endif diff --git a/engine/shaders/glsl/underwaterwarp.glsl b/engine/shaders/glsl/underwaterwarp.glsl index 70c9a4427..2c16b341e 100644 --- a/engine/shaders/glsl/underwaterwarp.glsl +++ b/engine/shaders/glsl/underwaterwarp.glsl @@ -11,11 +11,11 @@ varying vec2 v_edge; uniform float e_time; void main () { -gl_Position = ftetransform(); -v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0; -v_warp.s = e_time * 0.25 + v_texcoord.s; -v_warp.t = e_time * 0.25 + v_texcoord.t; -v_edge = v_texcoord.xy; + gl_Position = ftetransform(); + v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0; + v_warp.s = e_time * 0.25 + v_texcoord.s; + v_warp.t = e_time * 0.25 + v_texcoord.t; + v_edge = v_texcoord.xy; } #endif #ifdef FRAGMENT_SHADER @@ -25,21 +25,21 @@ varying vec2 v_edge; uniform sampler2D s_t0;/*$currentrender*/ uniform sampler2D s_t1;/*warp image*/ uniform sampler2D s_t2;/*edge image*/ -uniform vec3 e_rendertexturescale; +uniform vec4 e_rendertexturescale; uniform float cvar_r_waterwarp; void main () { -float amptemp; -vec3 edge; -edge = texture2D( s_t2, v_edge ).rgb; -amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x; -vec3 offset; -offset = texture2D( s_t1, v_warp ).rgb; -offset.x = (offset.x - 0.5) * 2.0; -offset.y = (offset.y - 0.5) * 2.0; -vec2 temp; -temp.x = v_stc.x + offset.x * amptemp; -temp.y = v_stc.y + offset.y * amptemp; -gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st ); + float amptemp; + vec3 edge; + edge = texture2D( s_t2, v_edge ).rgb; + amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x; + vec3 offset; + offset = texture2D( s_t1, v_warp ).rgb; + offset.x = (offset.x - 0.5) * 2.0; + offset.y = (offset.y - 0.5) * 2.0; + vec2 temp; + temp.x = v_stc.x + offset.x * amptemp; + temp.y = v_stc.y + offset.y * amptemp; + gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st ); } #endif diff --git a/plugins/berkelium/plugapi.cpp b/plugins/berkelium/plugapi.cpp index 102c4d71e..c4d7cc105 100644 --- a/plugins/berkelium/plugapi.cpp +++ b/plugins/berkelium/plugapi.cpp @@ -339,7 +339,7 @@ static void Dec_ChangeStream(void *vctx, char *newstream) else if (!strcmp(newstream+4, "unfocus")) ctx->wnd->unfocus(); else if (!strcmp(newstream+4, "opaque")) - ctx->wnd->setTransparent(true); + ctx->wnd->setTransparent(false); else if (!strcmp(newstream+4, "stop")) ctx->wnd->stop(); else if (!strcmp(newstream+4, "back")) diff --git a/plugins/berkelium/readme.txt b/plugins/berkelium/readme.txt index 92ef035ac..c3be34070 100644 --- a/plugins/berkelium/readme.txt +++ b/plugins/berkelium/readme.txt @@ -39,7 +39,20 @@ CSQC is able to interact with videos by: this will 'end' the video. when the shader is next displayed it'll reset from the original url. 7: you can change the url with: gecko_navigate(texname, "http://fteqw.com"); - +8: you can send it these navigation commands (in the place of a url). You'll likely want a focus command. + cmd:refresh + cmd:transparent + cmd:focus + cmd:unfocus + cmd:opaque + cmd:stop + cmd:back + cmd:forward + cmd:cut + cmd:copy + cmd:paste + cmd:del + cmd:selectall Compiling the plugin for Windows: