From 4974c57c2c44307cd52cebee5a493f7ac037d36f Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 1 Apr 2009 22:03:56 +0000 Subject: [PATCH] Big fat-off commit. A few changes. Half-Life support is finally getting committed. Some unnecessary filesystem code changes. And there's code for nsapi - meaning we can embed FTE in a browser (firefox and opera on windows work). A couple of CSQC changes, trying to move towards a final EXT_CSQC_1. Revised ruleset format finally implemented. Doesn't compile with msvc6 due to issues with libjpeg not being a clean library. Presumably its fine in vs2005. Your mileage may vary. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3148 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cg.c | 11 +- engine/client/cl_demo.c | 246 +++- engine/client/cl_ents.c | 63 +- engine/client/cl_input.c | 3 + engine/client/cl_main.c | 24 +- engine/client/cl_master.h | 1 + engine/client/cl_parse.c | 35 +- engine/client/cl_pred.c | 5 + engine/client/cl_screen.c | 11 +- engine/client/cl_ui.c | 2 +- engine/client/clhl_game.c | 1373 ++++++++++++++++++ engine/client/client.h | 23 + engine/client/clq3_parse.c | 4 +- engine/client/console.c | 6 + engine/client/image.c | 8 +- engine/client/in_win.c | 129 +- engine/client/keys.c | 3 +- engine/client/m_items.c | 9 +- engine/client/m_mp3.c | 79 +- engine/client/m_multi.c | 151 ++ engine/client/m_options.c | 9 +- engine/client/m_single.c | 6 +- engine/client/menu.c | 33 +- engine/client/merged.h | 2 + engine/client/net_master.c | 177 ++- engine/client/p_classic.c | 72 + engine/client/pr_csqc.c | 584 ++++++-- engine/client/pr_menu.c | 9 +- engine/client/quakedef.h | 13 +- engine/client/render.h | 5 +- engine/client/renderer.c | 31 +- engine/client/sbar.c | 6 +- engine/client/skin.c | 3 + engine/client/snd_dma.c | 86 +- engine/client/snd_mem.c | 10 +- engine/client/sys_npqtv.c | 1002 +++++++++++++ engine/client/sys_win.c | 205 ++- engine/client/textedit.c | 4 +- engine/client/valid.c | 73 +- engine/client/view.c | 5 +- engine/client/wad.h | 19 +- engine/client/winquake.h | 7 +- engine/client/winquake.rc | 2 +- engine/client/zqtp.c | 2 +- engine/common/bothdefs.h | 6 + engine/common/cmd.c | 28 +- engine/common/com_mesh.c | 42 +- engine/common/common.c | 114 +- engine/common/common.h | 104 +- engine/common/cvar.c | 48 +- engine/common/cvar.h | 23 +- engine/common/fs.c | 1902 ++++++------------------- engine/common/fs.h | 30 + engine/common/fs_pak.c | 544 +++++++ engine/common/fs_stdio.c | 226 +++ engine/common/fs_zip.c | 461 ++++++ engine/common/mathlib.c | 27 +- engine/common/net.h | 6 +- engine/common/net_wins.c | 51 +- engine/common/plugin.c | 4 +- engine/common/pmovetst.c | 2 + engine/common/pr_bgcmd.c | 56 +- engine/common/protocol.h | 1 + engine/common/q3common.c | 20 +- engine/common/qvm.c | 2 +- engine/common/sys.h | 21 +- engine/common/zone.c | 7 +- engine/d3d/d3d_draw.c | 14 +- engine/d3d/d3d_mesh.c | 27 - engine/d3d/d3d_rmain.c | 2 +- engine/d3d/vid_d3d.c | 88 +- engine/d3d9/d3d9_draw.c | 14 +- engine/d3d9/d3d9_rmain.c | 4 +- engine/d3d9/vid_d3d9.c | 77 +- engine/ftequake/ftequake.dsp | 273 +++- engine/ftequake/ftequake.dsw | 27 + engine/ftequake/npapi.def | 5 + engine/ftequake/npplug.rc | 111 ++ engine/ftequake/npqtv.dsp | 1044 ++++++++++++++ engine/gl/gl_draw.c | 48 +- engine/gl/gl_hlmdl.c | 51 +- engine/gl/gl_model.c | 48 +- engine/gl/gl_model.h | 5 +- engine/gl/gl_ngraph.c | 60 + engine/gl/gl_rmain.c | 2 +- engine/gl/gl_rsurf.c | 28 +- engine/gl/gl_shader.c | 4 +- engine/gl/gl_vidnt.c | 144 +- engine/gl/gltod3d/gl_fakegl.cpp | 1 + engine/gl/model_hl.h | 3 +- engine/http/ftpserver.c | 14 +- engine/http/iweb.h | 8 +- engine/http/iwebiface.c | 2 +- engine/http/webgen.c | 2 +- engine/libs/npapi/npapi.h | 766 ++++++++++ engine/libs/npapi/npruntime.h | 423 ++++++ engine/libs/npapi/nptypes.h | 105 ++ engine/libs/npapi/npupp.h | 721 ++++++++++ engine/libs/npapi/obsolete/protypes.h | 252 ++++ engine/libs/npapi/prcpucfg.h | 300 ++++ engine/libs/npapi/prtypes.h | 575 ++++++++ engine/qclib/hash.c | 8 +- engine/qclib/hash.h | 13 +- engine/qclib/initlib.c | 20 + engine/qclib/qccmain.c | 31 +- engine/server/q2game.h | 45 +- engine/server/savegame.c | 242 ++-- engine/server/server.h | 2 +- engine/server/sv_ccmds.c | 68 +- engine/server/sv_chat.c | 2 +- engine/server/sv_main.c | 176 ++- engine/server/sv_mvd.c | 262 ++-- engine/server/sv_rankin.c | 7 +- engine/server/sv_sys_win.c | 2 +- engine/server/sv_user.c | 22 +- engine/server/svhl_game.c | 1724 ++++++++++++++++++++++ engine/server/svhl_gcapi.h | 572 ++++++++ engine/server/svhl_phys.c | 1854 ++++++++++++++++++++++++ engine/server/svhl_world.c | 747 ++++++++++ engine/server/svq3_game.c | 2 +- engine/sw/d_sprite.c | 6 +- engine/sw/r_sprite.c | 4 +- engine/sw/sw_draw.c | 50 +- engine/sw/sw_model.c | 36 +- engine/sw/vid_win2.c | 35 +- 125 files changed, 16306 insertions(+), 3148 deletions(-) create mode 100644 engine/client/clhl_game.c create mode 100644 engine/client/sys_npqtv.c create mode 100644 engine/common/fs.h create mode 100644 engine/common/fs_pak.c create mode 100644 engine/common/fs_stdio.c create mode 100644 engine/common/fs_zip.c create mode 100644 engine/ftequake/npapi.def create mode 100644 engine/ftequake/npplug.rc create mode 100644 engine/ftequake/npqtv.dsp create mode 100644 engine/libs/npapi/npapi.h create mode 100644 engine/libs/npapi/npruntime.h create mode 100644 engine/libs/npapi/nptypes.h create mode 100644 engine/libs/npapi/npupp.h create mode 100644 engine/libs/npapi/obsolete/protypes.h create mode 100644 engine/libs/npapi/prcpucfg.h create mode 100644 engine/libs/npapi/prtypes.h create mode 100644 engine/server/svhl_game.c create mode 100644 engine/server/svhl_gcapi.h create mode 100644 engine/server/svhl_phys.c create mode 100644 engine/server/svhl_world.c diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 49c627f5f..7c7007eca 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -633,7 +633,16 @@ static int CG_SystemCallsEx(void *offset, unsigned int mask, int fn, const int * if (!angles) angles = vec3_origin; if (mod) +#ifndef CLIENTONLY TransformedNativeTrace(mod, 0, 0, start, end, mins, maxs, brushmask, &tr, origin, angles); +#else + { +#pragma message("FIXME: G3 CGame requires TransformedNativeTrace!") + memset(&tr, 0, sizeof(tr)); + tr.allsolid = tr.startsolid = true; + tr.contents = 1; + } +#endif else { memset(&tr, 0, sizeof(tr)); @@ -859,7 +868,7 @@ vec3_t listener_up; VectorCopy(axis+3, listener_right); VectorCopy(axis+6, listener_up); -// S_Update(origin, axis[0], axis[1], axis[2], false); + S_UpdateListener(org, axis[0], axis[1], axis[2], false); } break; diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index ff298ff21..1aa2b4087 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" +#include "fs.h" void CL_FinishTimeDemo (void); float demtime; @@ -883,7 +884,6 @@ void CL_Record_f (void) { int c; char name[MAX_OSPATH]; - int namelen = sizeof(name); sizebuf_t buf; char buf_data[MAX_QWMSGLEN]; int n, i, j; @@ -910,7 +910,6 @@ void CL_Record_f (void) if (cls.demorecording) CL_Stop_f(); - namelen -= strlen(com_gamedir)+1; if (c == 2) //user supplied a name { fname = Cmd_Argv(1); @@ -1651,6 +1650,8 @@ void CL_QTVPoll (void) else if (!strcmp(s, "BEGIN")) { + while (*colon && *(unsigned char*)colon <= ' ') + colon++; if (*colon) Con_Printf("streaming \"%s\" from qtv\n", colon); else @@ -1737,6 +1738,171 @@ char *strchrrev(char *str, char chr) return NULL; } +void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result) +{ + char buffer[2048]; + char *s; + memset(result, 0, sizeof(*result)); + if (!f) + { + Con_Printf("Couldn't open QTV file: %s\n", name); + return; + } + if (!VFS_GETS(f, buffer, sizeof(buffer)-1)) + { + Con_Printf("Empty QTV file: %s\n", name); + VFS_CLOSE(f); + return; + } + s = buffer; + while (*s == ' ' || *s == '\t') + s++; + if (*s != '[') + { + Con_Printf("Bad QTV file: %s\n", name); + VFS_CLOSE(f); + return; + } + s++; + while (*s == ' ' || *s == '\t') + s++; + if (strnicmp(s, "QTV", 3)) + { + Con_Printf("Bad QTV file: %s\n", name); + VFS_CLOSE(f); + return; + } + s+=3; + while (*s == ' ' || *s == '\t') + s++; + if (*s != ']') + { + Con_Printf("Bad QTV file: %s\n", name); + VFS_CLOSE(f); + return; + } + s++; + while (*s == ' ' || *s == '\t' || *s == '\r') + s++; + if (*s) + { + Con_Printf("Bad QTV file: %s\n", name); + VFS_CLOSE(f); + return; + } + + while (VFS_GETS(f, buffer, sizeof(buffer)-1)) + { + s = COM_ParseToken(buffer, ":="); + if (*s != '=' && *s != ':') + s = ""; + else + s++; + + if (!stricmp(com_token, "stream")) + { + result->connectiontype = QTVCT_STREAM; + s = COM_ParseOut(s, result->server, sizeof(result->server)); + } + else if (!stricmp(com_token, "connect")) + { + result->connectiontype = QTVCT_CONNECT; + s = COM_ParseOut(s, result->server, sizeof(result->server)); + } + else if (!stricmp(com_token, "join")) + { + result->connectiontype = QTVCT_JOIN; + s = COM_ParseOut(s, result->server, sizeof(result->server)); + } + else if (!stricmp(com_token, "observe")) + { + result->connectiontype = QTVCT_OBSERVE; + s = COM_ParseOut(s, result->server, sizeof(result->server)); + } + else if (!stricmp(com_token, "splash")) + { + s = COM_ParseOut(s, result->splashscreen, sizeof(result->server)); + } + } + VFS_CLOSE(f); +} + +void CL_ParseQTVDescriptor(vfsfile_t *f, const char *name) +{ + char buffer[1024]; + char *s; + + if (!f) + { + Con_Printf("Couldn't open QTV file: %s\n", name); + return; + } + while (VFS_GETS(f, buffer, sizeof(buffer)-1)) + { + if (!strncmp(buffer, "Stream=", 7) || !strncmp(buffer, "Stream:", 7)) + { + for (s = buffer + strlen(buffer)-1; s >= buffer; s--) + { + if (*s == '\r' || *s == '\n' || *s == ';') + *s = 0; + else + break; + } + s = buffer+7; + while(*s && *s <= ' ') + s++; + Cbuf_AddText(va("qtvplay \"%s\"\n", s), Cmd_ExecLevel); + break; + } + if (!strncmp(buffer, "Connect=", 8) || !strncmp(buffer, "Connect:", 8)) + { + for (s = buffer + strlen(buffer)-1; s >= buffer; s--) + { + if (*s == '\r' || *s == '\n' || *s == ';') + *s = 0; + else + break; + } + s = buffer+8; + while(*s && *s <= ' ') + s++; + Cbuf_AddText(va("connect \"%s\"\n", s), Cmd_ExecLevel); + break; + } + if (!strncmp(buffer, "Join=", 5) || !strncmp(buffer, "Join:", 5)) + { + for (s = buffer + strlen(buffer)-1; s >= buffer; s--) + { + if (*s == '\r' || *s == '\n' || *s == ';') + *s = 0; + else + break; + } + s = buffer+5; + while(*s && *s <= ' ') + s++; + Cbuf_AddText(va("join \"%s\"\n", s), Cmd_ExecLevel); + break; + } + if (!strncmp(buffer, "Observe=", 8) || !strncmp(buffer, "Observe:", 8)) + { + for (s = buffer + strlen(buffer)-1; s >= buffer; s--) + { + if (*s == '\r' || *s == '\n' || *s == ';') + *s = 0; + else + break; + } + s = buffer+8; + while(*s && *s <= ' ') + s++; + Cbuf_AddText(va("observe \"%s\"\n", s), Cmd_ExecLevel); + break; + } + } + VFS_CLOSE(f); +} + void CL_QTVPlay_f (void) { qboolean raw=0; @@ -1754,80 +1920,8 @@ void CL_QTVPlay_f (void) if (*connrequest == '#') { - char buffer[1024]; - char *s; - FILE *f; - f = fopen(connrequest+1, "rt"); - if (!f) - { - Con_Printf("Couldn't open QTV file: %s\n", connrequest+1); - return; - } - while (!feof(f)) - { - fgets(buffer, sizeof(buffer)-1, f); - if (!strncmp(buffer, "Stream=", 7) || !strncmp(buffer, "Stream:", 7)) - { - for (s = buffer + strlen(buffer)-1; s >= buffer; s--) - { - if (*s == '\r' || *s == '\n' || *s == ';') - *s = 0; - else - break; - } - s = buffer+7; - while(*s && *s <= ' ') - s++; - Cbuf_AddText(va("qtvplay \"%s\"\n", s), Cmd_ExecLevel); - break; - } - if (!strncmp(buffer, "Connect=", 8) || !strncmp(buffer, "Connect:", 8)) - { - for (s = buffer + strlen(buffer)-1; s >= buffer; s--) - { - if (*s == '\r' || *s == '\n' || *s == ';') - *s = 0; - else - break; - } - s = buffer+8; - while(*s && *s <= ' ') - s++; - Cbuf_AddText(va("connect \"%s\"\n", s), Cmd_ExecLevel); - break; - } - if (!strncmp(buffer, "Join=", 5) || !strncmp(buffer, "Join:", 5)) - { - for (s = buffer + strlen(buffer)-1; s >= buffer; s--) - { - if (*s == '\r' || *s == '\n' || *s == ';') - *s = 0; - else - break; - } - s = buffer+5; - while(*s && *s <= ' ') - s++; - Cbuf_AddText(va("join \"%s\"\n", s), Cmd_ExecLevel); - break; - } - if (!strncmp(buffer, "Observe=", 8) || !strncmp(buffer, "Observe:", 8)) - { - for (s = buffer + strlen(buffer)-1; s >= buffer; s--) - { - if (*s == '\r' || *s == '\n' || *s == ';') - *s = 0; - else - break; - } - s = buffer+8; - while(*s && *s <= ' ') - s++; - Cbuf_AddText(va("observe \"%s\"\n", s), Cmd_ExecLevel); - break; - } - } - fclose(f); + //#FILENAME is a local system path + CL_ParseQTVDescriptor(VFSOS_Open(connrequest+1, "rt"), connrequest+1); return; } diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 80ccd4187..721ceb385 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1595,6 +1595,8 @@ void CL_LinkPacketEntities (void) autorotate = anglemod(100*servertime); + CLCSQC_DeltaStart(); + for (newpnum=0 ; newpnumnum_entities ; newpnum++) { state = &pack->entities[newpnum]; @@ -1606,6 +1608,10 @@ void CL_LinkPacketEntities (void) Con_Printf("Too many visible entities\n"); break; } + + if (CLCSQC_DeltaUpdate(state)) + continue; + ent = &cl_visedicts[cl_numvisedicts]; #ifdef Q3SHADERS ent->forcedshader = NULL; @@ -1762,12 +1768,11 @@ void CL_LinkPacketEntities (void) AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); - if (ent->keynum <= MAX_CLIENTS -#ifdef NQPROT - && cls.protocol == CP_QUAKEWORLD -#endif - ) - ent->keynum += MAX_EDICTS; + if (ent->keynum <= MAX_CLIENTS) + { + if (!cl.nolocalplayer[0]) + ent->keynum += MAX_EDICTS; + } if (state->tagentity) { //ent is attached to a tag, rotate this ent accordingly. @@ -1869,6 +1874,7 @@ void CL_LinkPacketEntities (void) } } + CLCSQC_DeltaEnd(); } #else @@ -2752,6 +2758,9 @@ void CL_LinkPlayers (void) vec3_t angles; float *org; + if (!cl.worldmodel || cl.worldmodel->needload) + return; + playertime = realtime - cls.latency + 0.02; if (playertime > realtime) playertime = realtime; @@ -2763,7 +2772,13 @@ void CL_LinkPlayers (void) ; j++, info++, state++) { if (state->messagenum != cl.validsequence) + { + CLCSQC_DeltaPlayer(j, NULL); continue; // not present this frame + } + + if (CLCSQC_DeltaPlayer(j, state)) + continue; // spawn light flashes, even ones coming from invisible objects if (r_powerupglow.value && !(r_powerupglow.value == 2 && j == cl.playernum[0])) @@ -3010,25 +3025,29 @@ void CL_LinkViewModel(void) ent.shaderRGBAf[2] = 1; ent.shaderRGBAf[3] = alpha; - ent.framestate.g[FS_REG].frame[0] = cl.viewent[r_refdef.currentplayernum].framestate.g[FS_REG].frame[0]; - ent.framestate.g[FS_REG].frame[1] = oldframe[r_refdef.currentplayernum]; - - if (ent.framestate.g[FS_REG].frame[0] != prevframe[r_refdef.currentplayernum]) +#ifdef HLCLIENT + if (!CLHL_AnimateViewEntity(&ent)) +#endif { - oldframe[r_refdef.currentplayernum] = ent.framestate.g[FS_REG].frame[1] = prevframe[r_refdef.currentplayernum]; - lerptime[r_refdef.currentplayernum] = realtime; - } - prevframe[r_refdef.currentplayernum] = ent.framestate.g[FS_REG].frame[0]; + ent.framestate.g[FS_REG].frame[0] = cl.viewent[r_refdef.currentplayernum].framestate.g[FS_REG].frame[0]; + ent.framestate.g[FS_REG].frame[1] = oldframe[r_refdef.currentplayernum]; - if (ent.model != oldmodel[r_refdef.currentplayernum]) - { - oldmodel[r_refdef.currentplayernum] = ent.model; - oldframe[r_refdef.currentplayernum] = ent.framestate.g[FS_REG].frame[1] = ent.framestate.g[FS_REG].frame[0]; - lerptime[r_refdef.currentplayernum] = realtime; - } - ent.framestate.g[FS_REG].lerpfrac = 1-(realtime-lerptime[r_refdef.currentplayernum])*10; - ent.framestate.g[FS_REG].lerpfrac = bound(0, ent.framestate.g[FS_REG].lerpfrac, 1); + if (ent.framestate.g[FS_REG].frame[0] != prevframe[r_refdef.currentplayernum]) + { + oldframe[r_refdef.currentplayernum] = ent.framestate.g[FS_REG].frame[1] = prevframe[r_refdef.currentplayernum]; + lerptime[r_refdef.currentplayernum] = realtime; + } + prevframe[r_refdef.currentplayernum] = ent.framestate.g[FS_REG].frame[0]; + if (ent.model != oldmodel[r_refdef.currentplayernum]) + { + oldmodel[r_refdef.currentplayernum] = ent.model; + oldframe[r_refdef.currentplayernum] = ent.framestate.g[FS_REG].frame[1] = ent.framestate.g[FS_REG].frame[0]; + lerptime[r_refdef.currentplayernum] = realtime; + } + ent.framestate.g[FS_REG].lerpfrac = 1-(realtime-lerptime[r_refdef.currentplayernum])*10; + ent.framestate.g[FS_REG].lerpfrac = bound(0, ent.framestate.g[FS_REG].lerpfrac, 1); + } #define Q2RF_VIEWERMODEL 2 // don't draw through eyes, only mirrors #define Q2RF_WEAPONMODEL 4 // only draw through eyes #define Q2RF_DEPTHHACK 16 // for view weapon Z crunching diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 9c4ba9c3e..a08fdbeb2 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1505,6 +1505,9 @@ void CL_SendCmd (double frametime) } } +#ifdef HLCLIENT + if (!CLHL_BuildUserInput(msecstouse, &independantphysics[0])) +#endif for (plnum = 0; plnum < cl.splitclients; plnum++) { // CL_BaseMove (&independantphysics[plnum], plnum, (msecstouse - independantphysics[plnum].msec), wantfps); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 3f0015a93..b1e4d8104 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1504,7 +1504,7 @@ void CL_CheckServerInfo(void) cl.ktprogametime = 0; Cvar_ForceCheatVars(cls.allow_semicheats, cls.allow_cheats); - + Validation_Apply_Ruleset(); if (oldallowshaders != cls.allow_shaders) Cache_Flush(); //this will cause all models to be reloaded. @@ -2774,7 +2774,7 @@ void CL_ServerInfo_f(void) { if (!sv.state && cls.state) { - if (cls.demoplayback) + if (cls.demoplayback || cls.protocol != CP_QUAKEWORLD) { Info_Print (cl.serverinfo); } @@ -3385,10 +3385,10 @@ void Host_Frame (double time) if (cls.protocol == CP_QUAKE3) S_ExtraUpdate(); else - S_Update (r_origin, vpn, vright, vup); + S_UpdateListener (r_origin, vpn, vright, vup, false); } else - S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin); + S_UpdateListener (vec3_origin, vec3_origin, vec3_origin, vec3_origin, false); CDAudio_Update(); @@ -3420,6 +3420,8 @@ void Host_Frame (double time) static void simple_crypt(char *buf, int len) { + if (!(*buf & 128)) + return; while (len--) *buf++ ^= 0xff; } @@ -3626,6 +3628,7 @@ void Host_Init (quakeparms_t *parms) Cvar_ApplyLatches(CVAR_RENDERERLATCH); +#ifndef NPQTV //-1 means 'never set' if (qrenderer == -1 && *vid_renderer.string) { @@ -3641,6 +3644,7 @@ void Host_Init (quakeparms_t *parms) if (qrenderer == QR_NONE) Con_Printf("Use the setrenderer command to use a gui\n"); +#endif #ifdef VM_UI UI_Init(); @@ -3695,14 +3699,12 @@ to run quit through here before the final handoff to the sys code. */ void Host_Shutdown(void) { - static qboolean isdown = false; - - if (isdown) + if (!host_initialized) { Sys_Printf ("recursive shutdown\n"); return; } - isdown = true; + host_initialized = false; #ifdef VM_UI UI_Stop(); @@ -3713,6 +3715,7 @@ void Host_Shutdown(void) CDAudio_Shutdown (); S_Shutdown(); IN_Shutdown (); + R_ShutdownRenderer(); if (VID_DeInit) VID_DeInit(); #ifndef CLIENTONLY @@ -3720,11 +3723,16 @@ void Host_Shutdown(void) #else NET_Shutdown (); #endif + FS_Shutdown(); Cvar_Shutdown(); Validation_FlushFileList(); + Cmd_Shutdown(); Memory_DeInit(); + + memset(&sv, 0, sizeof(sv)); + memset(&svs, 0, sizeof(svs)); } #ifdef CLIENTONLY diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index 36876b0a9..4e30480c5 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -1,4 +1,5 @@ +#define SS_GENERICQUAKEWORLD 0 #define SS_FTESERVER 1 //hehehe... #define SS_QUAKE2 2 //useful (and cool). Could be blamed for swamping. #define SS_NETQUAKE 4 diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index b2cf1a34d..bdf8c19f9 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -452,12 +452,10 @@ void CL_DownloadFinished(char *filename, char *tempname) { if (strncmp(tempname,"skins/",6)) { - FS_CreatePath(filename, FS_GAME); FS_Rename(tempname, filename, FS_GAME); } else { - FS_CreatePath(filename+6, FS_SKINS); FS_Rename(tempname+6, filename+6, FS_SKINS); } } @@ -834,6 +832,14 @@ int CL_LoadModels(int stage) } #endif +#ifdef HLCLIENT + if (atstage()) + { + CLHL_LoadClientGame(); + endstage(); + } +#endif + #ifdef PEXT_CSQC if (atstage()) { @@ -890,8 +896,12 @@ int CL_LoadModels(int stage) else CSQC_LoadResource(cl.model_name[i], "model"); #endif - - cl.model_precache[i] = Mod_ForName (cl.model_name[i], false); +#ifdef Q2CLIENT + if (cls.protocol == CP_QUAKE2 && *cl.model_name[i] == '#') + cl.model_precache[i] = NULL; + else +#endif + cl.model_precache[i] = Mod_ForName (cl.model_name[i], false); Hunk_Check(); S_ExtraUpdate(); @@ -3334,7 +3344,7 @@ void CL_NewTranslation (int slot) } else local = cl.playernum[0]; - if (cl.teamplay && !strcmp(player->team, cl.players[local].team)) + if ((cl.teamplay || cls.protocol == CP_NETQUAKE) && !strcmp(player->team, cl.players[local].team)) { if (cl_teamtopcolor != ~0) top = cl_teamtopcolor; @@ -4961,6 +4971,18 @@ void CL_ParseServerMessage (void) case svcfte_pointparticles1: CLDP_ParsePointParticles(true); break; + + case svcfte_cgamepacket: +#ifdef HLCLIENT + if (CLHL_ParseGamePacket()); + break; +#endif +#ifdef CSQC_DAT + if (CSQC_ParseGamePacket()); + break; +#endif + Con_Printf("Unable to parse gamecode packet\n"); + break; } } } @@ -4995,7 +5017,6 @@ void CLQ2_ParseServerMessage (void) { if (msg_badread) { - SV_UnspawnServer(); Host_EndGame ("CLQ2_ParseServerMessage: Bad server message"); break; } @@ -5490,6 +5511,8 @@ void CLNQ_ParseServerMessage (void) if (cls.state == ca_active) Skin_Find (&cl.players[i]); + if (i == cl.playernum[0]) + Skin_FlushPlayers(); Sbar_Changed (); CL_NewTranslation (i); } diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index a3c4e1897..f9133ce1d 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -715,6 +715,9 @@ void CL_PredictMovePNum (int pnum) //these are to make svc_viewentity work better float *vel; float *org; + + cl.nolocalplayer[pnum] = false; + #ifdef Q2CLIENT if (cls.protocol == CP_QUAKE2) { @@ -775,6 +778,7 @@ void CL_PredictMovePNum (int pnum) { if (cl.viewentity[pnum] < cl.maxlerpents) { + cl.nolocalplayer[pnum] = true; // Con_Printf("Using lerped pos\n"); org = cl.lerpents[cl.viewentity[pnum]].origin; vel = vec3_origin; @@ -822,6 +826,7 @@ void CL_PredictMovePNum (int pnum) //no player states?? put the view on an ent if (cl.playernum[pnum] < cl.maxlerpents) { + cl.nolocalplayer[pnum] = true; // Con_Printf("Using lerped pos\n"); org = cl.lerpents[cl.playernum[pnum]+1].origin; vel = vec3_origin; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index cd37fae42..1edae68f9 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1317,6 +1317,12 @@ void SCR_DrawFPS (void) lastfps = 1/host_frametime; lastframetime = t; break; +#ifdef RGLQUAKE + case 5: + if (qrenderer == QR_OPENGL) + GLR_FrameTimeGraph((int)(1000.0*host_frametime)); + break; +#endif } if (usemsecs) @@ -1742,8 +1748,6 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i #endif void WriteBMPFile(char *filename, qbyte *in, int width, int height); -void WritePCXfile (char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit. - /* Find closest color in the palette for named color */ @@ -1870,7 +1874,6 @@ SCR_ScreenShot_f void SCR_ScreenShot_f (void) { char pcxname[80]; - char checkname[MAX_OSPATH]; int i; vfsfile_t *vfs; @@ -1903,7 +1906,7 @@ void SCR_ScreenShot_f (void) pcxname[17] = (i%1000)/100 + '0'; pcxname[18] = (i%100)/10 + '0'; pcxname[19] = (i%10) + '0'; - sprintf (checkname, "%s/%s", com_gamedir, pcxname); + if (!(vfs = FS_OpenVFS(pcxname, "rb", FS_GAMEONLY))) break; // file doesn't exist VFS_CLOSE(vfs); diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 45b409138..b34c4992e 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -618,7 +618,7 @@ void UI_RegisterFont(char *fontName, int pointSize, fontInfo_t *font) -#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) SV_Error("Call to ui trap %i passes invalid pointer\n", fn); //out of bounds. +#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to ui trap %i passes invalid pointer\n", fn); //out of bounds. #ifndef _DEBUG static diff --git a/engine/client/clhl_game.c b/engine/client/clhl_game.c new file mode 100644 index 000000000..796f4366f --- /dev/null +++ b/engine/client/clhl_game.c @@ -0,0 +1,1373 @@ +#include "quakedef.h" + +#include "glquake.h" + +#ifdef HLCLIENT + +#define CLIENTDLLNAME "cl_dlls/client" + +#define notimp(l) Con_Printf("halflife cl builtin not implemented on line %i\n", l) + +//#define HLCL_API_VERSION 6 +#define HLCL_API_VERSION 7 + +#define HLPIC model_t* + +typedef struct +{ + int l; + int r; + int t; + int b; +} hlsubrect_t; + +typedef struct +{ + vec3_t origin; + +#if HLCL_API_VERSION >= 7 + vec3_t viewangles; + int weapons; + float fov; +#else + float viewheight; + float maxspeed; + vec3_t viewangles; + vec3_t punchangles; + int keys; + int weapons; + float fov; + float idlescale; + float mousesens; +#endif +} hllocalclientdata_t; + +typedef struct +{ + short lerpmsecs; + qbyte msec; + vec3_t viewangles; + + float forwardmove; + float sidemove; + float upmove; + + qbyte lightlevel; + unsigned short buttons; + qbyte impulse; + qbyte weaponselect; + + int impact_index; + vec3_t impact_position; +} hlusercmd_t; + +typedef struct +{ + char name[64]; + char sprite[64]; + int unk; + int forscrwidth; + hlsubrect_t rect; +} hlspriteinf_t; + +typedef struct +{ + char *name; + short ping; + qbyte isus; + qbyte isspec; + qbyte pl; + char *model; + short tcolour; + short bcolour; +} hlplayerinfo_t; + +typedef struct +{ + int size; + int width; + int height; + int flags; + int charheight; + short charwidths[256]; +} hlscreeninfo_t; + +typedef struct +{ + int effect; + byte_vec4_t c1; + byte_vec4_t c2; + float x; + float y; + float fadein; + float fadeout; + float holdtime; + float fxtime; + char *name; + char *message; +} hlmsginfo_t; + +typedef struct +{ + HLPIC (*pic_load) (char *picname); + int (*pic_getnumframes) (HLPIC pic); + int (*pic_getheight) (HLPIC pic, int frame); + int (*pic_getwidth) (HLPIC pic, int frame); + void (*pic_select) (HLPIC pic, int r, int g, int b); + void (*pic_drawcuropaque) (int frame, int x, int y, void *loc); + void (*pic_drawcuralphatest) (int frame, int x, int y, void *loc); + void (*pic_drawcuradditive) (int frame, int x, int y, void *loc); + void (*pic_enablescissor) (int x, int y, int width, int height); + void (*pic_disablescissor) (void); + hlspriteinf_t *(*pic_parsepiclist) (char *filename, int *numparsed); + + void (*fillrgba) (int x, int y, int width, int height, int r, int g, int b, int a); + int (*getscreeninfo) (hlscreeninfo_t *info); + void (*setcrosshair) (HLPIC pic, hlsubrect_t rect, int r, int g, int b); //I worry about stuff like this + + int (*cvar_register) (char *name, char *defvalue, int flags); + float (*cvar_getfloat) (char *name); + char *(*cvar_getstring) (char *name); + + void (*cmd_register) (char *name, void (*func) (void)); + void (*hooknetmsg) (char *msgname, void *func); + void (*forwardcmd) (char *command); + void (*localcmd) (char *command); + + void (*getplayerinfo) (int entnum, hlplayerinfo_t *result); + + void (*startsound_name) (char *name, float vol); + void (*startsound_idx) (int idx, float vol); + + void (*anglevectors) (float *ina, float *outf, float *outr, float *outu); + + hlmsginfo_t *(*get_message_info) (char *name); //translated+scaled+etc intro stuff + int (*drawchar) (int x, int y, int charnum, int r, int g, int b); + int (*drawstring) (int x, int y, char *string); +#if HLCL_API_VERSION >= 7 + void (*settextcolour) (float r, float b, float g); +#endif + void (*drawstring_getlen) (char *string, int *outlen, int *outheight); + void (*consoleprint) (char *str); + void (*centerprint) (char *str); + +#if HLCL_API_VERSION >= 7 + int (*getwindowcenterx)(void); //yes, really, window center. for use with Get/SetCursorPos, the windows function. + int (*getwindowcentery)(void); //yes, really, window center. for use with Get/SetCursorPos, the windows function. + void (*getviewnangles)(float*ang); + void (*setviewnangles)(float*ang); + void (*getmaxclients)(float*ang); + void (*cvar_setvalue)(char *cvarname, char *value); + + int (*cmd_argc)(void); + char *(*cmd_argv)(int i); + void (*con_printf)(char *fmt, ...); + void (*con_dprintf)(char *fmt, ...); + void (*con_notificationprintf)(int pos, char *fmt, ...); + void (*con_notificationprintfex)(void *info, char *fmt, ...); //arg1 is of specific type + char *(*physkey)(char *key); + char *(*serverkey)(char *key); + float (*getclientmaxspeed)(void); + int (*checkparm)(char *str, char **next); + int (*keyevent)(int key, int down); + void (*getmousepos)(int *outx, int *outy); + int (*movetypeisnoclip)(void); + struct hlclent_s *(*getlocalplayer)(void); + struct hlclent_s *(*getviewent)(void); + struct hlclent_s *(*getentidx)(void); + float (*getlocaltime)(void); + void (*calcshake)(void); + void (*applyshake)(void); + int (*pointcontents)(float *point, float *truecon); + int (*waterentity)(float *point); + void (*traceline) (float *start, float *end, int flags, int hull, int forprediction); + + model_t *(*loadmodel)(char *modelname, int *mdlindex); + int (*addrentity)(int type, void *ent); + + model_t *(*modelfrompic) (HLPIC pic); + void (*soundatloc)(char*sound, float volume, float *org); + + unsigned short (*precacheevent)(int evtype, char *name); + void (*playevent)(int flags, struct hledict_s *ent, unsigned short evindex, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2); + void (*weaponanimate)(int anim, int body); + float (*randfloat) (float minv, float maxv); + long (*randlong) (long minv, long maxv); + void (*hookevent) (char *name, void (*func)(struct hlevent_s *event)); + int (*con_isshown) (void); + char *(*getgamedir) (void); + struct hlcvar_s *(*cvar_find) (char *name); + char *(*lookupbinding) (char *command); + char *(*getlevelname) (void); + void (*getscreenfade) (struct hlsfade_s *fade); + void (*setscreenfade) (struct hlsfade_s *fade); + void *(*vgui_getpanel) (void); + void (*vgui_paintback) (int extents[4]); + + void *(*loadfile) (char *path, int onhunk, int *length); + char *(*parsefile) (char *data, char *token); + void (*freefile) (void *file); + + struct hl_tri_api_s + { + int vers; + int sentinal; + } *triapi; + struct hl_sfx_api_s + { + int vers; + int sentinal; + } *efxapi; + struct hl_event_api_s + { + int vers; + int sentinal; + } *eventapi; + struct hl_demo_api_s + { + int (*isrecording)(void); + int (*isplaying)(void); + int (*istimedemo)(void); + void (*writedata)(int size, void *data); + + int sentinal; + } *demoapi; + struct hl_net_api_s + { + int vers; + int sentinal; + } *netapi; + + struct hl_voicetweek_s + { + int sentinal; + } *voiceapi; + + int (*forcedspectator) (void); + model_t *(*loadmapsprite) (char *name); + + void (*fs_addgamedir) (char *basedir, char *appname); + int (*expandfilename) (char *filename, char *outbuff, int outsize); + + char *(*player_key) (int pnum, char *key); + void (*player_setkey) (char *key, char *value); //wait, no pnum? + + qboolean (*getcdkey) (int playernum, char key[16]); + int trackerfromplayer; + int playerfromtracker; + int (*sendcmd_unreliable) (char *cmd); + void (*getsysmousepos) (long *xandy); + void (*setsysmousepos) (int x, int y); + void (*setmouseenable) (qboolean enable); +#endif + + int sentinal; +} CLHL_enginecgamefuncs_t; + + +typedef struct +{ + int (*HUD_VidInit) (void); + int (*HUD_Init) (void); + int (*HUD_Shutdown) (void); + int (*HUD_Redraw) (float maptime, int inintermission); + int (*HUD_UpdateClientData) (hllocalclientdata_t *localclientdata, float maptime); + int (*HUD_Reset) (void); +#if HLCL_API_VERSION >= 7 + void (*CL_CreateMove) (float frametime, hlusercmd_t *cmd, int isplaying); + void (*IN_ActivateMouse) (void); + void (*IN_DeactivateMouse) (void); + void (*IN_MouseEvent) (int buttonmask); +#endif +} CLHL_cgamefuncs_t; + + + +//FIXME +typedef struct +{ + vec3_t origin; + vec3_t oldorigin; + + int firstframe; + int numframes; + + int type; + vec3_t angles; + int flags; + float alpha; + float start; + float framerate; + model_t *model; + int skinnum; +} explosion_t; + + + + + +typedef struct +{ + char name[64]; + int (*hook) (char *name, int bufsize, void *bufdata); +} CLHL_UserMessages_t; +CLHL_UserMessages_t usermsgs[256]; + +int numnewhooks; +CLHL_UserMessages_t pendingusermsgs[256]; + + +static HLPIC selectedpic; + +float hl_viewmodelsequencetime; +int hl_viewmodelsequencecur; +int hl_viewmodelsequencebody; + + + + + +HLPIC CLGHL_pic_load (char *picname) +{ + return Mod_ForName(picname, false); +// return Draw_SafeCachePic(picname); +} +int CLGHL_pic_getnumframes (HLPIC pic) +{ + if (pic) + return pic->numframes; + else + return 0; +} + +static mspriteframe_t *getspriteframe(HLPIC pic, int frame) +{ + msprite_t *psprite; + mspritegroup_t *pgroup; + if (!pic) + return NULL; + psprite = pic->cache.data; + if (!psprite) + return NULL; + + if (psprite->frames[frame].type == SPR_SINGLE) + return psprite->frames[frame].frameptr; + else + { + pgroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + return pgroup->frames[0]; + } +} +static mpic_t *getspritepic(HLPIC pic, int frame) +{ + mspriteframe_t *f; + f = getspriteframe(pic, frame); + if (f) + return &f->p; + return NULL; +} + +int CLGHL_pic_getheight (HLPIC pic, int frame) +{ + mspriteframe_t *pframe; + + pframe = getspriteframe(pic, frame); + if (!pframe) + return 0; + + return pframe->p.width; +} +int CLGHL_pic_getwidth (HLPIC pic, int frame) +{ + mspriteframe_t *pframe; + + pframe = getspriteframe(pic, frame); + if (!pframe) + return 0; + + return pframe->p.height; +} +void CLGHL_pic_select (HLPIC pic, int r, int g, int b) +{ + selectedpic = pic; + Draw_ImageColours(r/255.0f, g/255.0f, b/255.0f, 1); +} +void CLGHL_pic_drawcuropaque (int frame, int x, int y, hlsubrect_t *loc) +{ + mpic_t *pic = getspritepic(selectedpic, frame); + if (!pic) + return; + + //faster SW render: no blends/holes + pic->flags &= ~1; + + Draw_Image(x, y, + loc->r-loc->l, loc->b-loc->t, + (float)loc->l/pic->width, (float)loc->t/pic->height, + (float)loc->r/pic->width, (float)loc->b/pic->height, + pic); +} +void CLGHL_pic_drawcuralphtest (int frame, int x, int y, hlsubrect_t *loc) +{ + mpic_t *pic = getspritepic(selectedpic, frame); + if (!pic) + return; + //use some kind of alpha + pic->flags |= 1; + + Draw_Image(x, y, + loc->r-loc->l, loc->b-loc->t, + (float)loc->l/pic->width, (float)loc->t/pic->height, + (float)loc->r/pic->width, (float)loc->b/pic->height, + pic); +} +void CLGHL_pic_drawcuradditive (int frame, int x, int y, hlsubrect_t *loc) +{ + mpic_t *pic = getspritepic(selectedpic, frame); + if (!pic) + return; + + qglEnable (GL_BLEND); + qglBlendFunc(GL_ONE, GL_ONE); + + //use some kind of alpha + pic->flags |= 1; + if (loc) + { + Draw_Image(x, y, + loc->r-loc->l, loc->b-loc->t, + (float)loc->l/pic->width, (float)loc->t/pic->height, + (float)loc->r/pic->width, (float)loc->b/pic->height, + pic); + } + else + { + Draw_Image(x, y, + pic->width, pic->height, + 0, 0, + 1, 1, + pic); + } + qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} +void CLGHL_pic_enablescissor (int x, int y, int width, int height) +{ +} +void CLGHL_pic_disablescissor (void) +{ +} +hlspriteinf_t *CLGHL_pic_parsepiclist (char *filename, int *numparsed) +{ + hlspriteinf_t *result; + int entry; + int entries; + void *file; + char *pos; + + *numparsed = 0; + + FS_LoadFile(filename, &file); + if (!file) + return NULL; + pos = file; + + pos = COM_Parse(pos); + entries = atoi(com_token); + + //name, res, pic, x, y, w, h + + result = Z_Malloc(sizeof(*result)*entries); + for (entry = 0; entry < entries; entry++) + { + pos = COM_Parse(pos); + Q_strncpyz(result[entry].name, com_token, sizeof(result[entry].name)); + + pos = COM_Parse(pos); + result[entry].forscrwidth = atoi(com_token); + + pos = COM_Parse(pos); + Q_strncpyz(result[entry].sprite, com_token, sizeof(result[entry].name)); + + pos = COM_Parse(pos); + result[entry].rect.l = atoi(com_token); + + pos = COM_Parse(pos); + result[entry].rect.t = atoi(com_token); + + pos = COM_Parse(pos); + result[entry].rect.r = result[entry].rect.l+atoi(com_token); + + pos = COM_Parse(pos); + result[entry].rect.b = result[entry].rect.t+atoi(com_token); + + if (pos) + *numparsed = entry; + } + + if (!pos || COM_Parse(pos)) + Con_Printf("unexpected end of file\n"); + + FS_FreeFile(file); + + return result; +} + +void CLGHL_fillrgba (int x, int y, int width, int height, int r, int g, int b, int a) +{ +} +int CLGHL_getscreeninfo (hlscreeninfo_t *info) +{ + int i; + if (info->size != sizeof(*info)) + return false; + + info->width = vid.width; + info->height = vid.height; + info->flags = 0; + info->charheight = 8; + for (i = 0; i < 256; i++) + info->charwidths[i] = 8; + + return true; +} +void CLGHL_setcrosshair (HLPIC pic, hlsubrect_t rect, int r, int g, int b) +{ +} + +int CLGHL_cvar_register (char *name, char *defvalue, int flags) +{ + if (Cvar_Get(name, defvalue, 0, "Halflife cvars")) + return GHL_CVarGetPointer(name); + else + return false; +} +float CLGHL_cvar_getfloat (char *name) +{ + cvar_t *var = Cvar_FindVar(name); + if (var) + return var->value; + return 0; +} +char *CLGHL_cvar_getstring (char *name) +{ + cvar_t *var = Cvar_FindVar(name); + if (var) + return var->string; + return ""; +} + +void CLGHL_cmd_register (char *name, xcommand_t func) +{ + Cmd_AddRemCommand(name, func); +} +void CLGHL_hooknetmsg (char *msgname, void *func) +{ + int i; + //update the current list now. + for (i = 0; i < sizeof(usermsgs)/sizeof(usermsgs[0]); i++) + { + if (!strcmp(usermsgs[i].name, msgname)) + { + usermsgs[i].hook = func; + break; //one per name + } + } + + //we already asked for it perhaps? + for (i = 0; i < numnewhooks; i++) + { + if (!strcmp(pendingusermsgs[i].name, msgname)) + { + pendingusermsgs[i].hook = func; + return; //nothing to do + } + } + + Q_strncpyz(pendingusermsgs[numnewhooks].name, msgname, sizeof(pendingusermsgs[i].name)); + pendingusermsgs[numnewhooks].hook = func; + numnewhooks++; +} +void CLGHL_forwardcmd (char *command) +{ + CL_SendClientCommand(true, "%s", command); +} +void CLGHL_localcmd (char *command) +{ + Cbuf_AddText(command, RESTRICT_SERVER); +} + +void CLGHL_getplayerinfo (int entnum, hlplayerinfo_t *result) +{ + notimp(__LINE__); +} + +void CLGHL_startsound_name (char *name, float vol) +{ + sfx_t *sfx = S_PrecacheSound (name); + if (!sfx) + { + Con_Printf ("CLGHL_startsound_name: can't cache %s\n", name); + return; + } + S_StartSound (-1, -1, sfx, vec3_origin, vol, 1); +} +void CLGHL_startsound_idx (int idx, float vol) +{ + sfx_t *sfx = cl.sound_precache[idx]; + if (!sfx) + { + Con_Printf ("CLGHL_startsound_name: index not precached %s\n", name); + return; + } + S_StartSound (-1, -1, sfx, vec3_origin, vol, 1); +} + +void CLGHL_anglevectors (float *ina, float *outf, float *outr, float *outu) +{ + AngleVectors(ina, outf, outr, outu); +} + +hlmsginfo_t *CLGHL_get_message_info (char *name) +{ + //fixme: add parser + return NULL; +} +int CLGHL_drawchar (int x, int y, int charnum, int r, int g, int b) +{ + return 0; +} +int CLGHL_drawstring (int x, int y, char *string) +{ + return 0; +} +void CLGHL_settextcolour(float r, float g, float b) +{ +} +void CLGHL_drawstring_getlen (char *string, int *outlen, int *outheight) +{ + *outlen = strlen(string)*8; + *outheight = 8; +} +void CLGHL_consoleprint (char *str) +{ + Con_Printf("%s", str); +} +void CLGHL_centerprint (char *str) +{ + SCR_CenterPrint(0, str, true); +} + + +int CLGHL_getwindowcenterx(void) +{ + return window_center_x; +} +int CLGHL_getwindowcentery(void) +{ + return window_center_y; +} +void CLGHL_getviewnangles(float*ang) +{ + VectorCopy(cl.viewangles[0], ang); +} +void CLGHL_setviewnangles(float*ang) +{ + VectorCopy(ang, cl.viewangles[0]); +} +void CLGHL_getmaxclients(float*ang){notimp(__LINE__);} +void CLGHL_cvar_setvalue(char *cvarname, char *value){notimp(__LINE__);} + +int CLGHL_cmd_argc(void) +{ + return Cmd_Argc(); +} +char *CLGHL_cmd_argv(int i) +{ + return Cmd_Argv(i); +} +#define CLGHL_con_printf Con_Printf//void CLGHL_con_printf(char *fmt, ...){notimp(__LINE__);} +#define CLGHL_con_dprintf Con_DPrintf//void CLGHL_con_dprintf(char *fmt, ...){notimp(__LINE__);} +void CLGHL_con_notificationprintf(int pos, char *fmt, ...){notimp(__LINE__);} +void CLGHL_con_notificationprintfex(void *info, char *fmt, ...){notimp(__LINE__);} +char *CLGHL_physkey(char *key){notimp(__LINE__);return NULL;} +char *CLGHL_serverkey(char *key){notimp(__LINE__);return NULL;} +float CLGHL_getclientmaxspeed(void) +{ + return 320; +} +int CLGHL_checkparm(char *str, const char **next) +{ + int i; + i = COM_CheckParm(str); + if (next) + { + if (i && i+1= 241 && key <= 241+5) + Key_Event(K_MOUSE1+key-241, down); + else + Con_Printf("CLGHL_keyevent: Unrecognised HL key code\n"); +} +void CLGHL_getmousepos(int *outx, int *outy){notimp(__LINE__);} +int CLGHL_movetypeisnoclip(void){notimp(__LINE__);return 0;} +struct hlclent_s *CLGHL_getlocalplayer(void){notimp(__LINE__);return NULL;} +struct hlclent_s *CLGHL_getviewent(void){notimp(__LINE__);return NULL;} +struct hlclent_s *CLGHL_getentidx(void){notimp(__LINE__);return NULL;} +float CLGHL_getlocaltime(void){return cl.time;} +void CLGHL_calcshake(void){notimp(__LINE__);} +void CLGHL_applyshake(float *origin, float *angles, float factor){notimp(__LINE__);} +int CLGHL_pointcontents(float *point, float *truecon){notimp(__LINE__);return 0;} +int CLGHL_entcontents(float *point){notimp(__LINE__);return 0;} +void CLGHL_traceline(float *start, float *end, int flags, int hull, int forprediction){notimp(__LINE__);} + +model_t *CLGHL_loadmodel(char *modelname, int *mdlindex){notimp(__LINE__);return Mod_ForName(modelname, false);} +int CLGHL_addrentity(int type, void *ent){notimp(__LINE__);return 0;} + +model_t *CLGHL_modelfrompic(HLPIC pic){notimp(__LINE__);return NULL;} +void CLGHL_soundatloc(char*sound, float volume, float *org){notimp(__LINE__);} + +unsigned short CLGHL_precacheevent(int evtype, char *name){notimp(__LINE__);return 0;} +void CLGHL_playevent(int flags, struct hledict_s *ent, unsigned short evindex, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2){notimp(__LINE__);} +void CLGHL_weaponanimate(int newsequence, int body) +{ + hl_viewmodelsequencetime = cl.time; + hl_viewmodelsequencecur = newsequence; + hl_viewmodelsequencebody = body; +} +float CLGHL_randfloat(float minv, float maxv){notimp(__LINE__);return minv;} +long CLGHL_randlong(long minv, long maxv){notimp(__LINE__);return minv;} +void CLGHL_hookevent(char *name, void (*func)(struct hlevent_s *event)){notimp(__LINE__);} +int CLGHL_con_isshown(void) +{ + return scr_con_current > 0; +} +char *CLGHL_getgamedir(void) +{ + extern char gamedirfile[]; + return gamedirfile; +} +struct hlcvar_s *CLGHL_cvar_find(char *name) +{ + return GHL_CVarGetPointer(name); +} +char *CLGHL_lookupbinding(char *command) +{ + return NULL; +} +char *CLGHL_getlevelname(void) +{ + return cl.levelname; +} +void CLGHL_getscreenfade(struct hlsfade_s *fade){notimp(__LINE__);} +void CLGHL_setscreenfade(struct hlsfade_s *fade){notimp(__LINE__);} +void *CLGHL_vgui_getpanel(void){notimp(__LINE__);return NULL;} +void CLGHL_vgui_paintback(int extents[4]){notimp(__LINE__);} + +void *CLGHL_loadfile(char *path, int alloctype, int *length) +{ + void *ptr = NULL; + int flen = -1; + if (alloctype == 5) + { + flen = FS_LoadFile(path, &ptr); + } + else + notimp(__LINE__); //don't leak, just fail + + if (length) + *length = flen; + + return ptr; +} +char *CLGHL_parsefile(char *data, char *token) +{ + return COM_ParseOut(data, token, 1024); +} +void CLGHL_freefile(void *file) +{ + //only valid for alloc type 5 + FS_FreeFile(file); +} + + +int CLGHL_forcedspectator(void) +{ + return cls.demoplayback; +} +model_t *CLGHL_loadmapsprite(char *name) +{ + notimp(__LINE__);return NULL; +} + +void CLGHL_fs_addgamedir(char *basedir, char *appname){notimp(__LINE__);return NULL;} +int CLGHL_expandfilename(char *filename, char *outbuff, int outsize){notimp(__LINE__);return NULL;} + +char *CLGHL_player_key(int pnum, char *key){notimp(__LINE__);return NULL;} +void CLGHL_player_setkey(char *key, char *value){notimp(__LINE__);return NULL;} + +qboolean CLGHL_getcdkey(int playernum, char key[16]){notimp(__LINE__);return false;} +int CLGHL_trackerfromplayer(int pslot){notimp(__LINE__);return 0;} +int CLGHL_playerfromtracker(int tracker){notimp(__LINE__);return 0;} +int CLGHL_sendcmd_unreliable(char *cmd){notimp(__LINE__);return 0;} +void CLGHL_getsysmousepos(long *xandy) +{ +#ifdef _WIN32 + GetCursorPos((LPPOINT)xandy); +#endif +} +void CLGHL_setsysmousepos(int x, int y) +{ +#ifdef _WIN32 + SetCursorPos(x, y); +#endif +} +void CLGHL_setmouseenable(qboolean enable) +{ + extern cvar_t _windowed_mouse; + Cvar_Set(&_windowed_mouse, enable?"1":"0"); +} + + + + +int CLGHL_demo_isrecording(void) +{ + return cls.demorecording; +} +int CLGHL_demo_isplaying(void) +{ + return cls.demoplayback; +} +int CLGHL_demo_istimedemo(void) +{ + return cls.timedemo; +} +void CLGHL_demo_writedata(int size, void *data) +{ + notimp(__LINE__); +} + +struct hl_demo_api_s hl_demo_api = +{ + CLGHL_demo_isrecording, + CLGHL_demo_isplaying, + CLGHL_demo_istimedemo, + CLGHL_demo_writedata, + + 0xdeadbeef +}; + +CLHL_cgamefuncs_t CLHL_cgamefuncs; +CLHL_enginecgamefuncs_t CLHL_enginecgamefuncs = +{ + CLGHL_pic_load, + CLGHL_pic_getnumframes, + CLGHL_pic_getheight, + CLGHL_pic_getwidth, + CLGHL_pic_select, + CLGHL_pic_drawcuropaque, + CLGHL_pic_drawcuralphtest, + CLGHL_pic_drawcuradditive, + CLGHL_pic_enablescissor, + CLGHL_pic_disablescissor, + CLGHL_pic_parsepiclist, + + CLGHL_fillrgba, + CLGHL_getscreeninfo, + CLGHL_setcrosshair, + + CLGHL_cvar_register, + CLGHL_cvar_getfloat, + CLGHL_cvar_getstring, + + CLGHL_cmd_register, + CLGHL_hooknetmsg, + CLGHL_forwardcmd, + CLGHL_localcmd, + + CLGHL_getplayerinfo, + + CLGHL_startsound_name, + CLGHL_startsound_idx, + + CLGHL_anglevectors, + + CLGHL_get_message_info, + CLGHL_drawchar, + CLGHL_drawstring, +#if HLCL_API_VERSION >= 7 + CLGHL_settextcolour, +#endif + CLGHL_drawstring_getlen, + CLGHL_consoleprint, + CLGHL_centerprint, + +#if HLCL_API_VERSION >= 7 + CLGHL_getwindowcenterx, + CLGHL_getwindowcentery, + CLGHL_getviewnangles, + CLGHL_setviewnangles, + CLGHL_getmaxclients, + CLGHL_cvar_setvalue, + + CLGHL_cmd_argc, + CLGHL_cmd_argv, + CLGHL_con_printf, + CLGHL_con_dprintf, + CLGHL_con_notificationprintf, + CLGHL_con_notificationprintfex, + CLGHL_physkey, + CLGHL_serverkey, + CLGHL_getclientmaxspeed, + CLGHL_checkparm, + CLGHL_keyevent, + CLGHL_getmousepos, + CLGHL_movetypeisnoclip, + CLGHL_getlocalplayer, + CLGHL_getviewent, + CLGHL_getentidx, + CLGHL_getlocaltime, + CLGHL_calcshake, + CLGHL_applyshake, + CLGHL_pointcontents, + CLGHL_entcontents, + CLGHL_traceline, + + CLGHL_loadmodel, + CLGHL_addrentity, + + CLGHL_modelfrompic, + CLGHL_soundatloc, + + CLGHL_precacheevent, + CLGHL_playevent, + CLGHL_weaponanimate, + CLGHL_randfloat, + CLGHL_randlong, + CLGHL_hookevent, + CLGHL_con_isshown, + CLGHL_getgamedir, + CLGHL_cvar_find, + CLGHL_lookupbinding, + CLGHL_getlevelname, + CLGHL_getscreenfade, + CLGHL_setscreenfade, + CLGHL_vgui_getpanel, + CLGHL_vgui_paintback, + + CLGHL_loadfile, + CLGHL_parsefile, + CLGHL_freefile, + + NULL, //triapi; + NULL, //efxapi; + NULL, //eventapi; + &hl_demo_api, + NULL, //netapi; + +//sdk 2.3+ + NULL, //voiceapi; + + CLGHL_forcedspectator, + CLGHL_loadmapsprite, + + CLGHL_fs_addgamedir, + CLGHL_expandfilename, + + CLGHL_player_key, + CLGHL_player_setkey, + + CLGHL_getcdkey, + (void*)0xdeaddead,//CLGHL_trackerfromplayer; + (void*)0xdeaddead,//CLGHL_playerfromtracker; + CLGHL_sendcmd_unreliable, + CLGHL_getsysmousepos, + CLGHL_setsysmousepos, + CLGHL_setmouseenable, +#endif + + 0xdeadbeef +}; + +dllhandle_t clg; + +int CLHL_GamecodeDoesMouse(void) +{ + if (!clg || !CLHL_cgamefuncs.CL_CreateMove) + return false; + return true; +} + +int CLHL_MouseEvent(unsigned int buttonmask) +{ + if (!CLHL_GamecodeDoesMouse()) + return false; + + CLHL_cgamefuncs.IN_MouseEvent(buttonmask); + return true; +} + +void CLHL_SetMouseActive(int activate) +{ + static int oldactive; + if (!clg) + { + oldactive = false; + return; + } + if (activate == oldactive) + return; + oldactive = activate; + + if (activate) + { + if (CLHL_cgamefuncs.IN_ActivateMouse) + CLHL_cgamefuncs.IN_ActivateMouse(); + } + else + { + if (CLHL_cgamefuncs.IN_DeactivateMouse) + CLHL_cgamefuncs.IN_DeactivateMouse(); + } +} + +void CLHL_UnloadClientGame(void) +{ + if (!clg) + return; + + CLHL_SetMouseActive(false); + if (CLHL_cgamefuncs.HUD_Shutdown) + CLHL_cgamefuncs.HUD_Shutdown(); + Sys_CloseLibrary(clg); + memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs)); + clg = NULL; + + hl_viewmodelsequencetime = 0; +} + +void CLHL_LoadClientGame(void) +{ + char fullname[MAX_OSPATH]; + char *path; + + int (*initfunc)(CLHL_enginecgamefuncs_t *funcs, int version); + dllfunction_t funcs[] = + { + {(void*)&initfunc, "Initialize"}, + {(void*)&CLHL_cgamefuncs.HUD_VidInit, "HUD_VidInit"}, + {(void*)&CLHL_cgamefuncs.HUD_Init, "HUD_Init"}, + {(void*)&CLHL_cgamefuncs.HUD_Shutdown, "HUD_Shutdown"}, + {(void*)&CLHL_cgamefuncs.HUD_Redraw, "HUD_Redraw"}, + {(void*)&CLHL_cgamefuncs.HUD_UpdateClientData, "HUD_UpdateClientData"}, + {(void*)&CLHL_cgamefuncs.HUD_Reset, "HUD_Reset"}, +#if HLCL_API_VERSION >= 7 + {(void*)&CLHL_cgamefuncs.CL_CreateMove, "CL_CreateMove"}, + {(void*)&CLHL_cgamefuncs.IN_ActivateMouse, "IN_ActivateMouse"}, + {(void*)&CLHL_cgamefuncs.IN_DeactivateMouse, "IN_DeactivateMouse"}, + {(void*)&CLHL_cgamefuncs.IN_MouseEvent, "IN_MouseEvent"}, +#endif + {NULL} + }; + + CLHL_UnloadClientGame(); + + memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs)); + + path = NULL; + while((path = COM_NextPath (path))) + { + if (!path) + return NULL; // couldn't find one anywhere + snprintf (fullname, sizeof(fullname), "%s/%s", path, "cl_dlls/client"); + clg = Sys_LoadLibrary(fullname, funcs); + if (clg) + break; + } + + if (!clg) + return; + + if (!initfunc(&CLHL_enginecgamefuncs, HLCL_API_VERSION)) + { + Sys_CloseLibrary(clg); + clg = NULL; + return; + } + + CLHL_cgamefuncs.HUD_Init(); + CLHL_cgamefuncs.HUD_VidInit(); +} + +int CLHL_BuildUserInput(int msecs, usercmd_t *cmd) +{ + hlusercmd_t hlcmd; + if (!clg || !CLHL_cgamefuncs.CL_CreateMove) + return false; + + CLHL_cgamefuncs.CL_CreateMove(msecs/255.0f, &hlcmd, cls.state>=ca_active && !cls.demoplayback); + +#define ANGLE2SHORT(x) (x) * (65536/360.0) + cmd->msec = msecs; + cmd->angles[0] = ANGLE2SHORT(hlcmd.viewangles[0]); + cmd->angles[1] = ANGLE2SHORT(hlcmd.viewangles[1]); + cmd->angles[2] = ANGLE2SHORT(hlcmd.viewangles[2]); + cmd->forwardmove = hlcmd.forwardmove; + cmd->sidemove = hlcmd.sidemove; + cmd->upmove = hlcmd.upmove; + cmd->weapon = hlcmd.weaponselect; + cmd->impulse = hlcmd.impulse; + cmd->buttons = hlcmd.buttons; + cmd->lightlevel = hlcmd.lightlevel; + return true; +} + +int CLHL_DrawHud(void) +{ + extern kbutton_t in_attack; + hllocalclientdata_t state; + + if (!clg || !CLHL_cgamefuncs.HUD_Redraw) + return false; + +// state.origin; +// state.viewangles; +#if HLCL_API_VERSION < 7 +// state.viewheight; +// state.maxspeed; +// state.punchangles; + state.idlescale = 0; + state.mousesens = 0; + state.keys = (in_attack.state[0]&3)?1:0; +#endif + state.weapons = cl.stats[0][STAT_ITEMS]; + state.fov = 90; + + V_StopPitchDrift(0); + + CLHL_cgamefuncs.HUD_UpdateClientData(&state, cl.time); + + return CLHL_cgamefuncs.HUD_Redraw(cl.time, cl.intermission); +} + +int CLHL_AnimateViewEntity(entity_t *ent) +{ + float time; + if (!hl_viewmodelsequencetime) + return false; + + time = cl.time - hl_viewmodelsequencetime; + ent->framestate.g[FS_REG].frame[0] = hl_viewmodelsequencecur; + ent->framestate.g[FS_REG].frame[1] = hl_viewmodelsequencecur; + ent->framestate.g[FS_REG].frametime[0] = time; + ent->framestate.g[FS_REG].frametime[1] = time; + return true; +} + +int CLHL_ParseGamePacket(void) +{ + int subcode; + char *end; + char *str; + int tempi; + + end = net_message.data+msg_readcount+2+MSG_ReadShort(); + + if (end > net_message.data+net_message.cursize) + return false; + + subcode = MSG_ReadByte(); + + if (usermsgs[subcode].hook) + if (usermsgs[subcode].hook(usermsgs[subcode].name, end - (net_message.data+msg_readcount), net_message.data+msg_readcount)) + { + msg_readcount = end - net_message.data; + return true; + } + + switch(subcode) + { + case 1: + //register the server-sent code. + tempi = MSG_ReadByte(); + str = MSG_ReadString(); + Q_strncpyz(usermsgs[tempi].name, str, sizeof(usermsgs[tempi].name)); + + //get the builtin to reregister its hooks. + for (tempi = 0; tempi < numnewhooks; tempi++) + CLGHL_hooknetmsg(pendingusermsgs[tempi].name, pendingusermsgs[tempi].hook); + break; + case svc_temp_entity: + { + vec3_t startp, endp, vel; + float ang; + int midx; + int mscale; + int mrate; + int flags; + int lifetime; + explosion_t *ef; + extern cvar_t temp1; + + subcode = MSG_ReadByte(); + + if (temp1.value) + Con_Printf("Temp ent %i\n", subcode); + switch(subcode) + { + case 3: + MSG_ReadPos(startp); + midx = MSG_ReadShort(); + mscale = MSG_ReadByte(); + mrate = MSG_ReadByte(); + flags = MSG_ReadByte(); + if (!(flags & 8)) + P_RunParticleEffectType(startp, NULL, 1, pt_explosion); + if (!(flags & 4)) + S_StartSound(0, 0, S_PrecacheSound("explosion"), startp, 1, 1); + if (!(flags & 2)) + CL_NewDlightRGB(0, startp[0], startp[1], startp[2], 200, 1, 0.2,0.2,0.2); + + ef = CL_AllocExplosion(); + VectorCopy(startp, ef->origin); + ef->start = cl.time; + ef->model = cl.model_precache[midx]; + ef->framerate = mrate; + ef->firstframe = 0; + ef->numframes = ef->model->numframes; + if (!(flags & 1)) + ef->flags = Q2RF_ADDATIVE; + else + ef->flags = 0; + break; + case 4: + MSG_ReadPos(startp); + P_RunParticleEffectType(startp, NULL, 1, pt_tarexplosion); + break; + case 5: + MSG_ReadPos(startp); + MSG_ReadShort(); + MSG_ReadByte(); + MSG_ReadByte(); + break; + case 6: + MSG_ReadPos(startp); + MSG_ReadPos(endp); + break; + case 9: + MSG_ReadPos(startp); + P_RunParticleEffectType(startp, NULL, 1, ptdp_spark); + break; + case 22: + MSG_ReadShort(); + MSG_ReadShort(); + MSG_ReadByte(); + MSG_ReadByte(); + MSG_ReadByte(); + MSG_ReadByte(); + MSG_ReadByte(); + break; + case 23: + MSG_ReadPos(startp); + MSG_ReadShort(); + MSG_ReadByte(); + MSG_ReadByte(); + MSG_ReadByte(); + break; + case 106: + MSG_ReadPos(startp); + MSG_ReadPos(vel); + ang = MSG_ReadAngle(); + midx = MSG_ReadShort(); + MSG_ReadByte(); + lifetime = MSG_ReadByte(); + + ef = CL_AllocExplosion(); + VectorCopy(startp, ef->origin); + ef->start = cl.time; + ef->angles[1] = ang; + ef->model = cl.model_precache[midx]; + ef->firstframe = 0; + ef->numframes = lifetime; + ef->flags = 0; + ef->framerate = 10; + break; + case 108: + MSG_ReadPos(startp); + MSG_ReadPos(endp); + MSG_ReadPos(vel); + MSG_ReadByte(); + MSG_ReadShort(); + MSG_ReadByte(); + MSG_ReadByte(); + MSG_ReadByte(); + break; + case 109: + MSG_ReadPos(startp); + MSG_ReadShort(); + MSG_ReadByte(); + break; + case 116: + MSG_ReadPos(startp); + MSG_ReadByte(); + break; + case 117: + MSG_ReadPos(startp); + MSG_ReadByte()+256; + break; + case 118: + MSG_ReadPos(startp); + MSG_ReadByte()+256; + break; + default: + Con_Printf("CLHL_ParseGamePacket: Unable to parse gamecode tempent %i\n", subcode); + msg_readcount = end - net_message.data; + break; + } + } + if (msg_readcount != end - net_message.data) + { + Con_Printf("CLHL_ParseGamePacket: Gamecode temp entity %i not parsed correctly read %i bytes too many\n", subcode, msg_readcount - (end - net_message.data)); + msg_readcount = end - net_message.data; + } + break; + case svc_intermission: + //nothing. + cl.intermission = true; + break; + case svc_cdtrack: + cl.cdtrack = MSG_ReadByte(); + MSG_ReadByte(); + CDAudio_Play ((qbyte)cl.cdtrack, true); + break; + + case 35: //svc_weaponanimation: + tempi = MSG_ReadByte(); + CLGHL_weaponanimate(tempi, MSG_ReadByte()); + break; + case 37: //svc_roomtype + tempi = MSG_ReadShort(); + SNDDMA_SetUnderWater(tempi==14||tempi==15||tempi==16); + break; + default: + Con_Printf("Unrecognised gamecode packet %i (%s)\n", subcode, usermsgs[subcode].name); + msg_readcount = end - net_message.data; + break; + } + + if (msg_readcount != end - net_message.data) + { + Con_Printf("CLHL_ParseGamePacket: Gamecode packet %i not parsed correctly read %i bytestoo many\n", subcode, msg_readcount - (end - net_message.data)); + msg_readcount = end - net_message.data; + } + return true; +} + +#endif diff --git a/engine/client/client.h b/engine/client/client.h index 39c1fb07a..915961ffb 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -552,6 +552,7 @@ typedef struct char levelname[40]; // for display on solo scoreboard int playernum[MAX_SPLITS]; + qboolean nolocalplayer[MAX_SPLITS]; int splitclients; //we are running this many clients split screen. // refresh related state @@ -804,6 +805,28 @@ void CL_QTVDemos_f (void); void CL_DemoJump_f(void); void CL_ProgressDemoTime(void); void CL_TimeDemo_f (void); +typedef struct +{ + enum + { + QTVCT_NONE, + QTVCT_STREAM, + QTVCT_CONNECT, + QTVCT_JOIN, + QTVCT_OBSERVE, + } connectiontype; + enum + { + QTVCT_NETQUAKE, + QTVCT_QUAKEWORLD, + QTVCT_QUAKE2, + QTVCT_QUAKE3 + } protocol; + char server[256]; + char splashscreen[256]; + //char *datafiles; +} qtvfile_t; +void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result); // // cl_parse.c diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index ee0df9415..1de2e48eb 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -464,8 +464,6 @@ qboolean CLQ3_SystemInfoChanged(char *str) Info_SetValueForStarKey (svs.info, "*gamedir", value, MAX_SERVERINFO_STRING); #endif COM_FlushFSCache(); - - Shader_Init(); } if (usingpure) @@ -607,7 +605,7 @@ void CLQ3_ParseGameState(void) { char buffer[2048]; strcpy(buffer, va("cp %i ", cl.servercount)); - FS_GenerateClientPacksList(buffer, sizeof(buffer), ccs.fs_key); + FSQ3_GenerateClientPacksList(buffer, sizeof(buffer), ccs.fs_key); CLQ3_SendClientCommand(buffer); } diff --git a/engine/client/console.c b/engine/client/console.c index 1cfd08434..843eb7258 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -894,6 +894,9 @@ The input line scrolls horizontally if typing goes beyond the right edge */ void Con_DrawInput (void) { +#ifdef _WIN32 + extern qboolean ActiveApp; +#endif int y; int i; int p; @@ -999,6 +1002,9 @@ void Con_DrawInput (void) } } +#ifdef _WIN32 + if (ActiveApp) +#endif if (((int)(realtime*con_cursorspeed)&1)) { maskedtext[key_linepos] = 11|CON_WHITEMASK; //make it blink diff --git a/engine/client/image.c b/engine/client/image.c index 37b52d660..9b2c0d1d9 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -584,7 +584,7 @@ void VARGS readpngdata(png_structp png_ptr,png_bytep data,png_size_t len) } qbyte *png_rgba; -qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, char *fname) +qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, const char *fname) { qbyte header[8], **rowpointers = NULL, *data = NULL; png_structp png; @@ -702,12 +702,10 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i png_structp png_ptr; png_infop info_ptr; png_byte **row_pointers; - snprintf (name, sizeof(name)-1, "%s/%s", com_gamedir, filename); - if (Sys_PathProtection(filename) ) + if (!FS_NativePath(filename, FS_GAMEONLY, name, sizeof(name))) return false; - if (!(fp = fopen (name, "wb"))) { COM_CreatePath (name); @@ -1146,7 +1144,7 @@ void screenshotJPEG(char *filename, int compression, qbyte *screendata, int scre WritePCXfile ============== */ -void WritePCXfile (char *filename, qbyte *data, int width, int height, +void WritePCXfile (const char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload) //data is 8bit. { int i, j, length; diff --git a/engine/client/in_win.c b/engine/client/in_win.c index b3a32b6b5..2c05dc462 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -401,7 +401,7 @@ void IN_UpdateClipCursor (void) IN_ShowMouse =========== */ -void IN_ShowMouse (void) +static void IN_ShowMouse (void) { if (!mouseshowtoggle) @@ -417,7 +417,7 @@ void IN_ShowMouse (void) IN_HideMouse =========== */ -void IN_HideMouse (void) +static void IN_HideMouse (void) { if (mouseshowtoggle) @@ -433,12 +433,12 @@ void IN_HideMouse (void) IN_ActivateMouse =========== */ -void IN_ActivateMouse (void) +static void IN_ActivateMouse (void) { mouseactivatetoggle = true; - if (mouseinitialized) + if (mouseinitialized && !mouseactive) { #ifdef AVAIL_DINPUT #if (DIRECTINPUT_VERSION >= DINPUT_VERSION_DX7) @@ -502,31 +502,17 @@ void IN_ActivateMouse (void) } -/* -=========== -IN_SetQuakeMouseState -=========== -*/ -void IN_SetQuakeMouseState (void) -{ - if (mouseactivatetoggle) - IN_ActivateMouse (); - else - IN_DeactivateMouse(); -} - - /* =========== IN_DeactivateMouse =========== */ -void IN_DeactivateMouse (void) +static void IN_DeactivateMouse (void) { mouseactivatetoggle = false; - if (mouseinitialized) + if (mouseinitialized && mouseactive) { #ifdef AVAIL_DINPUT #if (DIRECTINPUT_VERSION >= DINPUT_VERSION_DX7) @@ -579,6 +565,18 @@ void IN_DeactivateMouse (void) } } +/* +=========== +IN_SetQuakeMouseState +=========== +*/ +void IN_SetQuakeMouseState (void) +{ + if (mouseactivatetoggle) + IN_ActivateMouse (); + else + IN_DeactivateMouse(); +} /* =========== @@ -599,6 +597,60 @@ void IN_RestoreOriginalMouseState (void) ShowCursor (FALSE); } + + + +void IN_UpdateGrabs(int fullscreen, int activeapp) +{ + int grabmouse; + + if (fullscreen) + grabmouse = true; + else if (activeapp && _windowed_mouse.value) + { + if (!Key_MouseShouldBeFree()) + grabmouse = true; + else + grabmouse = false; + } + else + grabmouse = false; + + //visiblity + if (grabmouse) + IN_HideMouse(); + else + IN_ShowMouse(); + +#ifdef HLCLIENT + //halflife gamecode does its own mouse control... yes this is vile. + if (grabmouse) + { + if (CLHL_GamecodeDoesMouse()) + grabmouse = 2; + } + + if (grabmouse == 2) + { + IN_DeactivateMouse(); + CLHL_SetMouseActive(true); + return; + } + + CLHL_SetMouseActive(false); +#endif + + if (grabmouse) + IN_ActivateMouse(); + else + IN_DeactivateMouse(); +} + + + + + + #ifdef AVAIL_DINPUT BOOL CALLBACK IN_EnumerateDevices(LPCDIDEVICEINSTANCE inst, LPVOID parm) { @@ -1315,7 +1367,15 @@ void IN_MouseEvent (int mstate) { int i; - if ((mouseactive || (key_dest != key_game)) && !dinput) + if (dinput) + return; + +#ifdef HLCLIENT + if (CLHL_MouseEvent(mstate)) + return; +#endif + + if (mouseactive || (key_dest != key_game)) { // perform button actions for (i=0 ; iwheeldelta <= -mfwt) + if (mfwt) { - Key_Event (K_MWHEELUP, true); - Key_Event (K_MWHEELUP, false); - mouse->wheeldelta += mfwt; - } + while(mouse->wheeldelta <= -mfwt) + { + Key_Event (K_MWHEELUP, true); + Key_Event (K_MWHEELUP, false); + mouse->wheeldelta += mfwt; + } - while(mouse->wheeldelta >= mfwt) - { - Key_Event (K_MWHEELDOWN, true); - Key_Event (K_MWHEELDOWN, false); - mouse->wheeldelta -= mfwt; + while(mouse->wheeldelta >= mfwt) + { + Key_Event (K_MWHEELDOWN, true); + Key_Event (K_MWHEELDOWN, false); + mouse->wheeldelta -= mfwt; + } } if (m_forcewheel.value < 2) @@ -1460,10 +1523,6 @@ static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum) if (!cmd) { - if (mx || my) - { - SetCursorPos (window_center_x, window_center_y); - } return; } diff --git a/engine/client/keys.c b/engine/client/keys.c index b4cc5dc48..fa9afd89d 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -402,6 +402,7 @@ void Con_ExecuteLine(console_t *con, char *line) Cbuf_AddText ("\n", RESTRICT_LOCAL); if (!waschat || con_echochat.value) Con_Printf ("]%s\n",line); + if (cls.state == ca_disconnected) SCR_UpdateScreen (); // force an update, because the command // may take some time @@ -1372,7 +1373,7 @@ qboolean Key_MouseShouldBeFree(void) if (key_dest == key_menu) { - if (m_state == m_complex || m_state == m_plugin) + if (m_state == m_complex || m_state == m_plugin || m_state == m_menu_dat) return true; } if (key_dest == key_console) diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 577f8079e..821249c5f 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -1643,17 +1643,24 @@ void M_Menu_Main_f (void) if (!p) return; MC_AddPicture(mainm, 0, 173, "pics/m_main_logo"); +#ifndef CLIENTONLY MC_AddSelectablePicture(mainm, 68, 13, "pics/m_main_game"); +#endif MC_AddSelectablePicture(mainm, 68, 53, "pics/m_main_multiplayer"); MC_AddSelectablePicture(mainm, 68, 93, "pics/m_main_options"); MC_AddSelectablePicture(mainm, 68, 133, "pics/m_main_video"); MC_AddSelectablePicture(mainm, 68, 173, "pics/m_main_quit"); +#ifndef CLIENTONLY b = MC_AddConsoleCommand (mainm, 68, 13, "", "menu_single\n"); mainm->selecteditem = (menuoption_t *)b; b->common.width = 12*20; b->common.height = 20; +#endif b = MC_AddConsoleCommand (mainm, 68, 53, "", "menu_multi\n"); +#ifdef CLIENTONLY + mainm->selecteditem = (menuoption_t *)b; +#endif b->common.width = 12*20; b->common.height = 20; b = MC_AddConsoleCommand (mainm, 68, 93, "", "menu_options\n"); @@ -1666,7 +1673,7 @@ void M_Menu_Main_f (void) b->common.width = 12*20; b->common.height = 20; - mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 42, 13); + mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 42, mainm->selecteditem->common.posy); } return; } diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index f99a9d9d8..b19b7dfd9 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -120,7 +120,6 @@ void WinAmp_Think(void) #endif void Media_Seek (float time) { - soundcardinfo_t *sc; #ifdef WINAMP if (media_hijackwinamp.value) { @@ -135,18 +134,7 @@ void Media_Seek (float time) } } #endif - for (sc = sndcardinfo; sc; sc=sc->next) - { - sc->channel[NUM_AMBIENTS].pos += sc->sn.speed*time; - sc->channel[NUM_AMBIENTS].end += sc->sn.speed*time; - - if (sc->channel[NUM_AMBIENTS].pos < 0) - { - sc->channel[NUM_AMBIENTS].end -= sc->channel[NUM_AMBIENTS].pos; - sc->channel[NUM_AMBIENTS].pos=0; - } - //if we seek over the end, ignore it. The sound playing code will spot that. - } + S_Music_Seek(time); } void Media_FForward_f(void) @@ -226,23 +214,7 @@ qboolean Media_EvaluateNextTrack(void) //flushes music channel on all soundcards, and the tracks that arn't decoded yet. void Media_Clear (void) { - sfx_t *s; - soundcardinfo_t *sc; - for (sc = sndcardinfo; sc; sc=sc->next) - { - sc->channel[NUM_AMBIENTS].end = 0; - s = sc->channel[NUM_AMBIENTS].sfx; - sc->channel[NUM_AMBIENTS].sfx = NULL; - - if (s) - if (s->decoder) - if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly. - { - s->decoder->abort(s); - if (s->cache.data) - Cache_Free(&s->cache); - } - } + S_Music_Clear(NULL); } qboolean fakecdactive; @@ -250,6 +222,12 @@ void Media_FakeTrack(int i, qboolean loop) { char trackname[512]; + if (i > 999 || i < 0) + { + fakecdactive = false; + return; + } + sprintf(trackname, "sound/cdtracks/track%03i.ogg", i); if (COM_FCheckExists(trackname)) { @@ -259,6 +237,8 @@ void Media_FakeTrack(int i, qboolean loop) fakecdactive = true; media_playing = true; } + else + fakecdactive = false; } //actually, this func just flushes and states that it should be playing. the ambientsound func actually changes the track. @@ -414,11 +394,11 @@ void M_Media_Draw (void) char compleatenamepath[MAX_OSPATH]; char compleatenamename[MAX_OSPATH]; qboolean compleatenamemultiple; -int Com_CompleatenameCallback(char *name, int size, void *data) +int Com_CompleatenameCallback(const char *name, int size, void *data) { if (*compleatenamename) compleatenamemultiple = true; - strcpy(compleatenamename, name); + Q_strncpyz(compleatenamename, name, sizeof(compleatenamename)); return true; } @@ -727,7 +707,7 @@ void Media_LoadTrackNames (char *listname) } //safeprints only. -char *Media_NextTrack(void) +char *Media_NextTrack(int musicchannelnum) { #ifdef WINAMP if (media_hijackwinamp.value) @@ -885,15 +865,6 @@ struct cin_s { roq_info *roqfilm; } roq; - sfxcache_t *moviesoundbuffer; - sfx_t mediaaudio; -/* = { - "movieaudio", - {NULL, true}, - NULL - }; -*/ - float filmstarttime; float nextframetime; float filmlasttime; @@ -1173,7 +1144,7 @@ qboolean Media_Roq_DecodeFrame (cin_t *cin, qboolean nosound) cin->outdata = cin->framedata; if (!nosound) - if (cin->roq.roqfilm->audio_channels && sndcardinfo && cin->roq.roqfilm->aud_pos < cin->roq.roqfilm->vid_pos) + if (cin->roq.roqfilm->audio_channels && S_HaveOutput() && cin->roq.roqfilm->aud_pos < cin->roq.roqfilm->vid_pos) if (roq_read_audio(cin->roq.roqfilm)>0) { /* FILE *f; @@ -1260,10 +1231,6 @@ cin_t *Media_Static_TryLoad(char *name) char fullname[MAX_QPATH]; qbyte *file; - qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height); - qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey); - qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height); - qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, char *fname); sprintf(fullname, "%s", name); file = COM_LoadMallocFile(fullname); //read file @@ -1563,6 +1530,7 @@ void Media_Gecko_ChangeStream (struct cin_s *cin, char *streamname) cin_t *Media_Gecko_TryLoad(char *name) { + char xulprofiledir[MAX_OSPATH]; cin_t *cin; if (!strncmp(name, "http://", 7)) @@ -1585,7 +1553,8 @@ cin_t *Media_Gecko_TryLoad(char *name) return NULL; posgk_embedding_options_add_search_path(opts, "./xulrunner/"); - posgk_embedding_options_set_profile_dir(opts, va("%s/xulrunner_profile/", com_gamedir), 0); + if (FS_NativePath("xulrunner_profile/", FS_GAMEONLY, xulprofiledir, sizeof(xulprofiledir)); + posgk_embedding_options_set_profile_dir(opts, xulprofiledir, 0); gecko_embedding = posgk_embedding_create2(OSGK_API_VERSION, opts, &result); posgk_release(&opts->baseobj); @@ -1636,23 +1605,9 @@ qboolean Media_PlayingFullScreen(void) void Media_ShutdownCin(cin_t *cin) { - soundcardinfo_t *sc; - sfx_t *s; - if (!cin) return; - for (sc = sndcardinfo; sc; sc=sc->next) - { - s = sc->channel[NUM_AMBIENTS].sfx; - if (s && s == &cin->mediaaudio) - { - sc->channel[NUM_AMBIENTS].pos = 0; - sc->channel[NUM_AMBIENTS].end = 0; - sc->channel[NUM_AMBIENTS].sfx = NULL; - } - } - if (cin->shutdown) cin->shutdown(cin); diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 00c08a4c1..2d72ffd7e 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -112,6 +112,7 @@ typedef struct { menuedit_t *nameedit; menuedit_t *teamedit; menuedit_t *skinedit; + menucombo_t *modeledit; int topcolour; int lowercolour; @@ -175,6 +176,93 @@ qboolean SetupMenuColour (union menuoption_s *option,struct menu_s *menu, int ke } return false; } + + +typedef struct { + char **names; + int entries; + int match; +} q2skinsearch_t; + +int q2skin_enumerate(const char *name, int fsize, void *parm) +{ + char blah[MAX_QPATH]; + q2skinsearch_t *s = parm; + + COM_StripExtension(name+8, blah, sizeof(blah)); + if (strlen(blah) < 2) + return false; //this should never happen + blah[strlen(blah)-2] = 0; + + s->names = BZ_Realloc(s->names, ((s->entries+64)&~63) * sizeof(char*)); + s->names[s->entries] = BZ_Malloc(strlen(blah)+1); + strcpy(s->names[s->entries], blah); + + if (!strcmp(blah, skin.string)) + s->match = s->entries; + + s->entries++; + return true; +} +void q2skin_destroy(q2skinsearch_t *s) +{ + int i; + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s); +} + +qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct menu_s *menu, int key) +{ + setupmenu_t *info = menu->data; + q2skinsearch_t *s = Z_Malloc(sizeof(*s)); + COM_EnumerateFiles(va("players/%s/*_i.*", info->modeledit->values[info->modeledit->selectedoption]), q2skin_enumerate, s); + if (key == K_ENTER || key == K_RIGHTARROW) + { + s->match ++; + if (s->match>=s->entries) + s->match=0; + } + else if (key == K_LEFTARROW) + { + s->match --; + if (s->match<=0) + s->match=s->entries-1; + } + else + { + q2skin_destroy(s); + return false; + } + if (s->entries) + Cvar_Set(&skin, s->names[s->match]); + S_LocalSound ("misc/menu2.wav"); + q2skin_destroy(s); + return true; +} +void MSetupQ2_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) +{ + setupmenu_t *info = menu->data; + mpic_t *p; + + + p = Draw_SafeCachePic (va("players/%s_i", skin.string)); + if (!p) + { + q2skinsearch_t *s = Z_Malloc(sizeof(*s)); + COM_EnumerateFiles(va("players/%s/*_i.*", info->modeledit->values[info->modeledit->selectedoption]), q2skin_enumerate, s); + if (s->entries) + Cvar_Set(&skin, s->names[rand()%s->entries]); + q2skin_destroy(s); + + p = Draw_SafeCachePic (va("players/%s_i", skin.string)); + } + if (p) + Draw_TransPic (x-12, y-8, p); +} + void MSetup_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) { extern qbyte translationTable[256]; @@ -209,9 +297,72 @@ void MSetup_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) void M_Menu_Setup_f (void) { + int mgt; setupmenu_t *info; menu_t *menu; + mgt = M_GameType(); + if (mgt == MGT_QUAKE2) //quake2 main menu. + { + if (Draw_SafeCachePic("pics/m_banner_plauer_setup")) + { + char *modeloptions[] = + { + "male", + "female", + NULL + }; + mpic_t *p; + menucustom_t *cu; + m_state = m_complex; + key_dest = key_menu; + + menu = M_CreateMenu(sizeof(setupmenu_t)); + info = menu->data; +// menu->key = MC_Main_Key; + + MC_AddPicture(menu, 0, 4, "pics/m_main_plaque"); + p = Draw_SafeCachePic("pics/m_main_logo"); + if (!p) + return; + MC_AddPicture(menu, 0, 173, "pics/m_main_logo"); + + menu->selecteditem = (menuoption_t*) + (info->nameedit = MC_AddEdit(menu, 64, 40, "Your name", name.string)); + (info->modeledit = MC_AddCvarCombo(menu, 64, 72, "model", &skin, modeloptions, modeloptions)); + info->modeledit->selectedoption = !strncmp(skin.string, "female", 6); + cu = MC_AddCustom(menu, 172-16, 88+16, NULL); + cu->draw = MSetupQ2_TransDraw; + cu->key = MSetupQ2_ChangeSkin; + +/* MC_AddSelectablePicture(mainm, 68, 13, "pics/m_main_game"); + MC_AddSelectablePicture(mainm, 68, 53, "pics/m_main_multiplayer"); + MC_AddSelectablePicture(mainm, 68, 93, "pics/m_main_options"); + MC_AddSelectablePicture(mainm, 68, 133, "pics/m_main_video"); + MC_AddSelectablePicture(mainm, 68, 173, "pics/m_main_quit"); + + b = MC_AddConsoleCommand (mainm, 68, 13, "", "menu_single\n"); + mainm->selecteditem = (menuoption_t *)b; + b->common.width = 12*20; + b->common.height = 20; + b = MC_AddConsoleCommand (mainm, 68, 53, "", "menu_multi\n"); + b->common.width = 12*20; + b->common.height = 20; + b = MC_AddConsoleCommand (mainm, 68, 93, "", "menu_options\n"); + b->common.width = 12*20; + b->common.height = 20; + b = MC_AddConsoleCommand (mainm, 68, 133, "", "menu_video\n"); + b->common.width = 12*20; + b->common.height = 20; + b = MC_AddConsoleCommand (mainm, 68, 173, "", "menu_quit\n"); + b->common.width = 12*20; + b->common.height = 20; +*/ + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 54, 32, NULL, false); + } + return; + } + key_dest = key_menu; m_state = m_complex; diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 41837c941..3e0393cec 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -165,6 +165,7 @@ void M_Audio_StartSound (struct menu_s *menu) vec3_t org; audiomenuinfo_t *info = menu->data; soundcardinfo_t *sc; + vec3_t mat[4]; static float lasttime; @@ -189,10 +190,12 @@ void M_Audio_StartSound (struct menu_s *menu) if (lasttime+0.5 < Sys_DoubleTime()) { + S_GetListenerInfo(mat[0], mat[1], mat[2], mat[3]); + lasttime = Sys_DoubleTime(); - org[0] = listener_origin[0] + 2*(listener_right[0]*(info->testsoundsource->common.posx-320/2) + listener_forward[0]*(info->testsoundsource->common.posy-200/2)); - org[1] = listener_origin[1] + 2*(listener_right[1]*(info->testsoundsource->common.posx-320/2) + listener_forward[1]*(info->testsoundsource->common.posy-200/2)); - org[2] = listener_origin[2] + 2*(listener_right[2]*(info->testsoundsource->common.posx-320/2) + listener_forward[2]*(info->testsoundsource->common.posy-200/2)); + org[0] = mat[0][0] + 2*(mat[1][0]*(info->testsoundsource->common.posx-320/2) + mat[1][0]*(info->testsoundsource->common.posy-200/2)); + org[1] = mat[0][1] + 2*(mat[1][1]*(info->testsoundsource->common.posx-320/2) + mat[1][1]*(info->testsoundsource->common.posy-200/2)); + org[2] = mat[0][2] + 2*(mat[1][2]*(info->testsoundsource->common.posx-320/2) + mat[1][2]*(info->testsoundsource->common.posy-200/2)); S_StartSound(-2, 0, S_PrecacheSound("player/pain3.wav"), org, 1, 4); } } diff --git a/engine/client/m_single.c b/engine/client/m_single.c index d3faa465d..e5bc81cb2 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -223,10 +223,10 @@ void M_Menu_SinglePlayer_f (void) else { #ifdef CLIENTONLY - MC_AddBox (menu, 60, 10*8, 23, 4); - MC_AddWhiteText(menu, 92, 12*8, "QuakeWorld is for", false); MC_AddWhiteText(menu, 92, 13*8, "Internet play only", false); + + MC_AddBox (menu, 60, 10*8, 23, 4); #else MC_AddPicture(menu, 72, 32, "gfx/sp_menu.lmp"); @@ -384,7 +384,7 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key) return false; } -static int DemoAddItem(char *filename, int size, void *parm) +static int DemoAddItem(const char *filename, int size, void *parm) { int extnum; demomenu_t *menu = parm; diff --git a/engine/client/menu.c b/engine/client/menu.c index e1b6f0d4a..69d323a86 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -843,26 +843,31 @@ void M_Menu_Quit_f (void) { int i; + if (1) + { CL_Disconnect (); Sys_Quit (); + } + else + { + key_dest = key_menu; + m_state = m_complex; - key_dest = key_menu; - m_state = m_complex; - - M_RemoveMenu(&quitmenu); - memset(&quitmenu, 0, sizeof(quitmenu)); - M_AddMenuFront(&quitmenu); - quitmenu.exclusive = false; - quitmenu.key = MC_Quit_Key; + M_RemoveMenu(&quitmenu); + memset(&quitmenu, 0, sizeof(quitmenu)); + M_AddMenuFront(&quitmenu); + quitmenu.exclusive = false; + quitmenu.key = MC_Quit_Key; - i = rand()&7; + i = rand()&7; - MC_AddWhiteText(&quitmenu, 64, 84, quitMessage[i*4+0], false); - MC_AddWhiteText(&quitmenu, 64, 92, quitMessage[i*4+1], false); - MC_AddWhiteText(&quitmenu, 64, 100, quitMessage[i*4+2], false); - MC_AddWhiteText(&quitmenu, 64, 108, quitMessage[i*4+3], false); - MC_AddBox (&quitmenu, 56, 76, 24, 4); + MC_AddWhiteText(&quitmenu, 64, 84, quitMessage[i*4+0], false); + MC_AddWhiteText(&quitmenu, 64, 92, quitMessage[i*4+1], false); + MC_AddWhiteText(&quitmenu, 64, 100, quitMessage[i*4+2], false); + MC_AddWhiteText(&quitmenu, 64, 108, quitMessage[i*4+3], false); + MC_AddBox (&quitmenu, 56, 76, 24, 4); + } } //============================================================================= diff --git a/engine/client/merged.h b/engine/client/merged.h index 722efbd8b..b493bbaf2 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -133,6 +133,7 @@ extern void FNC(Mod_NowLoadExternal) (void); extern void FNC(Mod_Think) (void); extern int FNC(Mod_SkinForName) (struct model_s *model, char *name); +extern int FNC(Mod_FrameForName) (struct model_s *model, char *name); #undef FNC @@ -221,6 +222,7 @@ typedef struct { qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, framestate_t *fstate, float *result); int (*Mod_TagNumForName) (struct model_s *model, char *name); int (*Mod_SkinForName) (struct model_s *model, char *name); + int (*Mod_FrameForName) (struct model_s *model, char *name); qboolean (*VID_Init) (rendererstate_t *info, unsigned char *palette); diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 6ad00aa1d..9d618483a 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -37,7 +37,7 @@ typedef int SOCKET; cvar_t slist_cacheinfo = SCVAR("slist_cacheinfo", "0"); //this proves dangerous, memory wise. cvar_t slist_writeserverstxt = SCVAR("slist_writeservers", "0"); -void CL_MasterListParse(int type, qboolean slashpad); +void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad); void CL_QueryServers(void); int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite); @@ -83,27 +83,34 @@ int slist_customkeys; #endif -#define POLLUDPSOCKETS 64 //it's big so we can have lots of messages when behind a firewall. Basically if a firewall only allows replys, and only remembers 3 servers per socket, we need this big cos it can take a while for a packet to find a fast optimised route and we might be waiting for a few secs for a reply the first time around. -SOCKET pollsocketsUDP[POLLUDPSOCKETS]; -int lastpollsockUDP; +#define POLLUDP4SOCKETS 64 //it's big so we can have lots of messages when behind a firewall. Basically if a firewall only allows replys, and only remembers 3 servers per socket, we need this big cos it can take a while for a packet to find a fast optimised route and we might be waiting for a few secs for a reply the first time around. +int lastpollsockUDP4; + +#ifdef IPPROTO_IPV6 +#define POLLUDP6SOCKETS 4 //it's non-zero so we can have lots of messages when behind a firewall. Basically if a firewall only allows replys, and only remembers 3 servers per socket, we need this big cos it can take a while for a packet to find a fast optimised route and we might be waiting for a few secs for a reply the first time around. +int lastpollsockUDP6; +#else +#define POLLUDP6SOCKETS 0 +#endif #ifdef USEIPX -#define POLLIPXSOCKETS 2 //ipx isn't used as much. In fact, we only expect local servers to be using it. I'm not sure why I implemented it anyway. -SOCKET pollsocketsIPX[POLLIPXSOCKETS]; +#define POLLIPXSOCKETS 2 //ipx isn't used as much. In fact, we only expect local servers to be using it. I'm not sure why I implemented it anyway. You might see a q2 server using it. Rarely. int lastpollsockIPX; #else #define POLLIPXSOCKETS 0 #endif +#define FIRSTIPXSOCKET (0) +#define FIRSTUDP4SOCKET (FIRSTIPXSOCKET+POLLIPXSOCKETS) +#define FIRSTUDP6SOCKET (FIRSTUDP4SOCKET+POLLUDP4SOCKETS) +#define POLLTOTALSOCKETS (FIRSTUDP6SOCKET+POLLUDP6SOCKETS) +SOCKET pollsocketsList[POLLTOTALSOCKETS]; + void Master_SetupSockets(void) { int i; - for (i = 0; i < POLLUDPSOCKETS; i++) - pollsocketsUDP[i] = INVALID_SOCKET; -#ifdef USEIPX - for (i = 0; i < POLLIPXSOCKETS; i++) - pollsocketsIPX[i] = INVALID_SOCKET; -#endif + for (i = 0; i < POLLTOTALSOCKETS; i++) + pollsocketsList[i] = INVALID_SOCKET; } void Master_HideServer(serverinfo_t *server) @@ -587,6 +594,8 @@ void Master_AddMaster (char *address, int type, char *description) adr.type = NA_BROADCAST_IP; if (adr.type == NA_IPX) adr.type = NA_BROADCAST_IPX; + if (adr.type == NA_IPV6) + adr.type = NA_BROADCAST_IP6; } for (mast = master; mast; mast = mast->next) @@ -785,24 +794,38 @@ void NET_SendPollPacket(int len, void *data, netadr_t to) lastpollsockIPX++; if (lastpollsockIPX>=POLLIPXSOCKETS) lastpollsockIPX=0; - if (pollsocketsIPX[lastpollsockIPX]==INVALID_SOCKET) - pollsocketsIPX[lastpollsockIPX] = IPX_OpenSocket(PORT_ANY, true); - if (pollsocketsIPX[lastpollsockIPX]==INVALID_SOCKET) + if (pollsocketsList[FIRSTIPXSOCKET+lastpollsockIPX]==INVALID_SOCKET) + pollsocketsList[FIRSTIPXSOCKET+lastpollsockIPX] = IPX_OpenSocket(PORT_ANY, true); + if (pollsocketsList[FIRSTIPXSOCKET+lastpollsockIPX]==INVALID_SOCKET) return; //bother - ret = sendto (pollsocketsIPX[lastpollsockIPX], data, len, 0, (struct sockaddr *)&addr, sizeof(addr) ); + ret = sendto (pollsocketsList[FIRSTIPXSOCKET+lastpollsockIPX], data, len, 0, (struct sockaddr *)&addr, sizeof(addr) ); + } + else +#endif +#ifdef IPPROTO_IPV6 + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) + { + lastpollsockUDP6++; + if (lastpollsockUDP6>=POLLUDP6SOCKETS) + lastpollsockUDP6=0; + if (pollsocketsList[FIRSTUDP6SOCKET+lastpollsockUDP6]==INVALID_SOCKET) + pollsocketsList[FIRSTUDP6SOCKET+lastpollsockUDP6] = UDP6_OpenSocket(PORT_ANY, true); + if (pollsocketsList[FIRSTUDP6SOCKET+lastpollsockUDP6]==INVALID_SOCKET) + return; //bother + ret = sendto (pollsocketsList[FIRSTUDP6SOCKET+lastpollsockUDP6], data, len, 0, (struct sockaddr *)&addr, sizeof(addr) ); } else #endif if (((struct sockaddr*)&addr)->sa_family == AF_INET) { - lastpollsockUDP++; - if (lastpollsockUDP>=POLLUDPSOCKETS) - lastpollsockUDP=0; - if (pollsocketsUDP[lastpollsockUDP]==INVALID_SOCKET) - pollsocketsUDP[lastpollsockUDP] = UDP_OpenSocket(PORT_ANY, true); - if (pollsocketsUDP[lastpollsockUDP]==INVALID_SOCKET) + lastpollsockUDP4++; + if (lastpollsockUDP4>=POLLUDP4SOCKETS) + lastpollsockUDP4=0; + if (pollsocketsList[FIRSTUDP4SOCKET+lastpollsockUDP4]==INVALID_SOCKET) + pollsocketsList[FIRSTUDP4SOCKET+lastpollsockUDP4] = UDP_OpenSocket(PORT_ANY, true); + if (pollsocketsList[FIRSTUDP4SOCKET+lastpollsockUDP4]==INVALID_SOCKET) return; //bother - ret = sendto (pollsocketsUDP[lastpollsockUDP], data, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in) ); + ret = sendto (pollsocketsList[FIRSTUDP4SOCKET+lastpollsockUDP4], data, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in) ); } else return; @@ -831,18 +854,13 @@ int NET_CheckPollSockets(void) SOCKET usesocket; char adr[MAX_ADR_SIZE]; - for (sock = 0; sock < POLLUDPSOCKETS+POLLIPXSOCKETS; sock++) + for (sock = 0; sock < POLLTOTALSOCKETS; sock++) { int ret; struct sockaddr_qstorage from; int fromlen; -#ifdef USEIPX - if (sock >= POLLUDPSOCKETS) - usesocket = pollsocketsIPX[sock-POLLUDPSOCKETS]; - else -#endif - usesocket = pollsocketsUDP[sock]; + usesocket = pollsocketsList[sock]; if (usesocket == INVALID_SOCKET) continue; @@ -900,10 +918,18 @@ int NET_CheckPollSockets(void) CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEQ2, false); continue; } - if (!strncmp(s, "servers", 6)) //parse a bit more... +#ifdef IPPROTO_IPV6 + if (!strncmp(s, "server6", 7)) //parse a bit more... { msg_readcount = c+7; - CL_MasterListParse(SS_QUAKE2, false); + CL_MasterListParse(NA_IPV6, SS_QUAKE2, false); + continue; + } +#endif + if (!strncmp(s, "servers", 7)) //parse a bit more... + { + msg_readcount = c+7; + CL_MasterListParse(NA_IP, SS_QUAKE2, false); continue; } #endif @@ -915,10 +941,18 @@ int NET_CheckPollSockets(void) } #endif +#ifdef IPPROTO_IPV6 + if (!strncmp(s, "getserversResponse6\\", 20)) //parse a bit more... + { + msg_readcount = c+19-1; + CL_MasterListParse(NA_IPV6, SS_DARKPLACES, true); + continue; + } +#endif if (!strncmp(s, "getserversResponse\\", 19)) //parse a bit more... { msg_readcount = c+18-1; - CL_MasterListParse(SS_DARKPLACES, true); + CL_MasterListParse(NA_IP, SS_DARKPLACES, true); continue; } if (!strcmp(s, "infoResponse")) //parse a bit more... @@ -926,6 +960,16 @@ int NET_CheckPollSockets(void) CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEDP, false); continue; } + +#ifdef IPPROTO_IPV6 + if (!strncmp(s, "qw_slist6\\", 10)) //parse a bit more... + { + msg_readcount = c+9-1; + CL_MasterListParse(NA_IPV6, SS_GENERICQUAKEWORLD, false); + continue; + } +#endif + msg_readcount = c; c = MSG_ReadByte (); @@ -938,7 +982,7 @@ int NET_CheckPollSockets(void) if (c == M2C_MASTER_REPLY) //qw master reply. { - CL_MasterListParse(false, false); + CL_MasterListParse(NA_IP, SS_GENERICQUAKEWORLD, false); continue; } } @@ -976,7 +1020,7 @@ int NET_CheckPollSockets(void) // Q_strcat(name, name); } - CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i", name, map, maxusers), MT_SINGLENQ, false); + CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MT_SINGLENQ, false); } #endif continue; @@ -1196,10 +1240,10 @@ void MasterInfo_WriteServers(void) char *typename; master_t *mast; serverinfo_t *server; - FILE *mf, *qws; + vfsfile_t *mf, *qws; char adr[MAX_ADR_SIZE]; - mf = fopen("masters.txt", "wt"); + mf = FS_OpenVFS("masters.txt", "wt", FS_ROOT); if (!mf) { Con_Printf("Couldn't write masters.txt"); @@ -1259,40 +1303,40 @@ void MasterInfo_WriteServers(void) typename = "writeerror"; } if (mast->address) - fprintf(mf, "%s\t%s\t%s\n", mast->address , typename, mast->name); + VFS_PUTS(mf, va("%s\t%s\t%s\n", mast->address , typename, mast->name)); else - fprintf(mf, "%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), mast->adr), typename, mast->name); + VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), mast->adr), typename, mast->name)); } if (slist_writeserverstxt.value) - qws = fopen("servers.txt", "wt"); + qws = FS_OpenVFS("servers.txt", "wt", FS_ROOT); else qws = NULL; if (qws) - fprintf(mf, "\n%s\t%s\t%s\n\n", "file servers.txt", "favorite:qw", "personal server list"); + VFS_PUTS(mf, va("\n%s\t%s\t%s\n\n", "file servers.txt", "favorite:qw", "personal server list")); for (server = firstserver; server; server = server->next) { if (server->special & SS_FAVORITE) { if (server->special & SS_QUAKE3) - fprintf(mf, "%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:q3", server->name); + VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:q3", server->name)); else if (server->special & SS_QUAKE2) - fprintf(mf, "%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:q2", server->name); + VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:q2", server->name)); else if (server->special & SS_NETQUAKE) - fprintf(mf, "%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:nq", server->name); + VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:nq", server->name)); else if (qws) //servers.txt doesn't support the extra info. - fprintf(qws, "%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), server->name); + VFS_PUTS(qws, va("%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), server->name)); else //read only? damn them! - fprintf(mf, "%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:qw", server->name); + VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), server->adr), "favorite:qw", server->name)); } } if (qws) - fclose(qws); + VFS_CLOSE(qws); - fclose(mf); + VFS_CLOSE(mf); } //poll master servers for server lists. @@ -1758,19 +1802,36 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) } //rewrite to scan for existing server instead of wiping all. -void CL_MasterListParse(int type, qboolean slashpad) +void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) { serverinfo_t *info; serverinfo_t *last, *old; + int adrlen; int p1, p2; char adr[MAX_ADR_SIZE]; + int i; + + switch(adrtype) + { + case NA_IP: + adrlen = 4; + break; + case NA_IPV6: + adrlen = 16; + break; + case NA_IPX: + adrlen = 10; + break; + default: + return; + } MSG_ReadByte (); last = firstserver; - while(msg_readcount+6 < net_message.cursize) + while(msg_readcount+adrlen+2 < net_message.cursize) { if (slashpad) { @@ -1779,11 +1840,17 @@ void CL_MasterListParse(int type, qboolean slashpad) } info = Z_Malloc(sizeof(serverinfo_t)); - info->adr.type = NA_IP; - info->adr.address.ip[0] = MSG_ReadByte(); - info->adr.address.ip[1] = MSG_ReadByte(); - info->adr.address.ip[2] = MSG_ReadByte(); - info->adr.address.ip[3] = MSG_ReadByte(); + info->adr.type = adrtype; + switch(adrtype) + { + case NA_IP: + case NA_IPV6: + case NA_IPX: + //generic fixed-length addresses + for (i = 0; i < adrlen; i++) + ((qbyte *)&info->adr.address)[i] = MSG_ReadByte(); + break; + } p1 = MSG_ReadByte(); p2 = MSG_ReadByte(); diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index 60b34ad71..c63d02122 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -186,6 +186,19 @@ static void PClassic_ClearParticles (void) particles[r_numparticles - 1].next = NULL; } +#define USEARRAYS + +#define BUFFERVERTS 2048*3 +vec3_t classicverts[BUFFERVERTS]; +union c +{ + byte_vec4_t b; + unsigned int i; +} classiccolours[BUFFERVERTS]; +vec2_t classictexcoords[BUFFERVERTS]; +int classicnumverts; +int setuptexcoords; + //draws all the active particles. static void PClassic_DrawParticles(void) { @@ -198,6 +211,8 @@ static void PClassic_DrawParticles(void) unsigned char *at, theAlpha; vec3_t up, right; float dist, scale, r_partscale=0; + + union c usecolours; #endif if (!active_particles) @@ -218,10 +233,32 @@ static void PClassic_DrawParticles(void) if (!gl_solidparticles.value) qglDepthMask (GL_FALSE); qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + +#ifdef USEARRAYS + if (!setuptexcoords) + { + setuptexcoords = true; + for (i = 0; i < BUFFERVERTS; i += 3) + { + classictexcoords[i+1][0] = 1; + classictexcoords[i+2][1] = 1; + } + } + qglTexCoordPointer(2, GL_FLOAT, 0, classictexcoords); + qglVertexPointer(3, GL_FLOAT, 0, classicverts); + qglColorPointer(4, GL_UNSIGNED_BYTE, 0, classiccolours); + + qglEnableClientState(GL_TEXTURE_COORD_ARRAY); + qglEnableClientState(GL_COLOR_ARRAY); + qglEnableClientState(GL_VERTEX_ARRAY); +#else qglBegin (GL_TRIANGLES); +#endif VectorScale (vup, 1.5, up); VectorScale (vright, 1.5, right); + + classicnumverts = 0; break; #endif #ifdef SWQUAKE @@ -277,10 +314,36 @@ static void PClassic_DrawParticles(void) { #ifdef RGLQUAKE case QR_OPENGL: +#ifdef USEARRAYS + if (classicnumverts >= BUFFERVERTS-3) + { + qglDrawArrays(GL_TRIANGLES, 0, classicnumverts); + classicnumverts = 0; + } +#endif + // hack a scale up to keep particles from disapearing dist = (p->org[0] - r_origin[0]) * vpn[0] + (p->org[1] - r_origin[1]) * vpn[1] + (p->org[2] - r_origin[2]) * vpn[2]; scale = 1 + dist * r_partscale; +#ifdef USEARRAYS + usecolours.i = d_8to24rgbtable[(int)p->color]; + if (p->type == pt_fire) + usecolours.b[3] = 255 * (6 - p->ramp) / 6; + else + usecolours.b[3] = 255; + + classiccolours[classicnumverts].i = usecolours.i; + VectorCopy(p->org, classicverts[classicnumverts]); + classicnumverts++; + classiccolours[classicnumverts].i = usecolours.i; + VectorMA(p->org, scale, up, classicverts[classicnumverts]); + classicnumverts++; + classiccolours[classicnumverts].i = usecolours.i; + VectorMA(p->org, scale, right, classicverts[classicnumverts]); + classicnumverts++; +#else + at = (qbyte *) &d_8to24rgbtable[(int)p->color]; if (p->type == pt_fire) theAlpha = 255 * (6 - p->ramp) / 6; @@ -290,6 +353,7 @@ static void PClassic_DrawParticles(void) qglTexCoord2f (0, 0); qglVertex3fv (p->org); qglTexCoord2f (1, 0); qglVertex3f (p->org[0] + up[0] * scale, p->org[1] + up[1] * scale, p->org[2] + up[2] * scale); qglTexCoord2f (0, 1); qglVertex3f (p->org[0] + right[0] * scale, p->org[1] + right[1] * scale, p->org[2] + right[2] * scale); +#endif break; #endif #ifdef SWQUAKE @@ -356,7 +420,15 @@ static void PClassic_DrawParticles(void) { #ifdef RGLQUAKE case QR_OPENGL: +#ifdef USEARRAYS + if (classicnumverts) + { + qglDrawArrays(GL_TRIANGLES, 0, classicnumverts); + classicnumverts = 0; + } +#else qglEnd (); +#endif qglDisable (GL_BLEND); qglDepthMask (GL_TRUE); qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 62a98a4d3..8010fecb0 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -53,6 +53,7 @@ static int num_csqc_edicts; static int csqc_fakereadbyte; static int csqc_lplayernum; +static qboolean csqc_isdarkplaces; #define CSQCPROGSGROUP "CSQC progs control" cvar_t pr_csmaxedicts = SCVAR("pr_csmaxedicts", "3072"); @@ -140,8 +141,6 @@ typedef enum \ globalfunction(ent_update, "CSQC_Ent_Update"); \ globalfunction(ent_remove, "CSQC_Ent_Remove"); \ - globalfunction(delta_update, "CSQC_Delta_Update");/*EXT_CSQC_1*/ \ - globalfunction(delta_remove, "CSQC_Delta_Remove");/*EXT_CSQC_1*/ \ \ globalfunction(event_sound, "CSQC_Event_Sound"); \ globalfunction(serversound, "CSQC_ServerSound");/*obsolete, use event_sound*/ \ @@ -698,8 +697,11 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t out->g[FST_BASE].endbone = in->v->basebone; if (out->g[FST_BASE].endbone) { //small optimisation. + out->g[FST_BASE].endbone -= 1; + out->g[FST_BASE].frame[0] = in->v->baseframe; out->g[FST_BASE].frame[1] = in->v->baseframe2; + out->g[FST_BASE].lerpfrac = in->v->baselerpfrac; if (rflags & CSQCRF_FRAMETIMESARESTARTTIMES) { out->g[FST_BASE].frametime[0] = *csqcg.svtime - in->v->baseframe1time; @@ -710,7 +712,6 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t out->g[FST_BASE].frametime[0] = in->v->baseframe1time; out->g[FST_BASE].frametime[1] = in->v->baseframe2time; } - out->g[FST_BASE].lerpfrac = in->v->baselerpfrac; } //and the normal frames. @@ -928,10 +929,15 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) AngleVectors(out->angles, out->axis[0], out->axis[1], out->axis[2]); VectorInverse(out->axis[1]); - if (!in->v->scale) + if (!in->v->scale || in->v->scale == 1.0f) out->scale = 1; else + { + VectorScale(out->axis[0], in->v->scale, out->axis[0]); + VectorScale(out->axis[1], in->v->scale, out->axis[1]); + VectorScale(out->axis[2], in->v->scale, out->axis[2]); out->scale = in->v->scale; + } } if (in->v->colormap > 0 && in->v->colormap <= MAX_CLIENTS) @@ -1032,6 +1038,16 @@ static void PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_s *pr_glob int e; int oldself = *csqcg.self; + + if (cl.worldmodel) + { + if (mask & MASK_DELTA) + { + CL_LinkPlayers (); + CL_LinkPacketEntities (); + } + } + for (e=1; e < *prinst->parms->sv_num_edicts; e++) { ent = (void*)EDICT_NUM(prinst, e); @@ -1061,13 +1077,8 @@ static void PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_s *pr_glob { CL_LinkViewModel (); } - if (mask & MASK_DELTA) - { - CL_LinkPlayers (); - CL_LinkPacketEntities (); - CL_LinkProjectiles (); - CL_UpdateTEnts (); - } + CL_LinkProjectiles (); + CL_UpdateTEnts (); } } @@ -1990,11 +2001,22 @@ static void PF_cs_pointparticles (progfuncs_t *prinst, struct globalvars_s *pr_g static void PF_cs_trailparticles (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - int efnum = G_FLOAT(OFS_PARM0)-1; - csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1); + int efnum; + csqcedict_t *ent; float *start = G_VECTOR(OFS_PARM2); float *end = G_VECTOR(OFS_PARM3); + if (csqc_isdarkplaces) + { + efnum = G_FLOAT(OFS_PARM1)-1; + ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); + } + else + { + efnum = G_FLOAT(OFS_PARM0)-1; + ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1); + } + if (!ent->entnum) //world trails are non-state-based. pe->ParticleTrail(start, end, efnum, NULL); else @@ -3071,7 +3093,7 @@ static void PF_cs_addprogs (progfuncs_t *prinst, struct globalvars_s *pr_globals static void PF_cs_OpenPortal (progfuncs_t *prinst, struct globalvars_s *pr_globals) { #ifdef Q2BSPS - if (sv.worldmodel->fromgame == fg_quake2) + if (cl.worldmodel->fromgame == fg_quake2) CMQ2_SetAreaPortalState(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); #endif } @@ -3409,6 +3431,17 @@ static void PF_rotatevectorsbymatrix (progfuncs_t *prinst, struct globalvars_s * VectorNegate(res[1], csqcg.right); VectorCopy(res[2], csqcg.up); } +static void PF_frameforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int modelindex = G_FLOAT(OFS_PARM0); + char *str = PF_VarString(prinst, 1, pr_globals); + model_t *mod = CSQC_GetModelForIndex(modelindex); + + if (mod && Mod_FrameForName) + G_FLOAT(OFS_RETURN) = Mod_FrameForName(mod, str); + else + G_FLOAT(OFS_RETURN) = -1; +} static void PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int modelindex = G_FLOAT(OFS_PARM0); @@ -3416,7 +3449,7 @@ static void PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals model_t *mod = CSQC_GetModelForIndex(modelindex); - if (Mod_SkinForName) + if (mod && Mod_SkinForName) G_FLOAT(OFS_RETURN) = Mod_SkinForName(mod, str); else G_FLOAT(OFS_RETURN) = -1; @@ -4066,25 +4099,356 @@ static void PF_cs_setlistener (progfuncs_t *prinst, struct globalvars_s *pr_glob float *right = G_VECTOR(OFS_PARM2); float *up = G_VECTOR(OFS_PARM3); csqc_usinglistener = true; - S_Update(origin, forward, right, up); + S_UpdateListener(origin, forward, right, up, false); } -typedef struct oldcsqcpack_s -{ - unsigned int numents; - unsigned int maxents; - unsigned short *entnum; - csqcedict_t **entptr; -} oldcsqcpack_t; -static oldcsqcpack_t loadedcsqcpack[2]; -static int loadedcsqcpacknum; -static csqcedict_t *deltaedplayerents[MAX_CLIENTS]; - #define RSES_NOLERP 1 #define RSES_NOROTATE 2 #define RSES_NOTRAILS 4 #define RSES_NOLIGHTS 8 +void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src, csqcedict_t *ent) +{ + model_t *model; + lerpents_t *le; + + le = &cl.lerpents[src->number]; + + //frames needs special handling + ent->v->frame = src->frame; + ent->v->frame2 = le->frame; + if (le->framechange == le->oldframechange) + ent->v->lerpfrac = 0; + else + { + ent->v->lerpfrac = 1-(lerptime - le->framechange) / (le->framechange - le->oldframechange); + if (ent->v->lerpfrac > 1) + ent->v->lerpfrac = 1; + else if (ent->v->lerpfrac < 0) + { + ent->v->lerpfrac = 0; + } + } + + model = cl.model_precache[src->modelindex]; + if (!(flags & RSES_NOTRAILS)) + { + //use entnum as a test to see if its new (if the old origin isn't usable) + if (ent->v->entnum && model->particletrail >= 0) + { + if (pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, &(le->trailstate))) + pe->ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); + } + } + + ent->v->entnum = src->number; + ent->v->modelindex = src->modelindex; +// ent->v->bitmask = src->bitmask; + ent->v->flags = src->flags; +// ent->v->effects = src->effects; + ent->v->origin[0] = src->origin[0]; + ent->v->origin[1] = src->origin[1]; + ent->v->origin[2] = src->origin[2]; + ent->v->angles[0] = src->angles[0]; + ent->v->angles[1] = src->angles[1]; + ent->v->angles[2] = src->angles[2]; + +//we ignore the q2 state fields + + ent->v->colormap = src->colormap; + ent->v->skin = src->skinnum; +// ent->v->glowsize = src->glowsize; +// ent->v->glowcolor = src->glowcolour; + ent->v->scale = src->scale/16.0f; + ent->v->fatness = src->fatness/16.0f; +// ent->v->hexen2flags = src->hexen2flags; +// ent->v->abslight = src->abslight; +// ent->v->dpflags = src->dpflags; +// ent->v->colormod[0] = (src->colormod[0]/255.0f)*8; +// ent->v->colormod[1] = (src->colormod[1]/255.0f)*8; +// ent->v->colormod[2] = (src->colormod[2]/255.0f)*8; + ent->v->alpha = src->trans/255.0f; +// ent->v->lightstyle = src->lightstyle; +// ent->v->lightpflags = src->lightpflags; +// ent->v->solid = src->solid; +// ent->v->light[0] = src->light[0]; +// ent->v->light[1] = src->light[1]; +// ent->v->light[2] = src->light[2]; +// ent->v->light[3] = src->light[3]; +// ent->v->tagentity = src->tagentity; +// ent->v->tagindex = src->tagindex; + + if (model) + { + if (!(flags & RSES_NOROTATE) && (model->flags & EF_ROTATE)) + { + ent->v->angles[0] = 0; + ent->v->angles[1] = 100*lerptime; + ent->v->angles[2] = 0; + } + } +} +void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent) +{ + ent->v->entnum = pnum+1; + + if (cl.spectator && !Cam_DrawPlayer(0, pnum)) + { + ent->v->modelindex = 0; + } + else + ent->v->modelindex = srcp->modelindex; + ent->v->skin = srcp->skinnum; + + ent->v->frame1time = cl.time - cl.lerpplayers[pnum].framechange; + ent->v->frame2time = cl.time - cl.lerpplayers[pnum].oldframechange; + + if (ent->v->frame != cl.lerpplayers[pnum].frame) + { + ent->v->frame2 = ent->v->frame; + ent->v->frame = cl.lerpplayers[pnum].frame; + } + + ent->v->lerpfrac = 1-(realtime - cl.lerpplayers[pnum].framechange)*10; + if (ent->v->lerpfrac > 1) + ent->v->lerpfrac = 1; + else if (ent->v->lerpfrac < 0) + { + ent->v->lerpfrac = 0; + } + VectorCopy(srcp->origin, ent->v->origin); + VectorCopy(srcp->velocity, ent->v->velocity); + VectorCopy(srcp->viewangles, ent->v->angles); + ent->v->angles[0] *= -0.333; + ent->v->colormap = pnum+1; + ent->v->scale = srcp->scale/16.0f; + //ent->v->fatness = srcp->fatness; + ent->v->alpha = srcp->alpha/255.0f; + +// ent->v->colormod[0] = (srcp->colormod[0]/255.0f)*8; +// ent->v->colormod[1] = (srcp->colormod[1]/255.0f)*8; +// ent->v->colormod[2] = (srcp->colormod[2]/255.0f)*8; +// ent->v->effects = srcp->effects; +} + +unsigned int deltaflags[MAX_MODELS]; +func_t deltafunction[MAX_MODELS]; + +typedef struct +{ + unsigned int readpos; //pos + unsigned int numents; //present + unsigned int maxents; //buffer size + struct + { + unsigned short n; //don't rely on the ent->v->entnum + csqcedict_t *e; //the csqc ent + } *e; +} csqcdelta_pack_t; +static csqcdelta_pack_t csqcdelta_pack_new; +static csqcdelta_pack_t csqcdelta_pack_old; +float csqcdelta_time; + +static csqcedict_t *csqcdelta_playerents[MAX_CLIENTS]; + + +qboolean CLCSQC_DeltaPlayer(int playernum, player_state_t *state) +{ + func_t func; + + if (!state || !state->modelindex) + { + if (csqcdelta_playerents[playernum]) + { + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)csqcdelta_playerents[playernum]); + PR_ExecuteProgram(csqcprogs, csqcg.ent_remove); + csqcdelta_playerents[playernum] = NULL; + } + return false; + } + + func = deltafunction[state->modelindex]; + if (func) + { + void *pr_globals; + csqcedict_t *ent; + + ent = csqcdelta_playerents[playernum]; + if (!ent) + ent = (csqcedict_t *)ED_Alloc(csqcprogs); + + CSQC_PlayerStateToCSQC(playernum, state, ent); + ent->v->drawmask = MASK_DELTA; + + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent); + pr_globals = PR_globals(csqcprogs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = !csqcdelta_playerents[playernum]; + PR_ExecuteProgram(csqcprogs, func); + + csqcdelta_playerents[playernum] = ent; + + return true; + } + else if (csqcdelta_playerents[playernum]) + { + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)csqcdelta_playerents[playernum]); + PR_ExecuteProgram(csqcprogs, csqcg.ent_remove); + csqcdelta_playerents[playernum] = NULL; + } + return false; +} + +void CLCSQC_DeltaStart(float time) +{ + csqcdelta_pack_t tmp; + csqcdelta_time = time; + + tmp = csqcdelta_pack_new; + csqcdelta_pack_new = csqcdelta_pack_old; + csqcdelta_pack_old = tmp; + + csqcdelta_pack_new.numents = 0; + + csqcdelta_pack_new.readpos = 0; + csqcdelta_pack_old.readpos = 0; +} +qboolean CLCSQC_DeltaUpdate(entity_state_t *src) +{ + //FTE ensures that this function is called with increasing ent numbers each time + func_t func; + func = deltafunction[src->modelindex]; + if (func) + { + void *pr_globals; + csqcedict_t *ent, *oldent; + + + + + if (csqcdelta_pack_old.readpos == csqcdelta_pack_old.numents) + { //reached the end of the old frame's ents + oldent = NULL; + } + else + { + while (csqcdelta_pack_old.readpos < csqcdelta_pack_old.numents && csqcdelta_pack_old.e[csqcdelta_pack_old.readpos].n < src->number) + { + //this entity is stale, remove it. + oldent = csqcdelta_pack_old.e[csqcdelta_pack_old.readpos].e; + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)oldent); + PR_ExecuteProgram(csqcprogs, csqcg.ent_remove); + csqcdelta_pack_old.readpos++; + } + + if (src->number < csqcdelta_pack_old.e[csqcdelta_pack_old.readpos].n) + oldent = NULL; + else + { + oldent = csqcdelta_pack_old.e[csqcdelta_pack_old.readpos].e; + csqcdelta_pack_old.readpos++; + } + } + + if (src->number < maxcsqcentities && csqcent[src->number]) + { + //in the csqc list (don't permit in the delta list too) + if (oldent) + { + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)oldent); + PR_ExecuteProgram(csqcprogs, csqcg.ent_remove); + } + return false; + } + + + + + if (oldent) + ent = oldent; + else + ent = (csqcedict_t *)ED_Alloc(csqcprogs); + + CSQC_EntStateToCSQC(deltaflags[src->modelindex], csqcdelta_time, src, ent); + ent->v->drawmask = MASK_DELTA; + + + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent); + pr_globals = PR_globals(csqcprogs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = !oldent; + PR_ExecuteProgram(csqcprogs, func); + + + if (csqcdelta_pack_new.maxents <= csqcdelta_pack_new.numents) + { + csqcdelta_pack_new.maxents = csqcdelta_pack_new.numents + 64; + csqcdelta_pack_new.e = BZ_Realloc(csqcdelta_pack_new.e, sizeof(*csqcdelta_pack_new.e)*csqcdelta_pack_new.maxents); + } + csqcdelta_pack_new.e[csqcdelta_pack_new.numents].e = ent; + csqcdelta_pack_new.e[csqcdelta_pack_new.numents].n = src->number; + csqcdelta_pack_new.numents++; + + return G_FLOAT(OFS_RETURN); + } + return false; +} + +void CLCSQC_DeltaEnd(void) +{ + //remove any unreferenced ents stuck on the end + while (csqcdelta_pack_old.readpos < csqcdelta_pack_old.numents) + { + *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)csqcdelta_pack_old.e[csqcdelta_pack_old.readpos].e); + PR_ExecuteProgram(csqcprogs, csqcg.ent_remove); + csqcdelta_pack_old.readpos++; + } +} + +void PF_DeltaListen(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + char *mname = PR_GetStringOfs(prinst, OFS_PARM0); + func_t func = G_INT(OFS_PARM1); + unsigned int flags = G_FLOAT(OFS_PARM2); + + if (PR_GetFuncArgCount(prinst, func) < 0) + { + Con_Printf("PF_DeltaListen: Bad function index\n"); + return; + } + + if (!strcmp(mname, "*")) + { + //yes, even things that are not allocated yet + for (i = 0; i < MAX_MODELS; i++) + { + deltafunction[i] = func; + deltaflags[i] = flags; + } + } + else + { + for (i = 1; i < MAX_MODELS; i++) + { + if (!*cl.model_name[i]) + break; + if (!strcmp(cl.model_name[i], mname)) + { + deltafunction[i] = func; + deltaflags[i] = flags; + break; + } + } + } +} + + + +#if 1 +void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} +#else + packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp); void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -4127,45 +4491,7 @@ void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globa G_FLOAT(OFS_PARM0) = false; } - ent->v->entnum = i+1; - - if (cl.spectator && !Cam_DrawPlayer(0, i)) - { - ent->v->modelindex = 0; - } - else - ent->v->modelindex = srcp->modelindex; - ent->v->skin = srcp->skinnum; - - ent->v->frame1time = cl.time - cl.lerpplayers[i].framechange; - ent->v->frame2time = cl.time - cl.lerpplayers[i].oldframechange; - - if (ent->v->frame != cl.lerpplayers[i].frame) - { - ent->v->frame2 = ent->v->frame; - ent->v->frame = cl.lerpplayers[i].frame; - } - - ent->v->lerpfrac = 1-(cl.time - cl.lerpplayers[i].framechange)*10; - if (ent->v->lerpfrac > 1) - ent->v->lerpfrac = 1; - else if (ent->v->lerpfrac < 0) - { - ent->v->lerpfrac = 0; - } - VectorCopy(srcp->origin, ent->v->origin); - VectorCopy(srcp->velocity, ent->v->velocity); - VectorCopy(srcp->viewangles, ent->v->angles); - ent->v->angles[0] *= -0.333; - ent->v->colormap = i+1; - ent->v->scale = srcp->scale/16.0f; - //ent->v->fatness = srcp->fatness; - ent->v->alpha = srcp->alpha/255.0f; - -// ent->v->colormod[0] = (srcp->colormod[0]/255.0f)*8; -// ent->v->colormod[1] = (srcp->colormod[1]/255.0f)*8; -// ent->v->colormod[2] = (srcp->colormod[2]/255.0f)*8; -// ent->v->effects = srcp->effects; + CSQC_PlayerStateToCSQC(i, srcp, ent); if (csqcg.delta_update) { @@ -4240,81 +4566,8 @@ void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globa else ent = (csqcedict_t *)ED_Alloc(prinst); - le = &cl.lerpents[src->number]; - - //frames needs special handling - ent->v->frame = src->frame; - ent->v->frame2 = le->frame; - if (le->framechange == le->oldframechange) - ent->v->lerpfrac = 0; - else - { - ent->v->lerpfrac = 1-(servertime - le->framechange) / (le->framechange - le->oldframechange); - if (ent->v->lerpfrac > 1) - ent->v->lerpfrac = 1; - else if (ent->v->lerpfrac < 0) - { - ent->v->lerpfrac = 0; - } - } - - model = cl.model_precache[src->modelindex]; - if (!(flags & RSES_NOTRAILS)) - { - if (oldent && model->particletrail >= 0) - { - if (pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, &(le->trailstate))) - pe->ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); - } - } - - ent->v->entnum = src->number; - ent->v->modelindex = src->modelindex; -// ent->v->bitmask = src->bitmask; - ent->v->flags = src->flags; -// ent->v->effects = src->effects; - ent->v->origin[0] = src->origin[0]; - ent->v->origin[1] = src->origin[1]; - ent->v->origin[2] = src->origin[2]; - ent->v->angles[0] = src->angles[0]; - ent->v->angles[1] = src->angles[1]; - ent->v->angles[2] = src->angles[2]; - - //we ignore the q2 state fields - - ent->v->colormap = src->colormap; - ent->v->skin = src->skinnum; -// ent->v->glowsize = src->glowsize; -// ent->v->glowcolor = src->glowcolour; - ent->v->scale = src->scale/16.0f; - ent->v->fatness = src->fatness/16.0f; -// ent->v->hexen2flags = src->hexen2flags; -// ent->v->abslight = src->abslight; -// ent->v->dpflags = src->dpflags; -// ent->v->colormod[0] = (src->colormod[0]/255.0f)*8; -// ent->v->colormod[1] = (src->colormod[1]/255.0f)*8; -// ent->v->colormod[2] = (src->colormod[2]/255.0f)*8; - ent->v->alpha = src->trans/255.0f; -// ent->v->lightstyle = src->lightstyle; -// ent->v->lightpflags = src->lightpflags; -// ent->v->solid = src->solid; -// ent->v->light[0] = src->light[0]; -// ent->v->light[1] = src->light[1]; -// ent->v->light[2] = src->light[2]; -// ent->v->light[3] = src->light[3]; -// ent->v->tagentity = src->tagentity; -// ent->v->tagindex = src->tagindex; - - if (model) - { - if (!(flags & RSES_NOROTATE) && (model->flags & EF_ROTATE)) - { - ent->v->angles[0] = 0; - ent->v->angles[1] = 100*servertime; - ent->v->angles[2] = 0; - } - } - + CSQC_EntStateToCSQC(flags, servertime, src, ent); + if (csqcg.delta_update) { *csqcg.self = EDICT_TO_PROG(prinst, (void*)ent); @@ -4345,6 +4598,7 @@ void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globa newlist->numents = newidx; } +#endif #define PF_FixTen PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme @@ -4560,6 +4814,7 @@ static struct { {"skel_mul_bones", PF_skel_mul_bones, 272},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) {"skel_copybones", PF_skel_copybones, 273},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS) {"skel_delete", PF_skel_delete, 274},//void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS) + {"frameforname", PF_frameforname, 275}, // #275 //300 {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) @@ -4659,9 +4914,11 @@ static struct { {"readangle", PF_ReadAngle, 365}, // #365 float() readangle (EXT_CSQC) {"readstring", PF_ReadString, 366}, // #366 string() readstring (EXT_CSQC) {"readfloat", PF_ReadFloat, 367}, // #367 string() readfloat (EXT_CSQC) - {"readentitynum", PF_ReadEntityNum, 368}, // #368 float() readentitynum (EXT_CSQC) + {"readserverentitystate", PF_ReadServerEntityState, 369}, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1) +// {"readsingleentitystate", PF_ReadSingleEntityState, 370}, + {"deltalisten", PF_DeltaListen, 371}, // #371 float(string modelname, float flags) deltalisten (EXT_CSQC_1) //400 {"copyentity", PF_cs_copyentity, 400}, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) @@ -4901,6 +5158,8 @@ void CSQC_Shutdown(void) csqcprogs = NULL; in_sensitivityscale = 1; + + csqc_usinglistener = false; } //when the qclib needs a file, it calls out to this function. @@ -5019,6 +5278,8 @@ qboolean CSQC_Init (unsigned int checksum) csqcedict_t *worldent; csqcchecksum = checksum; + csqc_usinglistener = false; + //its already running... if (csqcprogs) return false; @@ -5070,7 +5331,7 @@ qboolean CSQC_Init (unsigned int checksum) csqcprogparms.globalbuiltins = pr_builtin;//builtin_t *globalbuiltins; //these are available to all progs csqcprogparms.numglobalbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); - csqcprogparms.autocompile = PR_NOCOMPILE;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; + csqcprogparms.autocompile = PR_COMPILEIGNORE;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; csqcprogparms.gametime = &csqctime; @@ -5089,11 +5350,16 @@ qboolean CSQC_Init (unsigned int checksum) CSQC_InitFields(); //let the qclib know the field order that the engine needs. - if (PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0) < 0) //no per-progs builtins. + csqc_isdarkplaces = false; + if (PR_LoadProgs(csqcprogs, "csprogs.dat", 32199, NULL, 0) < 0) //no per-progs builtins. { - CSQC_Shutdown(); - //failed to load or something - return false; + if (PR_LoadProgs(csqcprogs, "csprogs.dat", 52195, NULL, 0) < 0) //no per-progs builtins. + { + CSQC_Shutdown(); + //failed to load or something + return false; + } + csqc_isdarkplaces = true; } if (setjmp(csqc_abort)) { @@ -5120,17 +5386,16 @@ qboolean CSQC_Init (unsigned int checksum) worldent->readonly = true; worldent->isfree = false; worldent->v->model = PR_SetString(csqcprogs, cl.model_name[1]); - for (i = 0; i < 2; i++) - { - loadedcsqcpack[i].numents = 0; - loadedcsqcpack[i].maxents = 0; - Z_Free(loadedcsqcpack[i].entptr); - loadedcsqcpack[i].entptr = NULL; - Z_Free(loadedcsqcpack[i].entnum); - loadedcsqcpack[i].entnum = NULL; - } - memset(deltaedplayerents, 0, sizeof(deltaedplayerents)); + Z_Free(csqcdelta_pack_new.e); + memset(&csqcdelta_pack_new, 0, sizeof(csqcdelta_pack_new)); + Z_Free(csqcdelta_pack_old.e); + memset(&csqcdelta_pack_old, 0, sizeof(csqcdelta_pack_old)); + + memset(&deltafunction, 0, sizeof(deltafunction)); + + memset(csqcdelta_playerents, 0, sizeof(csqcdelta_playerents)); + csqcmapentitydata = NULL; csqcmapentitydataloaded = false; @@ -5415,6 +5680,11 @@ qboolean CSQC_ParseTempEntity(unsigned char firstbyte) return !!G_FLOAT(OFS_RETURN); } +qboolean CSQC_ParseGamePacket(void) +{ + return false; +} + qboolean CSQC_LoadResource(char *resname, char *restype) { void *pr_globals; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index dffdc8c04..9e9916afd 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -718,6 +718,8 @@ void PF_cl_setmousetarget (progfuncs_t *prinst, struct globalvars_s *pr_globals) //float getmousetarget(void) = #604; void PF_cl_getmousetarget (progfuncs_t *prinst, struct globalvars_s *pr_globals) { + extern int mouseusedforgui; + G_FLOAT(OFS_RETURN) = mouseusedforgui?1:2; } int MP_TranslateDPtoFTECodes(int code); @@ -760,6 +762,7 @@ void PF_cl_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *ret = G_VECTOR(OFS_RETURN); extern int mousemove_x, mousemove_y; + extern int mousecursor_x, mousecursor_y; ret[0] = mousemove_x; ret[1] = mousemove_y; @@ -767,8 +770,8 @@ void PF_cl_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_globals) mousemove_x=0; mousemove_y=0; -/* ret[0] = mousecursor_x; - ret[1] = mousecursor_y;*/ + ret[0] = mousecursor_x; + ret[1] = mousecursor_y; ret[2] = 0; } @@ -1637,7 +1640,7 @@ void MP_Init (void) menuprogparms.globalbuiltins = menu_builtins;//builtin_t *globalbuiltins; //these are available to all progs menuprogparms.numglobalbuiltins = menu_numbuiltins; - menuprogparms.autocompile = PR_COMPILEEXISTANDCHANGED;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; + menuprogparms.autocompile = PR_COMPILEIGNORE;//PR_COMPILEEXISTANDCHANGED;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; menuprogparms.gametime = &menutime; diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index fd475c869..a9825748b 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -131,17 +131,19 @@ extern "C" { #include "sys.h" #include "zone.h" #include "mathlib.h" -#include "wad.h" #include "cvar.h" -#include "screen.h" #include "net.h" #include "protocol.h" #include "cmd.h" +#if 1//ndef SERVERONLY +#include "wad.h" +#include "screen.h" #include "sbar.h" #include "sound.h" #include "merged.h" #include "render.h" #include "client.h" +#endif #include "vm.h" @@ -173,10 +175,8 @@ extern "C" { #include "progs.h" #endif #include "world.h" -#ifndef CLIENTONLY -//#ifdef Q2SERVER #include "q2game.h" -//#endif +#ifndef CLIENTONLY #include "server.h" #endif @@ -218,7 +218,7 @@ typedef struct quakeparms_s { char *basedir; int argc; - char **argv; + const char **argv; void *membase; unsigned int memsize; } quakeparms_t; @@ -238,6 +238,7 @@ extern qboolean noclip_anglehack; extern quakeparms_t host_parms; extern cvar_t com_gamename; +extern cvar_t com_modname; extern cvar_t sys_ticrate; extern cvar_t sys_nostdout; extern cvar_t developer; diff --git a/engine/client/render.h b/engine/client/render.h index 2c856458d..841ef01d6 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -383,6 +383,7 @@ void GL_InfinatePerspective(double fovx, double fovy, double zNear); void GLMod_Init (void); int Mod_TagNumForName(struct model_s *model, char *name); int Mod_SkinNumForName(struct model_s *model, char *name); +int Mod_FrameNumForName(struct model_s *model, char *name); void GLMod_ClearAll (void); struct model_s *GLMod_ForName (char *name, qboolean crash); @@ -444,11 +445,11 @@ void CLQ2_FlyEffect(struct q2centity_s *ent, vec3_t org); void CLQ2_DiminishingTrail(vec3_t oldorg, vec3_t neworg, struct q2centity_s *ent, unsigned int effects); void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg); -void WritePCXfile (char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit. +void WritePCXfile (const char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit. qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height); qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey); qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height); -qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, char *name); +qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, const char *name); qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out); void BoostGamma(qbyte *rgba, int width, int height); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 924d9f407..f4cf3e4dd 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -179,8 +179,15 @@ static cvar_t vid_bpp = SCVARF ("vid_bpp", "32", CVAR_ARCHIVE | CVAR_RENDERERLATCH); static cvar_t vid_desktopsettings = SCVARF ("vid_desktopsettings", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); +#ifdef NPQTV +static cvar_t vid_fullscreen_npqtv = SCVARF ("vid_fullscreen", "1", + CVAR_ARCHIVE | CVAR_RENDERERLATCH); +static cvar_t vid_fullscreen = SCVARF ("vid_fullscreen_embedded", "0", + CVAR_ARCHIVE | CVAR_RENDERERLATCH); +#else static cvar_t vid_fullscreen = SCVARF ("vid_fullscreen", "1", CVAR_ARCHIVE | CVAR_RENDERERLATCH); +#endif static cvar_t vid_height = SCVARF ("vid_height", "480", CVAR_ARCHIVE | CVAR_RENDERERLATCH); static cvar_t vid_multisample = SCVARF ("vid_multisample", "0", @@ -571,6 +578,7 @@ void Renderer_Init(void) currentrendererstate.bpp = -1; //no previous. currentrendererstate.renderer = -1; + qrenderer = -1; Cmd_AddCommand("setrenderer", R_SetRenderer_f); Cmd_AddCommand("vid_restart", R_RestartRenderer_f); @@ -593,6 +601,9 @@ void Renderer_Init(void) Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP); Cvar_Register (&vid_renderer, VIDCOMMANDGROUP); +#ifdef NPQTV + Cvar_Register (&vid_fullscreen_npqtv, VIDCOMMANDGROUP); +#endif Cvar_Register (&vid_fullscreen, VIDCOMMANDGROUP); // Cvar_Register (&vid_stretch, VIDCOMMANDGROUP); Cvar_Register (&vid_bpp, VIDCOMMANDGROUP); @@ -772,6 +783,7 @@ void (*Mod_Think) (void); //qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms); //int (*Mod_TagNumForName) (struct model_s *model, char *name); int (*Mod_SkinForName) (struct model_s *model, char *name); +int (*Mod_FrameForName) (struct model_s *model, char *name); @@ -790,7 +802,7 @@ void (*VID_SetWindowCaption) (char *msg); void (*SCR_UpdateScreen) (void); -r_qrenderer_t qrenderer=-1; +r_qrenderer_t qrenderer; char *q_renderername = "Non-Selected renderer"; @@ -883,6 +895,7 @@ rendererinfo_t dedicatedrendererinfo = { NULL, //Mod_GetTag NULL, //fixme: server will need this one at some point. NULL, + NULL, NULL, //VID_Init, NULL, //VID_DeInit, @@ -976,6 +989,7 @@ rendererinfo_t softwarerendererinfo = { NULL, //Mod_GetTag NULL, //Mod_TagForName NULL, + NULL, SWVID_Init, SWVID_Shutdown, @@ -1073,6 +1087,7 @@ rendererinfo_t openglrendererinfo = { Mod_GetTag, Mod_TagNumForName, Mod_SkinNumForName, + Mod_FrameNumForName, GLVID_Init, GLVID_DeInit, @@ -1108,7 +1123,9 @@ rendererinfo_t *pd3d9rendererinfo = &d3d9rendererinfo; rendererinfo_t **rendererinfo[] = { +#ifndef NPQTV &pdedicatedrendererinfo, +#endif #ifdef SWQUAKE &psoftwarerendererinfo, #endif @@ -1554,10 +1571,8 @@ void D3DSucks(void) Sys_Error("Failed to reload content after mode switch\n"); } -qboolean R_ApplyRenderer (rendererstate_t *newr) +void R_ShutdownRenderer(void) { - if (newr->bpp == -1) - return false; CL_AllowIndependantSendCmd(false); //FIXME: figure out exactly which parts are going to affect the model loading. @@ -1581,6 +1596,14 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) COM_FlushTempoaryPacks(); S_Shutdown(); +} + +qboolean R_ApplyRenderer (rendererstate_t *newr) +{ + if (newr->bpp == -1) + return false; + + R_ShutdownRenderer(); if (qrenderer == QR_NONE || qrenderer==-1) { diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 2551201a9..d40a00538 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -1164,7 +1164,7 @@ void Sbar_FillPC (int x, int y, int w, int h, unsigned int pcolour) { if (pcolour >= 16) { - Draw_FillRGB (x, y, w, h, (pcolour&0xff)/255.0f, ((pcolour&0xff00)>>8)/255.0f, ((pcolour&0xff0000)>>16)/255.0f); + Draw_FillRGB (x, y, w, h, ((pcolour&0xff0000)>>16)/255.0f, ((pcolour&0xff00)>>8)/255.0f, (pcolour&0xff)/255.0f); } else { @@ -2255,6 +2255,10 @@ void Sbar_Draw (void) sbar_parsingteamstatuses = false; +#ifdef HLCLIENT + if (CLHL_DrawHud()) + return; +#endif #ifdef Q2CLIENT if (cls.protocol == CP_QUAKE2) diff --git a/engine/client/skin.c b/engine/client/skin.c index 58fdbffed..bcc38d4f0 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -563,6 +563,9 @@ void Skin_FlushPlayers(void) int i; for (i = 0; i < MAX_CLIENTS; i++) cl.players[i].skin = NULL; + + for (i = 0; i < MAX_CLIENTS; i++) + CL_NewTranslation(i); } /* diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 677bfc4ed..8765c9059 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -102,6 +102,11 @@ void S_AmbientOn (void) snd_ambient = true; } +qboolean S_HaveOutput(void) +{ + return sound_started && sndcardinfo; +} + void S_SoundInfo_f(void) { @@ -361,7 +366,7 @@ void S_Startup (void) break; } - sound_started = 1; + sound_started = !!sndcardinfo; S_ClearRaw(); } @@ -540,11 +545,6 @@ void S_Init (void) { int p; - if (snd_initialized) //whoops - { - Con_Printf("Sound is already initialized\n"); - return; - } Con_DPrintf("\nSound Initialization\n"); Cmd_AddCommand("play", S_Play); @@ -1115,6 +1115,58 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) //============================================================================= +void S_Music_Clear(sfx_t *onlyifsample) +{ + //stops the current BGM music + //calling this will trigger Media_NextTrack later + sfx_t *s; + soundcardinfo_t *sc; + int i; + for (i = NUM_AMBIENTS; i < NUM_AMBIENTS + NUM_MUSICS; i++) + { + for (sc = sndcardinfo; sc; sc=sc->next) + { + s = sc->channel[i].sfx; + if (!s) + continue; + if (onlyifsample && s != onlyifsample) + continue; + + sc->channel[i].end = 0; + sc->channel[i].sfx = NULL; + + if (s) + if (s->decoder) + if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly. + { + s->decoder->abort(s); + if (s->cache.data) + Cache_Free(&s->cache); + } + } + } +} +void S_Music_Seek(float time) +{ + soundcardinfo_t *sc; + int i; + for (i = NUM_AMBIENTS; i < NUM_AMBIENTS + NUM_MUSICS; i++) + { + for (sc = sndcardinfo; sc; sc=sc->next) + { + sc->channel[i].pos += sc->sn.speed*time; + sc->channel[i].end += sc->sn.speed*time; + + if (sc->channel[i].pos < 0) + { //clamp to the start of the track + sc->channel[i].end -= sc->channel[i].pos; + sc->channel[i].pos=0; + } + //if we seek over the end, ignore it. The sound playing code will spot that. + } + } +} + /* =================== S_UpdateAmbientSounds @@ -1138,7 +1190,7 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc) chan = &sc->channel[i]; if (!chan->sfx) { - char *nexttrack = Media_NextTrack(); + char *nexttrack = Media_NextTrack(i-NUM_AMBIENTS); sfxcache_t *scache; sfx_t *newmusic; @@ -1210,7 +1262,7 @@ S_Update Called once each time through the main loop ============ */ -void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) +void S_UpdateListener(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, qboolean dontmix) { soundcardinfo_t *sc; @@ -1219,12 +1271,24 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) VectorCopy(right, listener_right); VectorCopy(up, listener_up); - S_RunCapture(); + if (dontmix) + { + S_RunCapture(); - for (sc = sndcardinfo; sc; sc = sc->next) - S_UpdateCard(sc); + for (sc = sndcardinfo; sc; sc = sc->next) + S_UpdateCard(sc); + } } + +void S_GetListenerInfo(float *origin, float *forward, float *right, float *up) +{ + VectorCopy(listener_origin, origin); + VectorCopy(listener_forward, forward); + VectorCopy(listener_right, right); + VectorCopy(listener_up, up); +} + void S_UpdateCard(soundcardinfo_t *sc) { int i, j; diff --git a/engine/client/snd_mem.c b/engine/client/snd_mem.c index ee02ca4ba..acdd42d9b 100644 --- a/engine/client/snd_mem.c +++ b/engine/client/snd_mem.c @@ -843,15 +843,21 @@ sfxcache_t *S_LoadSound (sfx_t *s) // load it in data = NULL; - if (*name == '*') + if (*name == '*') //q2 sexed sounds { + //clq2_parsestartsound detects this also + //here we just precache the male sound name, which provides us with our default Q_strcpy(namebuffer, "players/male/"); //q2 Q_strcat(namebuffer, name+1); //q2 } else if (name[0] == '.' && name[1] == '.' && name[2] == '/') + { + //not relative to sound/ Q_strcpy(namebuffer, name+3); + } else { + //q1 behaviour, relative to sound/ Q_strcpy(namebuffer, "sound/"); Q_strcat(namebuffer, name); data = COM_LoadStackFile(name, stackbuf, sizeof(stackbuf)); @@ -874,7 +880,7 @@ sfxcache_t *S_LoadSound (sfx_t *s) if (!data) { - //FIXME: check to see if qued for download. + //FIXME: check to see if queued for download. Con_DPrintf ("Couldn't load %s\n", namebuffer); s->failedload = true; return NULL; diff --git a/engine/client/sys_npqtv.c b/engine/client/sys_npqtv.c new file mode 100644 index 000000000..7faa17dc5 --- /dev/null +++ b/engine/client/sys_npqtv.c @@ -0,0 +1,1002 @@ +#include "quakedef.h" +#include "winquake.h" +#define bool int //we ain't c++ (grr microsoft stdbool.h gief!) + +#include "npapi/npupp.h" + +#define NPQTV_VERSION 0.1 + +#define FIREFOX_BUGS_OVER_25MB + +//TODO: player name input (before allowing them to join) +//TODO: fix active gl context (per thread, and we hijacked the browser's thread) + + +NPNetscapeFuncs *browserfuncs; + + + + +#ifdef _WIN32 +#ifndef GetWindowLongPtr +#define GetWindowLongPtr (void*)GetWindowLong +#endif +#ifndef SetWindowLongPtr +#define SetWindowLongPtr(w,p,v) SetWindowLong(w,p,(LONG)(v)) +#endif + + +extern HWND sys_hijackwindow; +HINSTANCE global_hInstance; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + global_hInstance = hinstDLL; + break; + default: + break; + } + return TRUE; +} +#endif + + + + + + +typedef struct +{ + vfsfile_t funcs; + + char *data; + int maxlen; + int writepos; + int readpos; +} vfspipe_t; + +void VFSPIPE_Close(vfsfile_t *f) +{ + vfspipe_t *p = (vfspipe_t*)f; + free(p->data); + free(p); +} +int VFSPIPE_GetLen(vfsfile_t *f) +{ + vfspipe_t *p = (vfspipe_t*)f; + return p->writepos - p->readpos; +} +int VFSPIPE_Tell(vfsfile_t *f) +{ + return 0; +} +qboolean VFSPIPE_Seek(vfsfile_t *f, unsigned long offset) +{ + Con_Printf("Seeking is a bad plan, mmkay?"); + return false; +} +int VFSPIPE_ReadBytes(vfsfile_t *f, void *buffer, int len) +{ + vfspipe_t *p = (vfspipe_t*)f; + if (len > p->writepos - p->readpos) + len = p->writepos - p->readpos; + memcpy(buffer, p->data+p->readpos, len); + p->readpos += len; + + if (p->readpos > 8192) + { + //shift the memory down periodically + //fixme: use cyclic buffer? max size, etc? + memmove(p->data, p->data+p->readpos, p->writepos-p->readpos); + + p->writepos -= p->readpos; + p->readpos = 0; + } + return len; +} +int VFSPIPE_WriteBytes(vfsfile_t *f, const void *buffer, int len) +{ + vfspipe_t *p = (vfspipe_t*)f; + if (p->writepos + len > p->maxlen) + { + p->maxlen = p->writepos + len; + p->data = realloc(p->data, p->maxlen); + } + memcpy(p->data+p->writepos, buffer, len); + p->writepos += len; + return len; +} + +vfsfile_t *VFSPIPE_Open(void) +{ + vfspipe_t *newf; + newf = malloc(sizeof(*newf)); + newf->data = NULL; + newf->maxlen = 0; + newf->readpos = 0; + newf->writepos = 0; + newf->funcs.Close = VFSPIPE_Close; + newf->funcs.Flush = NULL; + newf->funcs.GetLen = VFSPIPE_GetLen; + newf->funcs.ReadBytes = VFSPIPE_ReadBytes; + newf->funcs.Seek = VFSPIPE_Seek; + newf->funcs.Tell = VFSPIPE_Tell; + newf->funcs.WriteBytes = VFSPIPE_WriteBytes; + newf->funcs.seekingisabadplan = true; + + return &newf->funcs; +} + +char binaryname[MAX_PATH]; + +struct qstream +{ + vfsfile_t *pipe; + struct pipetype *type; + + struct qstream *next; + + char url[1]; +}; +struct context +{ + NPWindow window; + qboolean contextrunning; + int waitingfordatafiles; + float availver; + +#ifdef _WIN32 + WNDPROC oldproc; +#endif + + char datadownload[MAX_PATH]; + char gamename[MAX_QPATH]; + char *onstart; + char *onend; + char *ondemoend; + + NPP nppinstance; + + struct qstream *donestreams; + + int wait_size; + int wait_offset; + struct qstream *wait_stream; + + qtvfile_t qtvf; + + unsigned char *splashdata; + int splashwidth; + int splashheight; + + struct context *next; +}; + +struct context *activecontext; +struct context *contextlist; + + + + + + + + + +//////////////////////////////////////// + +struct pipetype +{ + enum { + WAIT_NO, + WAIT_YES, + WAIT_DONE + } wait; + qboolean needseeking; + void (*completionfunc) (struct context *ctx, vfsfile_t *file, const char *streamsource); + void (*beginfunc) (struct context *ctx, vfsfile_t *file, const char *streamsource); +}; + +#include "fs.h" +extern searchpathfuncs_t zipfilefuncs; + +int ExtractDataFile(const char *fname, int fsize, void *ptr) +{ + char buffer[8192]; + int read; + void *zip = ptr; + flocation_t loc; + int slashes; + const char *s; + vfsfile_t *compressedpak; + vfsfile_t *decompressedpak; + + if (zipfilefuncs.FindFile(zip, &loc, fname, NULL)) + { + compressedpak = zipfilefuncs.OpenVFS(zip, &loc, "rb"); + if (compressedpak) + { + //this extra logic is so we can handle things like nexuiz/data/blah.pk3 + //as well as just data/blah.pk3 + slashes = 0; + for (s = strchr(fname, '/'); s; s = strchr(s+1, '/')) + slashes++; + for (; slashes > 1; slashes--) + fname = strchr(fname, '/')+1; + + if (!slashes) + { + FS_CreatePath(fname, FS_GAMEONLY); + decompressedpak = FS_OpenVFS(fname, "wb", FS_GAMEONLY); + } + else + { + FS_CreatePath(fname, FS_ROOT); + decompressedpak = FS_OpenVFS(fname, "wb", FS_ROOT); + } + if (decompressedpak) + { + for(;;) + { + read = VFS_READ(compressedpak, buffer, sizeof(buffer)); + if (read <= 0) + break; + VFS_WRITE(decompressedpak, buffer, read); + } + VFS_CLOSE(decompressedpak); + } + VFS_CLOSE(compressedpak); + } + } + return true; +} + +void UnpackAndExtractPakFiles_Complete(struct context *ctx, vfsfile_t *file, const char *streamsource) +{ + extern searchpathfuncs_t zipfilefuncs; + void *zip; + + zip = zipfilefuncs.OpenNew(file, streamsource); + if (zip) + { + zipfilefuncs.EnumerateFiles(zip, "*.pk3", ExtractDataFile, zip); + zipfilefuncs.EnumerateFiles(zip, "*.pak", ExtractDataFile, zip); + + zipfilefuncs.ClosePath(zip); + + Cmd_ExecuteString("fs_restart", RESTRICT_LOCAL); + + //this code is to stop them from constantly downloading if that zip didn't contain one for some reason + if (!FS_FLocateFile("default.cfg", FSLFRT_IFFOUND, NULL)) + { + FS_WriteFile("default.cfg", "", 0, FS_GAMEONLY); + } + } +} +struct pipetype UnpackAndExtractPakFiles = +{ + WAIT_YES, + true, + UnpackAndExtractPakFiles_Complete +}; + +void LoadSplashImage(struct context *ctx, vfsfile_t *f, const char *name) +{ + int x, y; + int width = 0; + int height = 0; + int len = VFS_GETLEN(f); + char *buffer = malloc(len); + unsigned char *image; + VFS_READ(f, buffer, len); + VFS_CLOSE(f); + + image = NULL; + if (!image) + image = ReadJPEGFile(buffer, len, &width, &height); + if (!image) + image = ReadPNGFile(buffer, len, &width, &height, name); + + free(buffer); + if (image) + { + ctx->splashdata = malloc(width*height*4); + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + ctx->splashdata[(y*width + x)*4+0] = image[((height-y-1)*width + x)*4+2]; + ctx->splashdata[(y*width + x)*4+1] = image[((height-y-1)*width + x)*4+1]; + ctx->splashdata[(y*width + x)*4+2] = image[((height-y-1)*width + x)*4+0]; + } + } + ctx->splashwidth = width; + ctx->splashheight = height; + BZ_Free(image); + + if (ctx->window.window) + InvalidateRgn(ctx->window.window, NULL, FALSE); + } +} + +struct pipetype SplashscreenImageDescriptor = +{ + WAIT_DONE, + false, + LoadSplashImage +}; + +static void ReadQTVFileDescriptor(struct context *ctx, vfsfile_t *f, const char *name) +{ + CL_ParseQTVFile(f, name, &ctx->qtvf); + + if (*ctx->qtvf.splashscreen) + { + browserfuncs->geturlnotify(ctx->nppinstance, ctx->qtvf.splashscreen, NULL, &SplashscreenImageDescriptor); + } +} +struct pipetype QTVFileDescriptor = +{ + WAIT_DONE, + false, + ReadQTVFileDescriptor +}; +void CL_QTVPlay (vfsfile_t *newf, qboolean iseztv); +static void BeginDemo(struct context *ctx, vfsfile_t *f, const char *name) +{ + if (!activecontext) + activecontext = ctx; + + CL_QTVPlay(f, false); +} +static void EndDemo(struct context *ctx, vfsfile_t *f, const char *name) +{ + Cmd_ExecuteString("disconnect", RESTRICT_LOCAL); +} +struct pipetype DemoFileDescriptor = +{ + WAIT_NO, + false, + EndDemo, + BeginDemo +}; + +///////////////////////////////////// + + +#ifdef _WIN32 +void DrawWndBack(struct context *ctx, HWND hWnd, HDC hdc, PAINTSTRUCT *p) +{ + if (ctx->splashdata) + { + HBITMAP bmp; + BITMAPINFOHEADER bmh; + HDC memDC; + + bmh.biSize = sizeof(bmh); + bmh.biWidth = ctx->splashwidth; + bmh.biHeight = ctx->splashheight; + bmh.biPlanes = 1; + bmh.biBitCount = 32; + bmh.biCompression = BI_RGB; + bmh.biSizeImage = 0; + bmh.biXPelsPerMeter = 0; + bmh.biYPelsPerMeter = 0; + bmh.biClrUsed = 0; + bmh.biClrImportant = 0; + + memDC = CreateCompatibleDC(hdc); + bmp = CreateDIBitmap(hdc, + &bmh, + CBM_INIT, + (LPSTR)ctx->splashdata, + (LPBITMAPINFO)&bmh, + DIB_RGB_COLORS ); + + SelectObject(memDC, bmp); +// StretchBlt(hdc, 0, 0, p->rcPaint.right-p->rcPaint.left, p->rcPaint.bottom-p->rcPaint.top, memDC, 0, 0, ctx->splashwidth, ctx->splashheight, SRCCOPY); + StretchBlt(hdc, 0, 0, ctx->window.width, ctx->window.height, memDC, 0, 0, ctx->splashwidth, ctx->splashheight, SRCCOPY); + SelectObject(memDC, NULL); + DeleteDC(memDC); + DeleteObject(bmp); + } + else + PatBlt(hdc, p->rcPaint.left, p->rcPaint.top, p->rcPaint.right-p->rcPaint.left,p->rcPaint.bottom-p->rcPaint.top,PATCOPY); +} + +LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct qstream *str; + struct context *ctx; + ctx = GetWindowLongPtr(hWnd, GWL_USERDATA); + if (!ctx) + return DefWindowProc(hWnd, msg, wParam, lParam); + + switch(msg) + { + case WM_MOVE: + if (ctx->contextrunning) + { + PostMessage(mainwindow, WM_MOVE, 0, 0); + } + break; + case WM_TIMER: + if (ctx->contextrunning && !ctx->waitingfordatafiles) + { + while (ctx->donestreams) + { + str = ctx->donestreams; + ctx->donestreams = str->next; + + if (str->pipe) + { + if (str->type->completionfunc) + str->type->completionfunc(ctx, str->pipe, str->url); + else + VFS_CLOSE(str->pipe); + } + + free(str); + } + + if (sys_hijackwindow != ctx->window.window) + { + if (!sys_hijackwindow) + { + switch(ctx->qtvf.connectiontype) + { + case QTVCT_STREAM: + Cmd_ExecuteString(va("qtvplay %s", ctx->qtvf.server), RESTRICT_LOCAL); + break; + case QTVCT_CONNECT: + Cmd_ExecuteString(va("connect %s", ctx->qtvf.server), RESTRICT_LOCAL); + break; + case QTVCT_JOIN: + Cmd_ExecuteString(va("join %s", ctx->qtvf.server), RESTRICT_LOCAL); + break; + case QTVCT_OBSERVE: + Cmd_ExecuteString(va("observe %s", ctx->qtvf.server), RESTRICT_LOCAL); + break; + } + } + + sys_hijackwindow = ctx->window.window; + if (sys_hijackwindow) + { + Cvar_SetValue(Cvar_FindVar("vid_width"), ctx->window.width); + Cvar_SetValue(Cvar_FindVar("vid_height"), ctx->window.height); + Cmd_ExecuteString("vid_restart", RESTRICT_LOCAL); + } + } + else + { + NPQTV_Sys_MainLoop(); + if (!host_initialized) + { + //quit was issued + ctx->contextrunning = false; + activecontext = NULL; + InvalidateRgn(hWnd, NULL, FALSE); + + if (ctx->onend) + browserfuncs->geturl(ctx->nppinstance, va("javascript:%s;", ctx->onend), "_self"); + } + } + } + return TRUE; + + case WM_PAINT: + if (activecontext == ctx && !ctx->contextrunning && ctx->window.window) + { + int argc; + char *argv[16]; + sys_hijackwindow = NULL; + + GetModuleFileName(global_hInstance, binaryname, sizeof(binaryname)); + argv[0] = binaryname; + argc = 1; + + activecontext = ctx; + + if (!*ctx->gamename || !strcmp(ctx->gamename, "q1") || !strcmp(ctx->gamename, "qw") || !strcmp(ctx->gamename, "quake") || !strcmp(ctx->gamename, "id1")) + argv[argc++] = "-quake"; + else if (!strcmp(ctx->gamename, "q2") || !strcmp(ctx->gamename, "quake2")) + argv[argc++] = "-q2"; + else if (!strcmp(ctx->gamename, "q3") || !strcmp(ctx->gamename, "quake3")) + argv[argc++] = "-q3"; + else if (!strcmp(ctx->gamename, "hl") || !strcmp(ctx->gamename, "halflife")) + argv[argc++] = "-halflife"; + else if (!strcmp(ctx->gamename, "h2") || !strcmp(ctx->gamename, "hexen2")) + argv[argc++] = "-hexen2"; + else if (!strcmp(ctx->gamename, "nex") || !strcmp(ctx->gamename, "nexuiz")) + argv[argc++] = "-nexuiz"; + else + { + argv[argc++] = "-basegame"; + argv[argc++] = ctx->gamename; + } + ctx->contextrunning = NPQTV_Sys_Startup(argc, argv); + + Cvar_SetValue(Cvar_FindVar("vid_width"), ctx->window.width); + Cvar_SetValue(Cvar_FindVar("vid_height"), ctx->window.height); + + if (*ctx->datadownload) + { + if (!FS_FLocateFile("default.cfg", FSLFRT_IFFOUND, NULL) || !FS_FLocateFile("gfx.wad", FSLFRT_IFFOUND, NULL)) + { + browserfuncs->geturlnotify(ctx->nppinstance, ctx->datadownload, NULL, &UnpackAndExtractPakFiles); + ctx->waitingfordatafiles++; + } + } + + if (ctx->contextrunning) + { + if (ctx->onstart) + browserfuncs->geturl(ctx->nppinstance, va("javascript:%s;", ctx->onstart), "_self"); + + //windows timers have low precision, ~10ms + //they're low priority anyway, so we might as well just create lots and spam them + SetTimer(hWnd, 1, 1, NULL); + SetTimer(hWnd, 2, 1, NULL); + SetTimer(hWnd, 3, 1, NULL); + SetTimer(hWnd, 4, 1, NULL); + SetTimer(hWnd, 5, 1, NULL); + } + } + + if (ctx->waitingfordatafiles) + { + HDC hdc; + PAINTSTRUCT paint; + char *s; + + hdc = BeginPaint(hWnd, &paint); + DrawWndBack(ctx, hWnd, hdc, &paint); + SetBkMode(hdc, TRANSPARENT); + TextOutA(hdc, 0, 0, "Downloading Data, please wait", 16); + if (!ctx->wait_stream) + s = "connecting"; + else if (ctx->wait_size > 0) + s = va("%i bytes (%i%%)", ctx->wait_offset, (int)((100.0f*ctx->wait_offset)/ctx->wait_size)); + else + s = va("%i bytes", ctx->wait_offset); + TextOutA(hdc, 0, 32, s, strlen(s)); + EndPaint(hWnd, &paint); + return TRUE; + } + else if (!ctx->contextrunning) + { + HDC hdc; + PAINTSTRUCT paint; + char *s; + + hdc = BeginPaint(hWnd, &paint); + DrawWndBack(ctx, hWnd, hdc, &paint); + SetBkMode(hdc, TRANSPARENT); + if (!activecontext) + TextOutA(hdc, 0, 0, "Click to activate", 19); + if (ctx->availver) + { + s = va("Your plugin is out of date"); + TextOutA(hdc, 0, 16, s, strlen(s)); + s = va("Version %3.1f is available", ctx->availver); + TextOutA(hdc, 0, 32, s, strlen(s)); + } + EndPaint(hWnd, &paint); + return TRUE; + } + break; + + case WM_LBUTTONDOWN: + if (!activecontext) + { + activecontext = ctx; + InvalidateRgn(hWnd, NULL, FALSE); + } + else + Cbuf_AddText("quit\n", RESTRICT_LOCAL); + break; + default: + break; + } + + //I would call the previous wndproc... but that crashes firefox + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +#endif + +NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, + uint16 mode, int16 argc, char* argn[], + char* argv[], NPSavedData* saved) +{ + int i; + struct context *ctx; + if (!instance) + return NPERR_INVALID_INSTANCE_ERROR; + if (mode != NP_EMBED && mode != NP_FULL) + return NPERR_INVALID_PLUGIN_ERROR; + + ctx = malloc(sizeof(struct context)); + if (!ctx) + return NPERR_OUT_OF_MEMORY_ERROR; + + memset(ctx, 0, sizeof(struct context)); + + //link the instance to the context and the context to the instance + instance->pdata = ctx; + ctx->nppinstance = instance; + + Q_strncpyz(ctx->gamename, "q1", sizeof(ctx->gamename)); + + //parse out the properties + for (i = 0; i < argc; i++) + { + if (!stricmp(argn[i], "datadownload")) + { + Q_strncpyz(ctx->datadownload, argv[i], sizeof(ctx->datadownload)); + } + else if (!stricmp(argn[i], "game")) + { + if (!strstr(argn[i], ".")) + if (!strstr(argn[i], "/")) + if (!strstr(argn[i], "\\")) + if (!strstr(argn[i], ":")) + Q_strncpyz(ctx->gamename, argv[i], sizeof(ctx->gamename)); + } + else if (!stricmp(argn[i], "onstart")) + { + ctx->onstart = strdup(argv[i]); + } + else if (!stricmp(argn[i], "onend")) + { + ctx->onend = strdup(argv[i]); + } + else if (!stricmp(argn[i], "ondemoend")) + { + ctx->ondemoend = strdup(argv[i]); + } + else if (!stricmp(argn[i], "availver")) + { + ctx->availver = atof(argv[i]); + if (ctx->availver <= NPQTV_VERSION) + ctx->availver = 0; + } + else if (!stricmp(argn[i], "begin")) + { + if (atoi(argv[i]) && !activecontext) + activecontext = ctx; + } + + } + + //add it to the linked list + ctx->next = contextlist; + contextlist = ctx; + return NPERR_NO_ERROR; +} +NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save) +{ + struct context *ctx = instance->pdata; + struct context *prev; + +#ifdef _WIN32 + if (ctx->window.window) + { + if (ctx->oldproc) + SetWindowLongPtr(ctx->window.window, GWL_WNDPROC, ctx->oldproc); + SetWindowLongPtr(ctx->window.window, GWL_USERDATA, NULL); + } +#endif + + if (ctx->splashdata) + free(ctx->splashdata); + + if (ctx == contextlist) + contextlist = ctx->next; + else + { + for (prev = contextlist; prev->next; prev = prev->next) + { + if (prev->next == ctx) + { + prev->next = ctx->next; + break; + } + } + } + + if (ctx->contextrunning) + { + NPQTV_Sys_Shutdown(); + } + if (ctx == activecontext) + { + activecontext = NULL; + sys_hijackwindow = NULL; + } + + free(ctx); + instance->pdata = NULL; + + return NPERR_NO_ERROR; +} +NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window) +{ + struct context *ctx = instance->pdata; + +#ifdef _WIN32 + HWND oldwindow = ctx->window.window; + WNDPROC p; + + memcpy(&ctx->window, window, sizeof(ctx->window)); + + //if the window changed + if (ctx->window.window != oldwindow) + { + //we switched window? + if (oldwindow && ctx->oldproc) + { + SetWindowLongPtr(oldwindow, GWL_WNDPROC, ctx->oldproc); + ctx->oldproc = NULL; + } + + p = GetWindowLongPtr(ctx->window.window, GWL_WNDPROC); + if (p != MyPluginWndProc) + ctx->oldproc = p; + + SetWindowLongPtr(ctx->window.window, GWL_WNDPROC, MyPluginWndProc); + SetWindowLongPtr(ctx->window.window, GWL_USERDATA, ctx); + + if (ctx->contextrunning && mainwindow && oldwindow == sys_hijackwindow) + { + sys_hijackwindow = ctx->window.window; + SetParent(mainwindow, ctx->window.window); + + oldwindow = sys_hijackwindow; + } + } + + if (ctx->contextrunning && mainwindow && oldwindow == sys_hijackwindow) + MoveWindow(mainwindow, 0, 0, ctx->window.width, ctx->window.height, FALSE); + + InvalidateRgn(ctx->window.window, NULL, FALSE); +#endif + return NPERR_NO_ERROR; +} + +NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, + NPStream* stream, NPBool seekable, + uint16* stype) +{ + struct context *ctx = instance->pdata; + struct qstream *qstr; + + stream->pdata = qstr = malloc(sizeof(*qstr) + strlen(stream->url)); + memset(qstr, 0, sizeof(*qstr)); + strcpy(qstr->url, stream->url); + + if (!stream->notifyData) + { + //choose source type based on mime type + if (!strncmp(type, "text/x-quaketvident", 5)) + stream->notifyData = &QTVFileDescriptor; + else if (!strcmp(type, "application/x-multiviewdemo")) + stream->notifyData = &DemoFileDescriptor; + + //well that failed, try choosing based on extension + else if (!strcmp(COM_FileExtension(stream->url), "qtv")) + stream->notifyData = &QTVFileDescriptor; + + else + return NPERR_INVALID_PARAM; + } + qstr->type = stream->notifyData; + + if (qstr->type->needseeking) + { + *stype = NP_ASFILEONLY; //everything is a download + +#ifdef FIREFOX_BUGS_OVER_25MB + *stype = NP_NORMAL; + qstr->pipe = FS_OpenTemp(); +#endif + } + else + { + *stype = NP_NORMAL; + qstr->pipe = VFSPIPE_Open(); + } + + return NPERR_NO_ERROR; +} +NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, + NPReason reason) +{ + struct context *ctx = instance->pdata; + struct qstream *qstr = stream->pdata; + + if (!qstr) //urm, got canceled before it finished downloading? + return NPERR_NO_ERROR; + + if (ctx->wait_stream == qstr) + ctx->wait_stream = NULL; + + if (qstr->type->wait == WAIT_YES) + { + ctx->waitingfordatafiles--; + } + + if (qstr->type->wait == WAIT_DONE) + qstr->type->completionfunc(ctx, qstr->pipe, qstr->url); + else + { + qstr->next = ctx->donestreams; + ctx->donestreams = qstr; + } + + //CL_QTVPlay(pipe, false); + + return NPERR_NO_ERROR; +} +int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream) +{ + struct qstream *qstr = stream->pdata; + vfsfile_t *pipe = qstr?qstr->pipe:NULL; + + if (pipe && pipe->seekingisabadplan) + return 1024*1024 - VFS_GETLEN(pipe); + else + return 8192; +} +int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer) +{ + int bytes = NPP_WriteReady(instance, stream); + struct context *ctx = instance->pdata; + struct qstream *qstr = stream->pdata; + + if (qstr && qstr->type && qstr->type->wait) + { + if (!ctx->wait_stream) + ctx->wait_stream = qstr; + if (ctx->wait_stream == qstr) + { + ctx->wait_offset = offset; + ctx->wait_size = stream->end; + + InvalidateRgn(ctx->window.window, NULL, FALSE); + } + } + + if (!qstr || !qstr->pipe) + return bytes; + + //we're not meant to read more bytes than we said we could read. + if (len > bytes) + len = bytes; + + return VFS_WRITE(qstr->pipe, buffer, len); +} +void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, + const char* fname) +{ + struct qstream *qstr = stream->pdata; + + if (!qstr) + return; + + if (qstr->pipe) + VFS_CLOSE(qstr->pipe); + qstr->pipe = VFSOS_Open(fname, "rb"); +} +void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint) +{ + //we don't support printing. + //paper and ink doesn't give a good frame rate. + return; +} +int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event) +{ +// MessageBox(NULL, "NPP_HandleEvent", "npapi", 0); + return NPERR_NO_ERROR; +} +void NP_LOADDS NPP_URLNotify(NPP instance, const char* url, + NPReason reason, void* notifyData) +{ +} + +NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value) +{ + switch(variable) + { + case NPPVpluginScriptableNPObject: + *(void**)value = NULL; //no scripting object, sorry. + return NPERR_NO_ERROR; + default: + return NPERR_INVALID_PARAM; + } + + return NPERR_NO_ERROR; +} +NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value) +{ + switch(variable) + { + default: + return NPERR_INVALID_PARAM; + } + return NPERR_NO_ERROR; +} + + + + +NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs) +{ + browserfuncs = pFuncs; + return NPERR_NO_ERROR; +} + +NPError OSCALL NP_Shutdown(void) +{ + if (contextlist) + { //the browser isn't meant to call this when there's still instances left... + return NPERR_GENERIC_ERROR; + } + + return NPERR_NO_ERROR; +} + +NPError OSCALL NP_GetValue(void *instance, NPPVariable variable, void *value) +{ + if (value == NULL) + return NPERR_INVALID_PARAM; + + switch(variable) + { + case NPPVpluginNameString: + *(char**)value = "QTV Viewer"; + break; + case NPPVpluginDescriptionString: + *(char**)value = "QTV Viewer"; + break; + default: + return NPERR_INVALID_PARAM; + } + return NPERR_NO_ERROR; +} + +NPError OSCALL NP_GetEntryPoints (NPPluginFuncs* pFuncs) +{ + if (pFuncs->size < sizeof(NPPluginFuncs)) + return NPERR_INVALID_FUNCTABLE_ERROR; + pFuncs->size = sizeof(NPPluginFuncs); + + pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; + + pFuncs->newp = NPP_New; + pFuncs->destroy = NPP_Destroy; + pFuncs->setwindow = NPP_SetWindow; + pFuncs->newstream = NPP_NewStream; + pFuncs->destroystream = NPP_DestroyStream; + pFuncs->asfile = NPP_StreamAsFile; + pFuncs->writeready = NPP_WriteReady; + pFuncs->write = NPP_Write; + pFuncs->print = NPP_Print; + pFuncs->event = NPP_HandleEvent; + pFuncs->urlnotify = NPP_URLNotify; + pFuncs->javaClass = NULL; + pFuncs->getvalue = NPP_GetValue; + pFuncs->setvalue = NPP_SetValue; + + return NPERR_NO_ERROR; +} + +char *NP_GetMIMEDescription(void) +{ + return "test/x-qtv:qtv:QTV Stream Description"; +} diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index cb8405a29..98317da5a 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -37,6 +37,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #endif +#if !defined(CLIENTONLY) && !defined(SERVERONLY) +qboolean isDedicated = false; +#endif + +HWND sys_hijackwindow; void Sys_CloseLibrary(dllhandle_t *lib) { @@ -51,16 +56,19 @@ dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs) if (!lib) return NULL; - for (i = 0; funcs[i].name; i++) + if (funcs) { - *funcs[i].funcptr = GetProcAddress(lib, funcs[i].name); - if (!*funcs[i].funcptr) - break; - } - if (funcs[i].name) - { - Sys_CloseLibrary((dllhandle_t*)lib); - lib = NULL; + for (i = 0; funcs[i].name; i++) + { + *funcs[i].funcptr = GetProcAddress(lib, funcs[i].name); + if (!*funcs[i].funcptr) + break; + } + if (funcs[i].name) + { + Sys_CloseLibrary((dllhandle_t*)lib); + lib = NULL; + } } return (dllhandle_t*)lib; @@ -462,7 +470,7 @@ qboolean Sys_remove (char *path) return true; } -int Sys_EnumerateFiles (char *gpath, char *match, int (*func)(char *, int, void *), void *parm) +int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { HANDLE r; WIN32_FIND_DATA fd; @@ -718,7 +726,14 @@ void Sys_Quit (void) SV_Shutdown(); #endif +#ifdef NPQTV + { + extern jmp_buf host_abort; + longjmp (host_abort, 1); + } +#else exit (0); +#endif } @@ -1076,9 +1091,9 @@ void Sys_Sleep (void) { } - void Sys_SendKeyEvents (void) { +#ifndef NPQTV MSG msg; if (isDedicated) @@ -1100,6 +1115,7 @@ void Sys_SendKeyEvents (void) TranslateMessage (&msg); DispatchMessage (&msg); } +#endif } @@ -1129,6 +1145,128 @@ void SleepUntilInput (int time) MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT); } + + + + + + + +qboolean Sys_Startup_CheckMem(quakeparms_t *parms) +{ + int t; + MEMORYSTATUS lpBuffer; + lpBuffer.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus (&lpBuffer); + +// take the greater of all the available memory or half the total memory, +// but at least 8 Mb and no more than 16 Mb, unless they explicitly +// request otherwise + parms->memsize = lpBuffer.dwAvailPhys; + + if (parms->memsize < MINIMUM_WIN_MEMORY) + parms->memsize = MINIMUM_WIN_MEMORY; + + if (parms->memsize < (lpBuffer.dwTotalPhys >> 1)) + parms->memsize = lpBuffer.dwTotalPhys >> 1; + + if (parms->memsize > MAXIMUM_WIN_MEMORY) + parms->memsize = MAXIMUM_WIN_MEMORY; + + if (COM_CheckParm ("-heapsize")) + { + t = COM_CheckParm("-heapsize") + 1; + + if (t < com_argc) + parms->memsize = Q_atoi (com_argv[t]) * 1024; + } + else if (COM_CheckParm ("-mem")) + { + t = COM_CheckParm("-mem") + 1; + + if (t < com_argc) + parms->memsize = Q_atoi (com_argv[t]) * 1024*1024; + } + + parms->membase = VirtualAlloc (NULL, parms->memsize, MEM_RESERVE, PAGE_NOACCESS); +// parms->membase = malloc (parms.memsize); + + if (!parms->membase) + return false; + return true; +} + +#ifdef NPQTV +static quakeparms_t parms; +double lastlooptime; +qboolean NPQTV_Sys_Startup(int argc, char *argv[]) +{ + if (!host_initialized) + { + TL_InitLanguages(); + + parms.argc = argc; + parms.argv = argv; + parms.basedir = argv[0]; + COM_InitArgv (parms.argc, parms.argv); + + if (!Sys_Startup_CheckMem(&parms)) + return false; + + Host_Init (&parms); + } + + lastlooptime = Sys_DoubleTime (); + + return true; +} + +void NPQTV_Sys_MainLoop(void) +{ + double duratrion, newtime; + + if (isDedicated) + { +#ifndef CLIENTONLY + NET_Sleep(50, false); + + // find time passed since last cycle + newtime = Sys_DoubleTime (); + duratrion = newtime - lastlooptime; + lastlooptime = newtime; + + SV_Frame (); +#else + Sys_Error("wut?"); +#endif + } + else + { +#ifndef SERVERONLY + newtime = Sys_DoubleTime (); + duratrion = newtime - lastlooptime; + Host_Frame (duratrion); + lastlooptime = newtime; + + SetHookState(sys_disableWinKeys.value); + +// Sleep(0); +#else + Sys_Error("wut?"); +#endif + } +} + +void NPQTV_Sys_Shutdown(void) +{ + //disconnect server/client/etc + CL_Disconnect_f(); + R_ShutdownRenderer(); + + Host_Shutdown(); +} + +#else /* ================== WinMain @@ -1140,9 +1278,6 @@ char *argv[MAX_NUM_ARGVS]; static char exename[256]; HWND hwnd_dialog; -#if !defined(CLIENTONLY) && !defined(SERVERONLY) -qboolean isDedicated = false; -#endif /* #ifdef _MSC_VER #include @@ -1160,11 +1295,9 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin // MSG msg; quakeparms_t parms; double time, oldtime, newtime; - MEMORYSTATUS lpBuffer; char cwd[1024]; - int t; RECT rect; - char *qtvfile = NULL; + const char *qtvfile = NULL; /* previous instances do not exist in Win32 */ if (hPrevInstance) @@ -1181,9 +1314,6 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin global_hInstance = hInstance; global_nCmdShow = nCmdShow; - lpBuffer.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus (&lpBuffer); - parms.argc = 1; argv[0] = exename; @@ -1301,41 +1431,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin SetForegroundWindow (hwnd_dialog); } -// take the greater of all the available memory or half the total memory, -// but at least 8 Mb and no more than 16 Mb, unless they explicitly -// request otherwise - parms.memsize = lpBuffer.dwAvailPhys; - if (parms.memsize < MINIMUM_WIN_MEMORY) - parms.memsize = MINIMUM_WIN_MEMORY; - - if (parms.memsize < (lpBuffer.dwTotalPhys >> 1)) - parms.memsize = lpBuffer.dwTotalPhys >> 1; - - if (parms.memsize > MAXIMUM_WIN_MEMORY) - parms.memsize = MAXIMUM_WIN_MEMORY; - - if (COM_CheckParm ("-heapsize")) - { - t = COM_CheckParm("-heapsize") + 1; - - if (t < com_argc) - parms.memsize = Q_atoi (com_argv[t]) * 1024; - } - else if (COM_CheckParm ("-mem")) - { - t = COM_CheckParm("-mem") + 1; - - if (t < com_argc) - parms.memsize = Q_atoi (com_argv[t]) * 1024*1024; - } - - parms.membase = VirtualAlloc (NULL, parms.memsize, MEM_RESERVE, PAGE_NOACCESS); -// parms.membase = malloc (parms.memsize); - - if (!parms.membase) + if (!Sys_Startup_CheckMem(&parms)) Sys_Error ("Not enough memory free; check disk space\n"); + #ifndef CLIENTONLY if (isDedicated) //compleate denial to switch to anything else - many of the client structures are not initialized. { @@ -1429,6 +1529,7 @@ int __cdecl main(void) FreeConsole(); return WinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), SW_NORMAL); } +#endif qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate) { diff --git a/engine/client/textedit.c b/engine/client/textedit.c index b613789c4..28a153ea0 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -312,7 +312,7 @@ void EditorOpenFile(char *name) memcpy(firstblock->data, line, len); if (editprogfuncs) { - if (editprogfuncs->ToggleBreak(editprogfuncs, OpenEditorFile+strlen(com_gamedir)+1, i, 3)) + if (editprogfuncs->ToggleBreak(editprogfuncs, OpenEditorFile, i, 3)) { firstblock->flags |= FB_BREAK; } @@ -321,7 +321,7 @@ void EditorOpenFile(char *name) { if (svprogfuncs) { - if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile+strlen(com_gamedir)+1, i, 3)) + if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile, i, 3)) { firstblock->flags |= FB_BREAK; } diff --git a/engine/client/valid.c b/engine/client/valid.c index 2b27737b8..394332ecf 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -444,17 +444,13 @@ void Validation_DelatchRulesets(void) Con_DPrintf("Ruleset deactivated\n"); } -void Validation_AllChecks(void) -{ -} - -void Validation_OldRuleset(void) +qboolean Validation_GetCurrentRulesetName(char *rsnames, int resultbuflen, qboolean enforcechosenrulesets) { //this code is more complex than it needs to be //this allows for the ruleset code to print a ruleset name that is applied via the cvars, but not directly named by the user cvar_t *var; ruleset_t *rs; int i; - char rsnames[1024]; + rs = rulesets; *rsnames = '\0'; @@ -484,34 +480,75 @@ void Validation_OldRuleset(void) { if (*rsnames) { - Q_strncatz(rsnames, ", ", sizeof(rsnames)); + Q_strncatz(rsnames, ", ", resultbuflen); } - Q_strncatz(rsnames, rs->rulesetname, sizeof(rsnames)); + Q_strncatz(rsnames, rs->rulesetname, resultbuflen); rs->flagged = true; } } if (*rsnames) { - Cbuf_AddText(va("say Ruleset: %s\n", rsnames), RESTRICT_LOCAL); - - //now we've told the other players what rules we're playing by, we'd best stick to them - for (rs = rulesets; rs->rulesetname; rs++) + //as we'll be telling the other players what rules we're playing by, we'd best stick to them + if (enforcechosenrulesets) { - if (!rs->flagged) - continue; - for (i = 0; rs->rule[i].rulename; i++) + for (rs = rulesets; rs->rulesetname; rs++) { - var = Cvar_FindVar(rs->rule[i].rulename); - if (!var) + if (!rs->flagged) continue; - RulesetLatch(var); //set the latched flag + for (i = 0; rs->rule[i].rulename; i++) + { + var = Cvar_FindVar(rs->rule[i].rulename); + if (!var) + continue; + RulesetLatch(var); //set the latched flag + } } } + return true; } + else + return false; +} + +void Validation_OldRuleset(void) +{ + char rsnames[1024]; + + if (Validation_GetCurrentRulesetName(rsnames, sizeof(rsnames), true)) + Cbuf_AddText(va("say Ruleset: %s\n", rsnames), RESTRICT_LOCAL); else Cbuf_AddText("say No specific ruleset\n", RESTRICT_LOCAL); } +void Validation_AllChecks(void) +{ + char servername[22]; + char playername[16]; + char *enginebuild = va(DISTRIBUTION "%i", build_number()); + char localpnamelen = strlen(cl.players[cl.playernum[0]].name); + char ruleset[1024]; + + //figure out the padding for the player's name. + if (localpnamelen >= 15) + playername[0] = 0; + else + { + memset(playername, ' ', 15-localpnamelen-1); + playername[15-localpnamelen] = 0; + } + + //get the current server address + NET_AdrToString(servername, sizeof(servername), cls.netchan.remote_address); + + //get the ruleset names + if (!Validation_GetCurrentRulesetName(ruleset, sizeof(ruleset), true)) + Q_strncpyz(ruleset, "no ruleset", sizeof(ruleset)); + + //now send it + CL_SendClientCommand(true, "say \"%s%21s " "%16s %s\"", playername, servername, enginebuild, ruleset); + +} + void Validation_Apply_Ruleset(void) { //rulesets are applied when the client first gets a connection to the server ruleset_t *rs; diff --git a/engine/client/view.c b/engine/client/view.c index 340be640d..f14cd3537 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1198,7 +1198,10 @@ void V_CalcRefdef (int pnum) view->model = NULL; else view->model = cl.model_precache[cl.stats[pnum][STAT_WEAPON]]; - view->framestate.g[FS_REG].frame[0] = view_message?view_message->weaponframe:0; +#ifdef HLCLIENT + if (!CLHL_AnimateViewEntity(view)) +#endif + view->framestate.g[FS_REG].frame[0] = view_message?view_message->weaponframe:0; #ifdef SWQUAKE view->palremap = D_IdentityRemap(); #endif diff --git a/engine/client/wad.h b/engine/client/wad.h index b01900e68..3cef5968f 100644 --- a/engine/client/wad.h +++ b/engine/client/wad.h @@ -43,6 +43,14 @@ typedef struct qbyte data[4]; // variably sized } qpic_t; +#ifdef RGLQUAKE +typedef struct +{ + int texnum; + float sl, tl, sh, th; +} glpic_t; +#endif + //this is what's actually used. #define MPIC_ALPHA 1 typedef struct //use this so we don't have to go slow over pics, and don't have to shift too much data around. @@ -51,7 +59,16 @@ typedef struct //use this so we don't have to go slow over pics, and don't have unsigned short height; qbyte flags; qbyte pad; - qbyte data[4]; // variably sized + + union { + int dummy; +#ifdef RGLQUAKE + glpic_t gl; +#endif +#ifdef SWQUAKE + qbyte data[4]; // variably sized +#endif + } d; } mpic_t; diff --git a/engine/client/winquake.h b/engine/client/winquake.h index 2fd7b442a..a394f3712 100644 --- a/engine/client/winquake.h +++ b/engine/client/winquake.h @@ -62,6 +62,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern HINSTANCE global_hInstance; extern int global_nCmdShow; +extern HWND sys_hijackwindow; + #ifndef SERVERONLY #ifdef _WIN32 @@ -151,10 +153,7 @@ extern qboolean ActiveApp, Minimized; extern qboolean WinNT; -void IN_ShowMouse (void); -void IN_DeactivateMouse (void); -void IN_HideMouse (void); -void IN_ActivateMouse (void); +void IN_UpdateGrabs(int fullscreen, int activeapp); void IN_RestoreOriginalMouseState (void); void IN_SetQuakeMouseState (void); void IN_MouseEvent (int mstate); diff --git a/engine/client/winquake.rc b/engine/client/winquake.rc index ff5cf28c4..b90d25d26 100644 --- a/engine/client/winquake.rc +++ b/engine/client/winquake.rc @@ -56,7 +56,7 @@ IDD_DIALOG1 DIALOGEX 0, 0, 67, 40 STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE -FONT 16, "Times New Roman" +FONT 16, "Times New Roman", 0, 0, 0x1 BEGIN CTEXT "FTE QuakeWorld",IDC_STATIC,0,0,67,21,SS_CENTERIMAGE CTEXT "http://www.fteqw.com",IDC_STATIC,0,23,66,17, diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index df34189f7..a857cff26 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -3184,7 +3184,7 @@ qbool TP_CheckSoundTrigger (char *str) // clean up the message strcpy (str + j, str + i); - if (!snd_initialized) + if (!S_HaveOutput()) return false; COM_DefaultExtension (soundname, ".wav", sizeof(soundname)); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 2ffe842f0..30f33a84d 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -198,11 +198,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef USE_D3D #endif +#ifdef NPQTV + #undef TEXTEDITOR + #undef WEBCLIENT + #undef WEBSERVER +#endif #ifdef SERVERONLY //remove options that don't make sense on only a server #undef Q2CLIENT #undef Q3CLIENT #undef HLCLIENT + #undef HALFLIFEMODELS #undef VM_UI #undef VM_CG #undef WEBCLIENT diff --git a/engine/common/cmd.c b/engine/common/cmd.c index b4dc3a739..e71292cbd 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -74,12 +74,22 @@ static int macro_count = 0; void Cmd_AddMacro(char *s, char *(*f)(void), int disputableintentions) { - if (macro_count == MAX_MACROS) + int i; + for (i = 0; i < macro_count; i++) + { + if (!strcmp(macro_commands[i].name, s)) + break; + } + + if (i == MAX_MACROS) Sys_Error("Cmd_AddMacro: macro_count == MAX_MACROS"); + Q_strncpyz(macro_commands[macro_count].name, s, sizeof(macro_commands[macro_count].name)); macro_commands[macro_count].func = f; macro_commands[macro_count].disputableintentions = disputableintentions; - macro_count++; + + if (i == macro_count) + macro_count++; } char *TP_MacroString (char *s, int *len) @@ -1482,7 +1492,10 @@ qboolean Cmd_AddRemCommand (char *cmd_name, xcommand_t function) if (cmd->function == function) //happens a lot with q3 Con_DPrintf ("Cmd_AddCommand: %s already defined\n", cmd_name); else + { Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); + break; + } return false; } } @@ -2812,6 +2825,17 @@ void Cmd_Condump_f(void) } #endif +void Cmd_Shutdown(void) +{ + //make sure we get no other execution + int level; + for (level = 0; level < sizeof(cmd_text)/sizeof(cmd_text[0]); level++) + SZ_Clear (&cmd_text[level].buf); + + cmd_functions = NULL; + cmd_alias = NULL; +} + /* ============ Cmd_Init diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index db185b4e1..1e611324b 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1126,10 +1126,10 @@ void Mod_FloodFillSkin( qbyte *skin, int skinwidth, int skinheight ) #endif //additional skin loading -char **skinfilelist; +char ** skinfilelist; int skinfilecount; -static qboolean VARGS Mod_TryAddSkin(char *skinname, ...) +static qboolean VARGS Mod_TryAddSkin(const char *skinname, ...) { va_list argptr; char string[MAX_QPATH]; @@ -1159,7 +1159,7 @@ static qboolean VARGS Mod_TryAddSkin(char *skinname, ...) return true; } -int Mod_EnumerateSkins(char *name, int size, void *param) +int Mod_EnumerateSkins(const char *name, int size, void *param) { Mod_TryAddSkin(name); return true; @@ -2330,8 +2330,6 @@ qboolean Mod_LoadQ2Model (model_t *mod, void *buffer) - - int Mod_GetNumBones(model_t *model, qboolean allowtags) { galiasinfo_t *inf; @@ -2608,7 +2606,13 @@ int Mod_TagNumForName(model_t *model, char *name) galiasinfo_t *inf; md3tag_t *t; - if (!model || model->type != mod_alias) + if (!model) + return 0; +#ifdef HALFLIFEMODELS + if (model->type == mod_halflife) + return HLMod_BoneForName(model, name); +#endif + if (model->type != mod_alias) return 0; inf = Mod_Extradata(model); @@ -2634,6 +2638,32 @@ int Mod_TagNumForName(model_t *model, char *name) return 0; } #ifndef SERVERONLY +int Mod_FrameNumForName(model_t *model, char *name) +{ + galiasgroup_t *group; + galiasinfo_t *inf; + int i; + + if (!model) + return -1; +#ifdef HALFLIFEMODELS + if (model->type == mod_halflife) + return HLMod_FrameForName(model, name); +#endif + if (model->type != mod_alias) + return 0; + + inf = Mod_Extradata(model); + + for (i = 0; i < model->numframes; i++) + { + group = (galiasgroup_t*)((char*)inf + inf->groupofs); + if (!strcmp(group->name, name)) + return i; + } + return -1; +} + int Mod_SkinNumForName(model_t *model, char *name) { int i; diff --git a/engine/common/common.c b/engine/common/common.c index 58a760a25..e8a706501 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -38,15 +38,16 @@ usercmd_t nullcmd; // guarenteed to be zero entity_state_t nullentitystate; //this is the default state -static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1]; +static const char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1]; static char *argvdummy = " "; static char *safeargvs[NUM_SAFE_ARGVS] = {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"}; cvar_t registered = SCVAR("registered","0"); -cvar_t gameversion = SCVAR("gameversion","0"); +cvar_t gameversion = SCVARF("gameversion","", CVAR_SERVERINFO); cvar_t com_gamename = SCVAR("com_gamename", ""); +cvar_t com_modname = SCVAR("com_modname", ""); qboolean com_modified; // set true if using non-id files @@ -342,9 +343,9 @@ char *Q_strlwr(char *s) return ret; } -int wildcmp(char *wild, char *string) +int wildcmp(const char *wild, const char *string) { - char *cp=NULL, *mp=NULL; + const char *cp=NULL, *mp=NULL; while ((*string) && (*wild != '*')) { @@ -434,7 +435,7 @@ void Q_ftoa(char *str, float in) } } -int Q_atoi (char *str) +int Q_atoi (const char *str) { int val; int sign; @@ -493,7 +494,7 @@ int Q_atoi (char *str) } -float Q_atof (char *str) +float Q_atof (const char *str) { double val; int sign; @@ -1429,9 +1430,9 @@ void SZ_Print (sizebuf_t *buf, const char *data) COM_SkipPath ============ */ -char *COM_SkipPath (char *pathname) +char *COM_SkipPath (const char *pathname) { - char *last; + const char *last; last = pathname; while (*pathname) @@ -1440,7 +1441,7 @@ char *COM_SkipPath (char *pathname) last = pathname+1; pathname++; } - return last; + return (char *)last; } /* @@ -1448,11 +1449,11 @@ char *COM_SkipPath (char *pathname) COM_StripExtension ============ */ -void COM_StripExtension (char *in, char *out, int outlen) +void COM_StripExtension (const char *in, char *out, int outlen) { char *s; - if (out != in) + if (out != in) //optimisation, most calls use the same buffer Q_strncpyz(out, in, outlen); s = out+strlen(out); @@ -1494,7 +1495,7 @@ void COM_StripAllExtensions (char *in, char *out, int outlen) COM_FileExtension ============ */ -char *COM_FileExtension (char *in) +char *COM_FileExtension (const char *in) { static char exten[8]; int i; @@ -1565,9 +1566,9 @@ void COM_CleanUpPath(char *str) COM_FileBase ============ */ -void COM_FileBase (char *in, char *out, int outlen) +void COM_FileBase (const char *in, char *out, int outlen) { - char *s, *s2; + const char *s, *s2; s = in + strlen(in) - 1; @@ -1901,7 +1902,7 @@ messedup: #define TOKENSIZE sizeof(com_token) char com_token[TOKENSIZE]; int com_argc; -char **com_argv; +const char **com_argv; com_tokentype_t com_tokentype; @@ -1913,7 +1914,8 @@ COM_Parse Parse a token out of a string ============== */ -char *COM_Parse (char *data) +#ifndef COM_Parse +char *COM_Parse (const char *data) { int c; int len; @@ -1952,13 +1954,13 @@ skipwhite: while (1) { if (len >= TOKENSIZE-1) - return data; + return (char*)data; c = *data++; if (c=='\"' || !c) { com_token[len] = 0; - return data; + return (char*)data; } com_token[len] = c; len++; @@ -1969,7 +1971,7 @@ skipwhite: do { if (len >= TOKENSIZE-1) - return data; + return (char*)data; com_token[len] = c; data++; @@ -1978,10 +1980,11 @@ skipwhite: } while (c>32); com_token[len] = 0; - return data; + return (char*)data; } +#endif -char *COM_ParseStringSet (char *data) +char *COM_ParseStringSet (const char *data) { int c; int len; @@ -2004,7 +2007,10 @@ char *COM_ParseStringSet (char *data) do { if (len >= TOKENSIZE-1) - return data; + { + com_token[len] = 0; + return (char*)data; + } com_token[len] = c; data++; @@ -2013,11 +2019,11 @@ char *COM_ParseStringSet (char *data) } while (c>32 && c != ';'); com_token[len] = 0; - return data; + return (char*)data; } -char *COM_ParseOut (char *data, char *out, int outlen) +char *COM_ParseOut (const char *data, char *out, int outlen) { int c; int len; @@ -2056,13 +2062,16 @@ skipwhite: while (1) { if (len >= outlen-1) - return data; + { + out[len] = 0; + return (char*)data; + } c = *data++; if (c=='\"' || !c) { out[len] = 0; - return data; + return (char*)data; } out[len] = c; len++; @@ -2073,7 +2082,10 @@ skipwhite: do { if (len >= outlen-1) - return data; + { + out[len] = 0; + return (char*)data; + } out[len] = c; data++; @@ -2082,11 +2094,11 @@ skipwhite: } while (c>32); out[len] = 0; - return data; + return (char*)data; } //same as COM_Parse, but parses two quotes next to each other as a single quote as part of the string -char *COM_StringParse (char *data, qboolean expandmacros, qboolean qctokenize) +char *COM_StringParse (const char *data, qboolean expandmacros, qboolean qctokenize) { int c; int len; @@ -2144,7 +2156,7 @@ skipwhite: if (len >= TOKENSIZE-1) { com_token[len] = '\0'; - return data; + return (char*)data; } @@ -2155,7 +2167,7 @@ skipwhite: if (c!='\"') { com_token[len] = 0; - return data; + return (char*)data; } while (c=='\"') { @@ -2168,7 +2180,7 @@ skipwhite: if (!c) { com_token[len] = 0; - return data; + return (char*)data; } com_token[len] = c; len++; @@ -2184,7 +2196,7 @@ skipwhite: if (len >= TOKENSIZE-1) { com_token[len] = '\0'; - return data; + return (char*)data; } @@ -2195,7 +2207,7 @@ skipwhite: if (c!='\'') { com_token[len] = 0; - return data; + return (char*)data; } while (c=='\'') { @@ -2208,7 +2220,7 @@ skipwhite: if (!c) { com_token[len] = 0; - return data; + return (char*)data; } com_token[len] = c; len++; @@ -2220,7 +2232,7 @@ skipwhite: // single character com_token[len++] = c; com_token[len] = 0; - return data+1; + return (char*)data+1; } // parse a regular word @@ -2229,7 +2241,7 @@ skipwhite: if (len >= TOKENSIZE-1) { com_token[len] = '\0'; - return data; + return (char*)data; } com_token[len] = c; @@ -2241,7 +2253,7 @@ skipwhite: com_token[len] = 0; if (!expandmacros) - return data; + return (char*)data; //now we check for macros. for (s = com_token, c= 0; c < len; c++, s++) //this isn't a quoted token by the way. @@ -2267,7 +2279,7 @@ skipwhite: if (len+strlen(macro->string)-(i+1) >= TOKENSIZE-1) //give up. { com_token[len] = '\0'; - return data; + return (char*)data; } memmove(s+strlen(macro->string), s+i+1, len-c-i); memcpy(s, macro->string, strlen(macro->string)); @@ -2277,7 +2289,7 @@ skipwhite: } } - return data; + return (char*)data; } #define DEFAULT_PUNCTUATION "(,{})(\':;=!><&|+" @@ -2396,7 +2408,7 @@ skipwhite: return (char*)data; } -char *COM_ParseCString (char *data) +char *COM_ParseCString (const char *data) { int c; int len; @@ -2437,14 +2449,14 @@ skipwhite: if (len >= TOKENSIZE-2) { com_token[len] = '\0'; - return data; + return (char*)data; } c = *data++; if (!c) { com_token[len] = 0; - return data; + return (char*)data; } if (c == '\\') { @@ -2464,13 +2476,13 @@ skipwhite: continue; default: com_token[len] = 0; - return data; + return (char*)data; } } if (c=='\"' || !c) { com_token[len] = 0; - return data; + return (char*)data; } com_token[len] = c; len++; @@ -2489,7 +2501,7 @@ skipwhite: } while (c>32); com_token[len] = 0; - return data; + return (char*)data; } @@ -2502,7 +2514,7 @@ where the given parameter apears, or 0 if not present ================ */ -int COM_CheckNextParm (char *parm, int last) +int COM_CheckNextParm (const char *parm, int last) { int i = last+1; @@ -2517,7 +2529,7 @@ int COM_CheckNextParm (char *parm, int last) return 0; } -int COM_CheckParm (char *parm) +int COM_CheckParm (const char *parm) { return COM_CheckNextParm(parm, 0); } @@ -2607,7 +2619,7 @@ void COM_CheckRegistered (void) COM_InitArgv ================ */ -void COM_InitArgv (int argc, char **argv) //not allowed to tprint +void COM_InitArgv (int argc, const char **argv) //not allowed to tprint { qboolean safe; int i; @@ -2685,7 +2697,7 @@ COM_AddParm Adds the given string at the end of the current argument list ================ */ -void COM_AddParm (char *parm) +void COM_AddParm (const char *parm) { largv[com_argc++] = parm; } @@ -2920,7 +2932,7 @@ void COM_Effectinfo_Reload(void) } } -unsigned int COM_Effectinfo_ForName(char *efname) +unsigned int COM_Effectinfo_ForName(const char *efname) { struct effectinfo_s *e; diff --git a/engine/common/common.h b/engine/common/common.h index 7f3f407b6..a19d750fa 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -170,11 +170,11 @@ void MSG_ReadData (void *data, int len); //============================================================================ -char *Q_strcpyline(char *out, char *in, int maxlen); //stops at '\n' (and '\r') +char *Q_strcpyline(char *out, const char *in, int maxlen); //stops at '\n' (and '\r') void Q_ftoa(char *str, float in); char *Q_strlwr(char *str); -int wildcmp(char *wild, char *string); //1 if match +int wildcmp(const char *wild, const char *string); //1 if match #define Q_memset(d, f, c) memset((d), (f), (c)) #define Q_memcpy(d, s, c) memcpy((d), (s), (c)) @@ -220,8 +220,8 @@ void Q_strncpyz(char*d, const char*s, int n); #endif -int Q_atoi (char *str); -float Q_atof (char *str); +int Q_atoi (const char *str); +float Q_atof (const char *str); @@ -234,34 +234,37 @@ extern com_tokentype_t com_tokentype; extern qboolean com_eof; -char *COM_Parse (char *data); -char *COM_ParseStringSet (char *data); -char *COM_ParseCString (char *data); -char *COM_StringParse (char *data, qboolean expandmacros, qboolean qctokenize); +//these cast away the const for the return value. +//char *COM_Parse (const char *data); +#define COM_Parse(d) COM_ParseOut(d,com_token, sizeof(com_token)) +char *COM_ParseOut (const char *data, char *out, int outlen); +char *COM_ParseStringSet (const char *data); +char *COM_ParseCString (const char *data); +char *COM_StringParse (const char *data, qboolean expandmacros, qboolean qctokenize); char *COM_ParseToken (const char *data, const char *punctuation); char *COM_TrimString(char *str); extern int com_argc; -extern char **com_argv; +extern const char **com_argv; -int COM_CheckParm (char *parm); -int COM_CheckNextParm (char *parm, int last); -void COM_AddParm (char *parm); +int COM_CheckParm (const char *parm); +int COM_CheckNextParm (const char *parm, int last); +void COM_AddParm (const char *parm); void COM_Init (void); -void COM_InitArgv (int argc, char **argv); +void COM_InitArgv (int argc, const char **argv); void COM_ParsePlusSets (void); -char *COM_SkipPath (char *pathname); -void COM_StripExtension (char *in, char *out, int outlen); -void COM_FileBase (char *in, char *out, int outlen); -int COM_FileSize(char *path); +char *COM_SkipPath (const char *pathname); +void COM_StripExtension (const char *in, char *out, int outlen); +void COM_FileBase (const char *in, char *out, int outlen); +int COM_FileSize(const char *path); void COM_DefaultExtension (char *path, char *extension, int maxlen); void COM_DeFunString(unsigned long *str, char *out, int outsize, qboolean ignoreflags); void COM_ParseFunString(char *str, unsigned long *out, int outsize); int COM_FunStringLength(unsigned char *str); -char *COM_FileExtension (char *in); +char *COM_FileExtension (const char *in); void COM_CleanUpPath(char *str); char *VARGS va(char *format, ...); @@ -273,7 +276,6 @@ extern qboolean com_file_copyprotected; extern int com_filesize; struct cache_user_s; -extern char com_gamedir[MAX_OSPATH]; extern char com_quakedir[MAX_OSPATH]; extern char com_homedir[MAX_OSPATH]; extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in @@ -294,15 +296,15 @@ struct vfsfile_s; typedef enum {FSLFRT_IFFOUND, FSLFRT_LENGTH, FSLFRT_DEPTH_OSONLY, FSLFRT_DEPTH_ANYPATH} FSLF_ReturnType_e; //if loc is valid, loc->search is always filled in, the others are filled on success. //returns -1 if couldn't find. -int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *loc); +int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation_t *loc); struct vfsfile_s *FS_OpenReadLocation(flocation_t *location); char *FS_WhichPackForLocation(flocation_t *loc); char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly); char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly); -int COM_FOpenFile (char *filename, FILE **file); -int COM_FOpenWriteFile (char *filename, FILE **file); +int COM_FOpenFile (const char *filename, FILE **file); +int COM_FOpenWriteFile (const char *filename, FILE **file); //#ifdef _MSC_VER //this is enough to annoy me, without conflicting with other (more bizzare) platforms. //#define fopen dont_use_fopen @@ -316,7 +318,7 @@ void COM_CloseFile (FILE *h); typedef struct vfsfile_s { int (*ReadBytes) (struct vfsfile_s *file, void *buffer, int bytestoread); - int (*WriteBytes) (struct vfsfile_s *file, void *buffer, int bytestoread); + int (*WriteBytes) (struct vfsfile_s *file, const void *buffer, int bytestoread); qboolean (*Seek) (struct vfsfile_s *file, unsigned long pos); //returns false for error unsigned long (*Tell) (struct vfsfile_s *file); unsigned long (*GetLen) (struct vfsfile_s *file); //could give some lag @@ -332,54 +334,58 @@ typedef struct vfsfile_s { #define VFS_READ(vf,buffer,buflen) (vf->ReadBytes(vf,buffer,buflen)) #define VFS_WRITE(vf,buffer,buflen) (vf->WriteBytes(vf,buffer,buflen)) #define VFS_FLUSH(vf) do{if(vf->Flush)vf->Flush(vf);}while(0) +#define VFS_PUTS(vf,s) do{const char *t=s;vf->WriteBytes(vf,t,strlen(t));}while(0) char *VFS_GETS(vfsfile_t *vf, char *buffer, int buflen); +void VFS_PRINTF(vfsfile_t *vf, char *fmt, ...); + +enum fs_relative{ + FS_GAME, //standard search (not generally valid for save/rename/delete/etc) + FS_ROOT, //./ + FS_GAMEONLY, //$gamedir/ + FS_CONFIGONLY, //fte/ (should still be part of the game path) + FS_SKINS //qw/skins/ +}; void FS_FlushFSHash(void); -void FS_CreatePath(char *pname, int relativeto); -int FS_Rename(char *oldf, char *newf, int relativeto); //0 on success, non-0 on error -int FS_Rename2(char *oldf, char *newf, int oldrelativeto, int newrelativeto); -int FS_Remove(char *fname, int relativeto); //0 on success, non-0 on error -qboolean FS_WriteFile (char *filename, void *data, int len, int relativeto); -vfsfile_t *FS_OpenVFS(char *filename, char *mode, int relativeto); +void FS_CreatePath(const char *pname, enum fs_relative relativeto); +int FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto); //0 on success, non-0 on error +int FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto); +int FS_Remove(const char *fname, int relativeto); //0 on success, non-0 on error +qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out, int outlen); //if you really need to fopen yourself +qboolean FS_WriteFile (const char *filename, const void *data, int len, enum fs_relative relativeto); +vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto); vfsfile_t *FS_OpenTemp(void); -vfsfile_t *FS_OpenTCP(char *name); +vfsfile_t *FS_OpenTCP(const char *name); void FS_UnloadPackFiles(void); void FS_ReloadPackFiles(void); -char *FS_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum); -enum { - FS_GAME, - FS_ROOT, - FS_GAMEONLY, - FS_CONFIGONLY, - FS_SKINS -}; +char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum); int COM_filelength (FILE *f); -qbyte *COM_LoadStackFile (char *path, void *buffer, int bufsize); -qbyte *COM_LoadTempFile (char *path); -qbyte *COM_LoadTempFile2 (char *path); //allocates a little bit more without freeing old temp -qbyte *COM_LoadHunkFile (char *path); -qbyte *COM_LoadMallocFile (char *path); -void COM_LoadCacheFile (char *path, struct cache_user_s *cu); +qbyte *COM_LoadStackFile (const char *path, void *buffer, int bufsize); +qbyte *COM_LoadTempFile (const char *path); +qbyte *COM_LoadTempFile2 (const char *path); //allocates a little bit more without freeing old temp +qbyte *COM_LoadHunkFile (const char *path); +qbyte *COM_LoadMallocFile (const char *path); +void COM_LoadCacheFile (const char *path, struct cache_user_s *cu); void COM_CreatePath (char *path); -void COM_Gamedir (char *dir); -void FS_ForceToPure(char *str, char *crcs, int seed); +void COM_Gamedir (const char *dir); +void FS_ForceToPure(const char *str, const char *crcs, int seed); char *COM_GetPathInfo (int i, int *crc); char *COM_NextPath (char *prevpath); void COM_FlushFSCache(void); //a file was written using fopen void COM_RefreshFSCache_f(void); -qboolean COM_LoadMapPackFile(char *name, int offset); +qboolean COM_LoadMapPackFile(const char *name, int offset); void COM_FlushTempoaryPacks(void); -void COM_EnumerateFiles (char *match, int (*func)(char *, int, void *), void *parm); +void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *), void *parm); extern struct cvar_s registered; extern qboolean standard_quake; //fixme: remove void COM_Effectinfo_Clear(void); -unsigned int COM_Effectinfo_ForName(char *efname); +unsigned int COM_Effectinfo_ForName(const char *efname); char *COM_Effectinfo_ForNumber(unsigned int efnum); #define MAX_INFO_KEY 64 diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 20bd2866a..c2b5210ea 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -26,15 +26,18 @@ cvar_group_t *cvar_groups; //cvar_t *cvar_vars; static char *cvar_null_string = ""; static char *cvar_zero_string = "0"; +static char *cvar_one_string = "1"; char *Cvar_DefaultAlloc(char *str) { char *c; - + if (str[0] == '\0') return cvar_null_string; if (str[0] == '0' && str[1] == '\0') return cvar_zero_string; + if (str[0] == '1' && str[1] == '\0') + return cvar_one_string; c = (char *)Z_Malloc(strlen(str)+1); Q_strcpy(c, str); @@ -48,6 +51,8 @@ void Cvar_DefaultFree(char *str) return; else if (str == cvar_zero_string) return; + else if (str == cvar_one_string) + return; else Z_Free(str); } @@ -868,7 +873,8 @@ void Cvar_Free(cvar_t *tbf) } unlinked: Z_Free(tbf->string); - Cvar_DefaultFree(tbf->defaultstr); + if (tbf->flags & CVAR_FREEDEFAULT) + Cvar_DefaultFree(tbf->defaultstr); if (tbf->latched_string) Z_Free(tbf->latched_string); Z_Free(tbf); @@ -886,10 +892,12 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname) { cvar_t *old; cvar_group_t *group; - char value[512]; + char *initial; -// copy the value off, because future sets will Z_Free it - strcpy (value, variable->string); + if (variable->defaultstr) + initial = variable->defaultstr; + else + initial = variable->string; // check to see if it has already been defined old = Cvar_FindVar (variable->name); @@ -900,7 +908,7 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname) group = Cvar_GetGroup(groupname); variable->modified = old->modified; - variable->flags |= old->flags & CVAR_ARCHIVE; + variable->flags |= (old->flags & CVAR_ARCHIVE); // link the variable in variable->next = group->cvars; @@ -911,7 +919,10 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname) variable->string = (char*)Z_Malloc (1); //cheat prevention - engine set default is the one that stays. - variable->defaultstr = Cvar_DefaultAlloc(value); //give it it's default (for server controlled vars and things) + if (variable->flags & CVAR_FREEDEFAULT) + variable->defaultstr = Cvar_DefaultAlloc(initial); + else + variable->defaultstr = initial; // set it through the function to be consistant if (old->latched_string) @@ -943,19 +954,17 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname) variable->string = (char*)Z_Malloc (1); - variable->defaultstr = Cvar_DefaultAlloc(value); //give it it's default (for server controlled vars and things) + if (variable->flags & CVAR_FREEDEFAULT) + variable->defaultstr = Cvar_DefaultAlloc(initial); + else + variable->defaultstr = initial; // set it through the function to be consistant - Cvar_SetCore (variable, value, true); + Cvar_SetCore (variable, initial, true); return true; } -/* -void Cvar_RegisterVariable (cvar_t *variable) -{ - Cvar_Register(variable, NULL); -} -*/ + cvar_t *Cvar_Get(const char *name, const char *defaultvalue, int flags, const char *group) { cvar_t *var; @@ -979,7 +988,7 @@ cvar_t *Cvar_Get(const char *name, const char *defaultvalue, int flags, const ch var->name = (char *)(var+1); strcpy(var->name, name); var->string = (char*)defaultvalue; - var->flags = flags|CVAR_POINTER|CVAR_USERCREATED; + var->flags = flags|CVAR_POINTER|CVAR_FREEDEFAULT|CVAR_USERCREATED; if (!Cvar_Register(var, group)) return NULL; @@ -1203,9 +1212,16 @@ void Cvar_Shutdown(void) var = cvar_groups->cvars; cvar_groups->cvars = var->next; + if (var->flags & CVAR_FREEDEFAULT) + { + Cvar_DefaultFree(var->defaultstr); + var->defaultstr = NULL; + } Z_Free(var->string); if (var->flags & CVAR_POINTER) Z_Free(var); + else + var->string = NULL; } grp = cvar_groups; diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 30c327851..ca5ee805e 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -103,17 +103,18 @@ typedef struct cvar_group_s //freestyle #define CVAR_POINTER (1<<5) // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly. -#define CVAR_NOTFROMSERVER (1<<6) // the console will ignore changes to cvars if set at from the server or any gamecode. This is to protect against security flaws - like qterm -#define CVAR_USERCREATED (1<<7) //write a 'set' or 'seta' in front of the var name. -#define CVAR_CHEAT (1<<8) //latch to the default, unless cheats are enabled. -#define CVAR_SEMICHEAT (1<<9) //if strict ruleset, force to 0/blank. -#define CVAR_RENDERERLATCH (1<<10) //requires a vid_restart to reapply. -#define CVAR_SERVEROVERRIDE (1<<11) //the server has overridden out local value - should probably be called SERVERLATCH -#define CVAR_RENDERERCALLBACK (1<<12) //force callback for cvars on renderer change -#define CVAR_NOUNSAFEEXPAND (1<<13) // do not expand cvar value when command is from gamecode -#define CVAR_RULESETLATCH (1<<14) //latched by the ruleset +#define CVAR_FREEDEFAULT (1<<6) // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly. +#define CVAR_NOTFROMSERVER (1<<7) // the console will ignore changes to cvars if set at from the server or any gamecode. This is to protect against security flaws - like qterm +#define CVAR_USERCREATED (1<<8) //write a 'set' or 'seta' in front of the var name. +#define CVAR_CHEAT (1<<9) //latch to the default, unless cheats are enabled. +#define CVAR_SEMICHEAT (1<<10) //if strict ruleset, force to 0/blank. +#define CVAR_RENDERERLATCH (1<<11) //requires a vid_restart to reapply. +#define CVAR_SERVEROVERRIDE (1<<12) //the server has overridden out local value - should probably be called SERVERLATCH +#define CVAR_RENDERERCALLBACK (1<<13) //force callback for cvars on renderer change +#define CVAR_NOUNSAFEEXPAND (1<<14) // do not expand cvar value when command is from gamecode +#define CVAR_RULESETLATCH (1<<15) //latched by the ruleset -#define CVAR_LASTFLAG CVAR_NOUNSAFEEXPAND +#define CVAR_LASTFLAG CVAR_RULESETLATCH #define CVAR_LATCHMASK (CVAR_LATCH|CVAR_RENDERERLATCH|CVAR_SERVEROVERRIDE|CVAR_CHEAT|CVAR_SEMICHEAT) //you're only allowed one of these. #define CVAR_NEEDDEFAULT CVAR_CHEAT @@ -129,8 +130,6 @@ qboolean Cvar_Register (cvar_t *variable, const char *cvargroup); // registers a cvar that already has the name, string, and optionally the // archive elements set. -//#define Cvar_RegisterVariable(x) Cvar_Register(x,__FILE__); - cvar_t *Cvar_ForceSet (cvar_t *var, const char *value); cvar_t *Cvar_Set (cvar_t *var, const char *value); // equivelant to " " typed at the console diff --git a/engine/common/fs.c b/engine/common/fs.c index 5f0c74569..bd7e01d80 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -4,34 +4,52 @@ //#define com_gamedir com__gamedir #include +#include +#include +#include "fs.h" -#include "hash.h" hashtable_t filesystemhash; qboolean com_fschanged = true; extern cvar_t com_fs_cache; int active_fs_cachetype; +struct +{ + const char *extension; + searchpathfuncs_t *funcs; +} searchpathformats[64]; +int FS_RegisterFileSystemType(const char *extension, searchpathfuncs_t *funcs) +{ + unsigned int i; + for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + { + if (searchpathformats[i].extension && !strcmp(searchpathformats[i].extension, extension)) + break; //extension match always replaces + if (!searchpathformats[i].extension && !searchpathformats[i].funcs) + break; + } + if (i == sizeof(searchpathformats)/sizeof(searchpathformats[0])) + return 0; + searchpathformats[i].extension = extension; + searchpathformats[i].funcs = funcs; + com_fschanged = true; + return i+1; +} -typedef struct { - void (*PrintPath)(void *handle); - void (*ClosePath)(void *handle); - void (*BuildHash)(void *handle); - qboolean (*FindFile)(void *handle, flocation_t *loc, char *name, void *hashedresult); //true if found (hashedresult can be NULL) - //note that if rawfile and offset are set, many Com_FileOpens will read the raw file - //otherwise ReadFile will be called instead. - void (*ReadFile)(void *handle, flocation_t *loc, char *buffer); //reads the entire file - int (*EnumerateFiles)(void *handle, char *match, int (*func)(char *, int, void *), void *parm); +void FS_UnRegisterFileSystemType(int idx) +{ + if ((unsigned int)(idx-1) >= sizeof(searchpathformats)/sizeof(searchpathformats[0])) + return; - void *(*OpenNew)(vfsfile_t *file, char *desc); //returns a handle to a new pak/path + searchpathformats[idx-1].funcs = NULL; + com_fschanged = true; - int (*GeneratePureCRC) (void *handle, int seed, int usepure); - - vfsfile_t *(*OpenVFS)(void *handle, flocation_t *loc, char *mode); -} searchpathfuncs_t; + //FS_Restart will be needed +} vfsfile_t *FS_OpenVFSLoc(flocation_t *loc, char *mode); @@ -65,6 +83,17 @@ char *VFS_GETS(vfsfile_t *vf, char *buffer, int buflen) return buffer; } +void VFS_PRINTF(vfsfile_t *vf, char *format, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr, format); + vsnprintf (string,sizeof(string)-1, format,argptr); + va_end (argptr); + + VFS_PUTS(vf, string); +} @@ -81,60 +110,6 @@ int com_filesize; qboolean com_file_copyprotected; -// -// in memory -// - -typedef struct -{ - char name[MAX_QPATH]; - int filepos, filelen; - - bucket_t bucket; -} packfile_t; - -typedef struct pack_s -{ - char descname[MAX_OSPATH]; - vfsfile_t *handle; - unsigned int filepos; //the pos the subfiles left it at (to optimize calls to vfs_seek) - int numfiles; - packfile_t *files; - int references; //seeing as all vfiles from a pak file use the parent's vfsfile, we need to keep the parent open until all subfiles are closed. -} pack_t; - -// -// on disk -// -typedef struct -{ - char name[56]; - int filepos, filelen; -} dpackfile_t; - -typedef struct -{ - int filepos, filelen; - char name[8]; -} dwadfile_t; - -typedef struct -{ - char id[4]; - int dirofs; - int dirlen; -} dpackheader_t; - -typedef struct -{ - char id[4]; - int dirlen; - int dirofs; -} dwadheader_t; - -#define MAX_FILES_IN_PACK 2048 - -char com_gamedir[MAX_OSPATH]; //the os path where we write files //char *com_basedir; //obsolete char com_quakedir[MAX_OSPATH]; @@ -152,9 +127,8 @@ int fs_hash_files; static int COM_FileOpenRead (char *path, FILE **hndl); -qboolean Sys_PathProtection(char *pattern); - - +static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen); +void FS_RegisterDefaultFileSystems(void); #define ENFORCEFOPENMODE(mode) {if (strcmp(mode, "r") && strcmp(mode, "w")/* && strcmp(mode, "rw")*/)Sys_Error("fs mode %s is not permitted here\n");} @@ -164,1157 +138,6 @@ qboolean Sys_PathProtection(char *pattern); -//====================================================================================================== -//STDIO files (OS) - -typedef struct { - vfsfile_t funcs; - FILE *handle; -} vfsosfile_t; -int VFSOS_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) -{ - vfsosfile_t *intfile = (vfsosfile_t*)file; - return fread(buffer, 1, bytestoread, intfile->handle); -} -int VFSOS_WriteBytes (struct vfsfile_s *file, void *buffer, int bytestoread) -{ - vfsosfile_t *intfile = (vfsosfile_t*)file; - return fwrite(buffer, 1, bytestoread, intfile->handle); -} -qboolean VFSOS_Seek (struct vfsfile_s *file, unsigned long pos) -{ - vfsosfile_t *intfile = (vfsosfile_t*)file; - return fseek(intfile->handle, pos, SEEK_SET) == 0; -} -unsigned long VFSOS_Tell (struct vfsfile_s *file) -{ - vfsosfile_t *intfile = (vfsosfile_t*)file; - return ftell(intfile->handle); -} -unsigned long VFSOS_GetSize (struct vfsfile_s *file) -{ - vfsosfile_t *intfile = (vfsosfile_t*)file; - - unsigned int curpos; - unsigned int maxlen; - curpos = ftell(intfile->handle); - fseek(intfile->handle, 0, SEEK_END); - maxlen = ftell(intfile->handle); - fseek(intfile->handle, curpos, SEEK_SET); - - return maxlen; -} -void VFSOS_Close(vfsfile_t *file) -{ - vfsosfile_t *intfile = (vfsosfile_t*)file; - fclose(intfile->handle); - Z_Free(file); -} - -vfsfile_t *FS_OpenTemp(void) -{ - FILE *f; - vfsosfile_t *file; - - f = tmpfile(); - if (!f) - return NULL; - - file = Z_Malloc(sizeof(vfsosfile_t)); - file->funcs.ReadBytes = VFSOS_ReadBytes; - file->funcs.WriteBytes = VFSOS_WriteBytes; - file->funcs.Seek = VFSOS_Seek; - file->funcs.Tell = VFSOS_Tell; - file->funcs.GetLen = VFSOS_GetSize; - file->funcs.Close = VFSOS_Close; - file->handle = f; - - return (vfsfile_t*)file; -} - -vfsfile_t *VFSOS_Open(char *osname, char *mode) -{ - FILE *f; - vfsosfile_t *file; - qboolean read = !!strchr(mode, 'r'); - qboolean write = !!strchr(mode, 'w'); - qboolean append = !!strchr(mode, 'a'); - qboolean text = !!strchr(mode, 't'); - char newmode[3]; - int modec = 0; - - if (read) - newmode[modec++] = 'r'; - if (write) - newmode[modec++] = 'w'; - if (append) - newmode[modec++] = 'a'; - if (text) - newmode[modec++] = 't'; - else - newmode[modec++] = 'b'; - newmode[modec++] = '\0'; - - f = fopen(osname, newmode); - if (!f) - return NULL; - - file = Z_Malloc(sizeof(vfsosfile_t)); - file->funcs.ReadBytes = strchr(mode, 'r')?VFSOS_ReadBytes:NULL; - file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSOS_WriteBytes:NULL; - file->funcs.Seek = VFSOS_Seek; - file->funcs.Tell = VFSOS_Tell; - file->funcs.GetLen = VFSOS_GetSize; - file->funcs.Close = VFSOS_Close; - file->handle = f; - - return (vfsfile_t*)file; -} - -vfsfile_t *FSOS_OpenVFS(void *handle, flocation_t *loc, char *mode) -{ - char diskname[MAX_OSPATH]; - - if (Sys_PathProtection(loc->rawname)) - return NULL; - - snprintf(diskname, sizeof(diskname), "%s/%s", (char*)handle, loc->rawname); - - return VFSOS_Open(diskname, mode); -} - -void FSOS_PrintPath(void *handle) -{ - Con_Printf("%s\n", handle); -} -void FSOS_ClosePath(void *handle) -{ - Z_Free(handle); -} -int FSOS_RebuildFSHash(char *filename, int filesize, void *data) -{ - if (filename[strlen(filename)-1] == '/') - { //this is actually a directory - - char childpath[256]; - sprintf(childpath, "%s*", filename); - Sys_EnumerateFiles((char*)data, childpath, FSOS_RebuildFSHash, data); - return true; - } - if (!Hash_GetInsensative(&filesystemhash, filename)) - { - bucket_t *bucket = (bucket_t*)BZ_Malloc(sizeof(bucket_t) + strlen(filename)+1); - strcpy((char *)(bucket+1), filename); -#ifdef _WIN32 - Q_strlwr((char *)(bucket+1)); -#endif - Hash_AddInsensative(&filesystemhash, (char *)(bucket+1), data, bucket); - - fs_hash_files++; - } - else - fs_hash_dups++; - return true; -} -void FSOS_BuildHash(void *handle) -{ - Sys_EnumerateFiles(handle, "*", FSOS_RebuildFSHash, handle); -} -qboolean FSOS_FLocate(void *handle, flocation_t *loc, char *filename, void *hashedresult) -{ - FILE *f; - int len; - char netpath[MAX_OSPATH]; - - - if (hashedresult && (void *)hashedresult != handle) - return false; - -/* - if (!static_registered) - { // if not a registered version, don't ever go beyond base - if ( strchr (filename, '/') || strchr (filename,'\\')) - continue; - } -*/ - -// check a file in the directory tree - snprintf (netpath, sizeof(netpath)-1, "%s/%s",(char*)handle, filename); - - f = fopen(netpath, "rb"); - if (!f) - return false; - - fseek(f, 0, SEEK_END); - len = ftell(f); - fclose(f); - if (loc) - { - loc->len = len; - loc->offset = 0; - loc->index = 0; - Q_strncpyz(loc->rawname, filename, sizeof(loc->rawname)); - } - - return true; -} -void FSOS_ReadFile(void *handle, flocation_t *loc, char *buffer) -{ - FILE *f; - f = fopen(loc->rawname, "rb"); - if (!f) //err... - return; - fseek(f, loc->offset, SEEK_SET); - fread(buffer, 1, loc->len, f); - fclose(f); -} -int FSOS_EnumerateFiles (void *handle, char *match, int (*func)(char *, int, void *), void *parm) -{ - return Sys_EnumerateFiles(handle, match, func, parm); -} - -searchpathfuncs_t osfilefuncs = { - FSOS_PrintPath, - FSOS_ClosePath, - FSOS_BuildHash, - FSOS_FLocate, - FSOS_ReadFile, - FSOS_EnumerateFiles, - NULL, - NULL, - FSOS_OpenVFS -}; - - -//====================================================================================================== -//PACK files (*.pak) - -void FSPAK_PrintPath(void *handle) -{ - pack_t *pak = handle; - - if (pak->references != 1) - Con_Printf("%s (%i)\n", pak->descname, pak->references-1); - else - Con_Printf("%s\n", pak->descname); -} -void FSPAK_ClosePath(void *handle) -{ - pack_t *pak = handle; - - pak->references--; - if (pak->references > 0) - return; //not free yet - - - VFS_CLOSE (pak->handle); - if (pak->files) - Z_Free(pak->files); - Z_Free(pak); -} -void FSPAK_BuildHash(void *handle) -{ - pack_t *pak = handle; - int i; - - for (i = 0; i < pak->numfiles; i++) - { - if (!Hash_GetInsensative(&filesystemhash, pak->files[i].name)) - { - fs_hash_files++; - Hash_AddInsensative(&filesystemhash, pak->files[i].name, &pak->files[i], &pak->files[i].bucket); - } - else - fs_hash_dups++; - } -} -qboolean FSPAK_FLocate(void *handle, flocation_t *loc, char *filename, void *hashedresult) -{ - packfile_t *pf = hashedresult; - int i, len; - pack_t *pak = handle; - -// look through all the pak file elements - - if (pf) - { //is this a pointer to a file in this pak? - if (pf < pak->files || pf > pak->files + pak->numfiles) - return false; //was found in a different path - } - else - { - for (i=0 ; inumfiles ; i++) //look for the file - { - if (!strcmp (pak->files[i].name, filename)) - { - pf = &pak->files[i]; - break; - } - } - } - - if (pf) - { - len = pf->filelen; - if (loc) - { - loc->index = pf - pak->files; - snprintf(loc->rawname, sizeof(loc->rawname), "%s", pak->descname); - loc->offset = pf->filepos; - loc->len = pf->filelen; - } - return true; - } - return false; -} -int FSPAK_EnumerateFiles (void *handle, char *match, int (*func)(char *, int, void *), void *parm) -{ - pack_t *pak = handle; - int num; - - for (num = 0; num<(int)pak->numfiles; num++) - { - if (wildcmp(match, pak->files[num].name)) - { - if (!func(pak->files[num].name, pak->files[num].filelen, parm)) - return false; - } - } - - return true; -} -/* -================= -COM_LoadPackFile - -Takes an explicit (not game tree related) path to a pak file. - -Loads the header and directory, adding the files at the beginning -of the list so they override previous pack files. -================= -*/ -void *FSPAK_LoadPackFile (vfsfile_t *file, char *desc) -{ - dpackheader_t header; - int i; -// int j; - packfile_t *newfiles; - int numpackfiles; - pack_t *pack; - vfsfile_t *packhandle; - dpackfile_t info; - int read; -// unsigned short crc; - - packhandle = file; - if (packhandle == NULL) - return NULL; - - VFS_READ(packhandle, &header, sizeof(header)); - if (header.id[0] != 'P' || header.id[1] != 'A' - || header.id[2] != 'C' || header.id[3] != 'K') - { - return NULL; -// Sys_Error ("%s is not a packfile", packfile); - } - header.dirofs = LittleLong (header.dirofs); - header.dirlen = LittleLong (header.dirlen); - - numpackfiles = header.dirlen / sizeof(dpackfile_t); - -// if (numpackfiles > MAX_FILES_IN_PACK) -// Sys_Error ("%s has %i files", packfile, numpackfiles); - -// if (numpackfiles != PAK0_COUNT) -// com_modified = true; // not the original file - - newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t)); - - VFS_SEEK(packhandle, header.dirofs); -// fread (&info, 1, header.dirlen, packhandle); - -// crc the directory to check for modifications -// crc = QCRC_Block((qbyte *)info, header.dirlen); - - -// QCRC_Init (&crc); - - pack = (pack_t*)Z_Malloc (sizeof (pack_t)); -// parse the directory - for (i=0 ; idescname, desc); - pack->handle = packhandle; - pack->numfiles = numpackfiles; - pack->files = newfiles; - pack->filepos = 0; - VFS_SEEK(packhandle, pack->filepos); - - pack->references++; - - Con_TPrintf (TL_ADDEDPACKFILE, desc, numpackfiles); - return pack; -} - - -typedef struct { - vfsfile_t funcs; - pack_t *parentpak; - unsigned long startpos; - unsigned long length; - unsigned long currentpos; -} vfspack_t; -int VFSPAK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread) -{ - vfspack_t *vfsp = (vfspack_t*)vfs; - int read; - - if (bytestoread == 0) - return 0; - - if (vfsp->currentpos - vfsp->startpos + bytestoread > vfsp->length) - bytestoread = vfsp->length - (vfsp->currentpos - vfsp->startpos); - if (bytestoread <= 0) - { - return -1; - } - - if (vfsp->parentpak->filepos != vfsp->currentpos) - VFS_SEEK(vfsp->parentpak->handle, vfsp->currentpos); - read = VFS_READ(vfsp->parentpak->handle, buffer, bytestoread); - vfsp->currentpos += read; - vfsp->parentpak->filepos = vfsp->currentpos; - - return read; -} -int VFSPAK_WriteBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread) -{ //not supported. - Sys_Error("Cannot write to pak files\n"); - return 0; -} -qboolean VFSPAK_Seek (struct vfsfile_s *vfs, unsigned long pos) -{ - vfspack_t *vfsp = (vfspack_t*)vfs; - if (pos < 0 || pos > vfsp->length) - return false; - vfsp->currentpos = pos + vfsp->startpos; - - return true; -} -unsigned long VFSPAK_Tell (struct vfsfile_s *vfs) -{ - vfspack_t *vfsp = (vfspack_t*)vfs; - return vfsp->currentpos - vfsp->startpos; -} -unsigned long VFSPAK_GetLen (struct vfsfile_s *vfs) -{ - vfspack_t *vfsp = (vfspack_t*)vfs; - return vfsp->length; -} -void VFSPAK_Close(vfsfile_t *vfs) -{ - vfspack_t *vfsp = (vfspack_t*)vfs; - FSPAK_ClosePath(vfsp->parentpak); //tell the parent that we don't need it open any more (reference counts) - Z_Free(vfsp); //free ourselves. -} -vfsfile_t *FSPAK_OpenVFS(void *handle, flocation_t *loc, char *mode) -{ - pack_t *pack = (pack_t*)handle; - vfspack_t *vfs; - - if (strcmp(mode, "rb")) - return NULL; //urm, unable to write/append - - vfs = Z_Malloc(sizeof(vfspack_t)); - - vfs->parentpak = pack; - vfs->parentpak->references++; - - vfs->startpos = loc->offset; - vfs->length = loc->len; - vfs->currentpos = vfs->startpos; - - vfs->funcs.Close = VFSPAK_Close; - vfs->funcs.GetLen = VFSPAK_GetLen; - vfs->funcs.ReadBytes = VFSPAK_ReadBytes; - vfs->funcs.Seek = VFSPAK_Seek; - vfs->funcs.Tell = VFSPAK_Tell; - vfs->funcs.WriteBytes = VFSPAK_WriteBytes; //not supported - - return (vfsfile_t *)vfs; -} - -searchpathfuncs_t packfilefuncs = { - FSPAK_PrintPath, - FSPAK_ClosePath, - FSPAK_BuildHash, - FSPAK_FLocate, - FSOS_ReadFile, - FSPAK_EnumerateFiles, - FSPAK_LoadPackFile, - NULL, - FSPAK_OpenVFS -}; - - - -#ifdef DOOMWADS -void *FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, char *desc) -{ - dwadheader_t header; - int i; - packfile_t *newfiles; - int numpackfiles; - pack_t *pack; - dwadfile_t info; - - int section=0; - char sectionname[MAX_QPATH]; - char filename[52]; - char neatwadname[52]; - - if (packhandle == NULL) - return NULL; - - VFS_READ(packhandle, &header, sizeof(header)); - if (header.id[1] != 'W' || header.id[2] != 'A' || header.id[3] != 'D') - return NULL; //not a doom wad - - //doom wads come in two sorts. iwads and pwads. - //iwads are the master wads, pwads are meant to replace parts of the master wad. - //this is awkward, of course. - //we ignore the i/p bit for the most part, but with maps, pwads are given a prefixed name. - if (header.id[0] == 'I') - *neatwadname = '\0'; - else if (header.id[0] == 'P') - { - COM_FileBase(desc, neatwadname, sizeof(neatwadname)); - strcat(neatwadname, "#"); - } - else - return NULL; - - header.dirofs = LittleLong (header.dirofs); - header.dirlen = LittleLong (header.dirlen); - - numpackfiles = header.dirlen; - newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t)); - VFS_SEEK(packhandle, header.dirofs); - - //doom wads are awkward. - //they have no directory structure, except for start/end 'files'. - //they follow along the lines of lumps after the parent name. - //a map is the name of that map, and then a squence of the lumps that form that map (found by next-with-that-name). - //this is a problem for a real virtual filesystem, so we add a hack to recognise special names and expand them specially. - for (i=0 ; idescname, desc); - pack->handle = packhandle; - pack->numfiles = numpackfiles; - pack->files = newfiles; - pack->filepos = 0; - VFS_SEEK(packhandle, pack->filepos); - - pack->references++; - - Con_TPrintf (TL_ADDEDPACKFILE, desc, numpackfiles); - return pack; -} -searchpathfuncs_t doomwadfilefuncs = { - FSPAK_PrintPath, - FSPAK_ClosePath, - FSPAK_BuildHash, - FSPAK_FLocate, - FSOS_ReadFile, - FSPAK_EnumerateFiles, - FSPAK_LoadDoomWadFile, - NULL, - FSPAK_OpenVFS -}; -#endif -//====================================================================================================== -//ZIP files (*.zip *.pk3) - -void *com_pathforfile; //fread and stuff is preferable if null - -#ifndef ZEXPORT -#define ZEXPORT VARGS -#endif - -#ifdef AVAIL_ZLIB -#ifdef _WIN32 -#pragma comment( lib, "../libs/zlib.lib" ) -#endif - -//#define uShort ZLIBuShort -//#define uLong ZLIBuLong - -#include -#include "unzip.c" - -typedef struct zipfile_s -{ - char filename[MAX_QPATH]; - unzFile handle; - int numfiles; - packfile_t *files; - -#ifdef HASH_FILESYSTEM - hashtable_t hash; -#endif - - vfsfile_t *raw; - vfsfile_t *currentfile; //our unzip.c can only handle one active file at any one time - //so we have to keep closing and switching. - //slow, but it works. most of the time we'll only have a single file open anyway. - int references; //and a reference count -} zipfile_t; - - -static void FSZIP_PrintPath(void *handle) -{ - zipfile_t *zip = handle; - - if (zip->references != 1) - Con_Printf("%s (%i)\n", zip->filename, zip->references-1); - else - Con_Printf("%s\n", zip->filename); -} -static void FSZIP_ClosePath(void *handle) -{ - zipfile_t *zip = handle; - - if (--zip->references > 0) - return; //not yet time - - unzClose(zip->handle); - if (zip->files) - Z_Free(zip->files); - Z_Free(zip); -} -static void FSZIP_BuildHash(void *handle) -{ - zipfile_t *zip = handle; - int i; - - for (i = 0; i < zip->numfiles; i++) - { - if (!Hash_GetInsensative(&filesystemhash, zip->files[i].name)) - { - fs_hash_files++; - Hash_AddInsensative(&filesystemhash, zip->files[i].name, &zip->files[i], &zip->files[i].bucket); - } - else - fs_hash_dups++; - } -} -static qboolean FSZIP_FLocate(void *handle, flocation_t *loc, char *filename, void *hashedresult) -{ - packfile_t *pf = hashedresult; - int i, len; - zipfile_t *zip = handle; - -// look through all the pak file elements - - if (pf) - { //is this a pointer to a file in this pak? - if (pf < zip->files || pf >= zip->files + zip->numfiles) - return false; //was found in a different path - } - else - { - for (i=0 ; inumfiles ; i++) //look for the file - { - if (!stricmp (zip->files[i].name, filename)) - { - pf = &zip->files[i]; - break; - } - } - } - - if (pf) - { - len = pf->filelen; - if (loc) - { - loc->index = pf - zip->files; - strcpy(loc->rawname, zip->filename); - loc->offset = pf->filepos; - loc->len = pf->filelen; - - unzLocateFileMy (zip->handle, loc->index, zip->files[loc->index].filepos); - loc->offset = unzGetCurrentFileUncompressedPos(zip->handle); -// if (loc->offset<0) -// { //file not found, or is compressed. -// *loc->rawname = '\0'; -// loc->offset=0; -// } - } - return true; - } - return false; -} - -static void FSZIP_ReadFile(void *handle, flocation_t *loc, char *buffer) -{ - zipfile_t *zip = handle; - int err; - - unzLocateFileMy (zip->handle, loc->index, zip->files[loc->index].filepos); - - unzOpenCurrentFile (zip->handle); - err = unzReadCurrentFile (zip->handle, buffer, zip->files[loc->index].filelen); - unzCloseCurrentFile (zip->handle); - - if (err!=zip->files[loc->index].filelen) - { - Con_Printf ("Can't extract file \"%s:%s\" (corrupt)\n", zip->filename, zip->files[loc->index].name); - return; - } - return; -} - -static int FSZIP_EnumerateFiles (void *handle, char *match, int (*func)(char *, int, void *), void *parm) -{ - zipfile_t *zip = handle; - int num; - - for (num = 0; num<(int)zip->numfiles; num++) - { - if (wildcmp(match, zip->files[num].name)) - { - if (!func(zip->files[num].name, zip->files[num].filelen, parm)) - return false; - } - } - - return true; -} - -/* -================= -COM_LoadZipFile - -Takes an explicit (not game tree related) path to a pak file. - -Loads the header and directory, adding the files at the beginning -of the list so they override previous pack files. -================= -*/ -static void *FSZIP_LoadZipFile (vfsfile_t *packhandle, char *desc) -{ - int i; - int nextfileziphandle; - - zipfile_t *zip; - packfile_t *newfiles; - - unz_global_info globalinf = {0}; - unz_file_info file_info; - - zip = Z_Malloc(sizeof(zipfile_t)); - Q_strncpyz(zip->filename, desc, sizeof(zip->filename)); - zip->handle = unzOpen ((zip->raw = packhandle)); - if (!zip->handle) - { - Z_Free(zip); - Con_TPrintf (TL_COULDNTOPENZIP, desc); - return NULL; - } - - unzGetGlobalInfo (zip->handle, &globalinf); - - zip->numfiles = globalinf.number_entry; - - zip->files = newfiles = Z_Malloc (zip->numfiles * sizeof(packfile_t)); - for (i = 0; i < zip->numfiles; i++) - { - if (unzGetCurrentFileInfo (zip->handle, &file_info, newfiles[i].name, sizeof(newfiles[i].name), NULL, 0, NULL, 0) != UNZ_OK) - Con_Printf("Zip Error\n"); - Q_strlwr(newfiles[i].name); - newfiles[i].filelen = file_info.uncompressed_size; - newfiles[i].filepos = file_info.c_offset; - - nextfileziphandle = unzGoToNextFile (zip->handle); - if (nextfileziphandle == UNZ_END_OF_LIST_OF_FILE) - break; - else if (nextfileziphandle != UNZ_OK) - Con_Printf("Zip Error\n"); - } - - zip->references = 1; - zip->currentfile = NULL; - - Con_TPrintf (TL_ADDEDZIPFILE, desc, zip->numfiles); - return zip; -} - -int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) -{ - zipfile_t *zip = handle; - unz_file_info file_info; - - int *filecrcs; - int numcrcs=0; - int i; - - filecrcs = BZ_Malloc((zip->numfiles+1)*sizeof(int)); - filecrcs[numcrcs++] = seed; - - unzGoToFirstFile(zip->handle); - for (i = 0; i < zip->numfiles; i++) - { - if (zip->files[i].filelen>0) - { - unzGetCurrentFileInfo (zip->handle, &file_info, NULL, 0, NULL, 0, NULL, 0); - filecrcs[numcrcs++] = file_info.crc; - } - unzGoToNextFile (zip->handle); - } - - if (crctype) - return Com_BlockChecksum(filecrcs, numcrcs*sizeof(int)); - else - return Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int)); -} - -typedef struct { - vfsfile_t funcs; - - vfsfile_t *defer; - - //in case we're forced away. - zipfile_t *parent; - qboolean iscompressed; - int pos; - int length; //try and optimise some things - int index; - int startpos; -} vfszip_t; -void VFSZIP_MakeActive(vfszip_t *vfsz) -{ - int i; - char buffer[8192]; //must be power of two - - if ((vfszip_t*)vfsz->parent->currentfile == vfsz) - return; //already us - if (vfsz->parent->currentfile) - unzCloseCurrentFile(vfsz->parent->handle); - - unzLocateFileMy(vfsz->parent->handle, vfsz->index, vfsz->startpos); - unzOpenCurrentFile(vfsz->parent->handle); - - - if (vfsz->pos > 0) - { - Con_DPrintf("VFSZIP_MakeActive: Shockingly inefficient\n"); - - //now we need to seek up to where we had previously gotten to. - for (i = 0; i < vfsz->pos-sizeof(buffer); i++) - unzReadCurrentFile(vfsz->parent->handle, buffer, sizeof(buffer)); - unzReadCurrentFile(vfsz->parent->handle, buffer, vfsz->pos - i); - } - - vfsz->parent->currentfile = (vfsfile_t*)vfsz; -} - -int VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) -{ - int read; - vfszip_t *vfsz = (vfszip_t*)file; - - if (vfsz->defer) - return VFS_READ(vfsz->defer, buffer, bytestoread); - - if (vfsz->iscompressed) - { - VFSZIP_MakeActive(vfsz); - read = unzReadCurrentFile(vfsz->parent->handle, buffer, bytestoread); - } - else - { - if (vfsz->parent->currentfile != file) - { - unzCloseCurrentFile(vfsz->parent->handle); - VFS_SEEK(vfsz->parent->raw, vfsz->pos+vfsz->startpos); - vfsz->parent->currentfile = file; - } - read = VFS_READ(vfsz->parent->raw, buffer, bytestoread); - } - - vfsz->pos += read; - return read; -} -int VFSZIP_WriteBytes (struct vfsfile_s *file, void *buffer, int bytestoread) -{ - Sys_Error("VFSZIP_WriteBytes: Not supported\n"); - return 0; -} -qboolean VFSZIP_Seek (struct vfsfile_s *file, unsigned long pos) -{ - vfszip_t *vfsz = (vfszip_t*)file; - - if (vfsz->defer) - return VFS_SEEK(vfsz->defer, pos); - - //This is *really* inefficient - if (vfsz->parent->currentfile == file) - { - if (vfsz->iscompressed) - { //if they're going to seek on a file in a zip, let's just copy it out - char buffer[8192]; - unsigned int chunk; - unsigned int i; - unsigned int length; - - vfsz->defer = FS_OpenTemp(); - if (vfsz->defer) - { - unzCloseCurrentFile(vfsz->parent->handle); - vfsz->parent->currentfile = NULL; //make it not us - - length = vfsz->length; - i = 0; - vfsz->pos = 0; - VFSZIP_MakeActive(vfsz); - while (1) - { - chunk = length - i; - if (chunk > sizeof(buffer)) - chunk = sizeof(buffer); - if (chunk == 0) - break; - unzReadCurrentFile(vfsz->parent->handle, buffer, chunk); - VFS_WRITE(vfsz->defer, buffer, chunk); - - i += chunk; - } - } - } - - unzCloseCurrentFile(vfsz->parent->handle); - vfsz->parent->currentfile = NULL; //make it not us - - if (vfsz->defer) - return VFS_SEEK(vfsz->defer, pos); - } - - - - if (pos < 0 || pos > vfsz->length) - return false; - vfsz->pos = pos; - - return true; -} -unsigned long VFSZIP_Tell (struct vfsfile_s *file) -{ - vfszip_t *vfsz = (vfszip_t*)file; - - if (vfsz->defer) - return VFS_TELL(vfsz->defer); - - return vfsz->pos; -} -unsigned long VFSZIP_GetLen (struct vfsfile_s *file) -{ - vfszip_t *vfsz = (vfszip_t*)file; - return vfsz->length; -} -void VFSZIP_Close (struct vfsfile_s *file) -{ - vfszip_t *vfsz = (vfszip_t*)file; - - if (vfsz->parent->currentfile == file) - vfsz->parent->currentfile = NULL; //make it not us - - if (vfsz->defer) - VFS_CLOSE(vfsz->defer); - - FSZIP_ClosePath(vfsz->parent); - Z_Free(vfsz); -} - -vfsfile_t *FSZIP_OpenVFS(void *handle, flocation_t *loc, char *mode) -{ - int rawofs; - zipfile_t *zip = handle; - vfszip_t *vfsz; - - if (strcmp(mode, "rb")) - return NULL; //urm, unable to write/append - - vfsz = Z_Malloc(sizeof(vfszip_t)); - - vfsz->parent = zip; - vfsz->index = loc->index; - vfsz->startpos = zip->files[loc->index].filepos; - vfsz->length = loc->len; - - vfsz->funcs.Close = VFSZIP_Close; - vfsz->funcs.GetLen = VFSZIP_GetLen; - vfsz->funcs.ReadBytes = VFSZIP_ReadBytes; - vfsz->funcs.Seek = VFSZIP_Seek; - vfsz->funcs.Tell = VFSZIP_Tell; - vfsz->funcs.WriteBytes = NULL; - vfsz->funcs.seekingisabadplan = true; - - unzLocateFileMy(vfsz->parent->handle, vfsz->index, vfsz->startpos); - rawofs = unzGetCurrentFileUncompressedPos(zip->handle); - vfsz->iscompressed = rawofs<0; - if (!vfsz->iscompressed) - { - vfsz->startpos = rawofs; - VFS_SEEK(zip->raw, vfsz->startpos); - vfsz->parent->currentfile = (vfsfile_t*)vfsz; - } - - zip->references++; - - return (vfsfile_t*)vfsz; -} - -searchpathfuncs_t zipfilefuncs = { - FSZIP_PrintPath, - FSZIP_ClosePath, - FSZIP_BuildHash, - FSZIP_FLocate, - FSZIP_ReadFile, - FSZIP_EnumerateFiles, - FSZIP_LoadZipFile, - FSZIP_GeneratePureCRC, - FSZIP_OpenVFS -}; - -#endif - - //====================================================================================================== @@ -1323,9 +146,10 @@ searchpathfuncs_t zipfilefuncs = { typedef struct searchpath_s { - searchpathfuncs_t *funcs; + const searchpathfuncs_t *funcs; qboolean copyprotected; //don't allow downloads from here. qboolean istemporary; + qboolean isexplicit; //explicitly loaded (ie: id1|qw|$gamedir|fte) void *handle; char purepath[256]; //server tracks the path used to load them so it can tell the client @@ -1340,45 +164,6 @@ searchpath_t *com_searchpaths; searchpath_t *com_purepaths; searchpath_t *com_base_searchpaths; // without gamedirs -static void COM_AddDataFiles(char *purepath, char *pathto, searchpath_t *search, char *extension, searchpathfuncs_t *funcs); - -searchpath_t *COM_AddPathHandle(char *purepath, char *probablepath, searchpathfuncs_t *funcs, void *handle, qboolean copyprotect, qboolean istemporary, unsigned int loadstuff) -{ - searchpath_t *search; - - search = (searchpath_t*)Z_Malloc (sizeof(searchpath_t)); - search->copyprotected = copyprotect; - search->istemporary = istemporary; - search->handle = handle; - search->funcs = funcs; - Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); - - search->next = com_searchpaths; - com_searchpaths = search; - - com_fschanged = true; - - - //add any data files too - if (loadstuff & 2) - COM_AddDataFiles(purepath, probablepath, search, "pak", &packfilefuncs);//q1/hl/h2/q2 - //pk2s never existed. -#ifdef AVAIL_ZLIB - if (loadstuff & 4) - COM_AddDataFiles(purepath, probablepath, search, "pk3", &zipfilefuncs); //q3 + offspring - if (loadstuff & 8) - COM_AddDataFiles(purepath, probablepath, search, "pk4", &zipfilefuncs); //q4 - //we could easily add zip, but it's friendlier not to -#endif - -#ifdef DOOMWADS - if (loadstuff & 16) - COM_AddDataFiles(purepath, probablepath, search, "wad", &doomwadfilefuncs); //q4 -#endif - - return search; -} - /* ================ COM_filelength @@ -1413,7 +198,7 @@ static int COM_FileOpenRead (char *path, FILE **hndl) } */ -int COM_FileSize(char *path) +int COM_FileSize(const char *path) { int len; flocation_t loc; @@ -1461,7 +246,7 @@ COM_Dir_f ============ */ -static int COM_Dir_List(char *name, int size, void *parm) +static int COM_Dir_List(const char *name, int size, void *parm) { Con_Printf("%s (%i)\n", name, size); return 1; @@ -1540,7 +325,8 @@ FILE *COM_WriteFileOpen (char *filename) //like fopen, but based around quake's FILE *f; char name[MAX_OSPATH]; - sprintf (name, "%s/%s", com_gamedir, filename); + if (!FS_NativePath(filename, FS_GAMEONLY, name, sizeof(name))) + return NULL; COM_CreatePath(name); @@ -1681,15 +467,17 @@ Sets com_filesize and one of handle or file */ //if loc is valid, loc->search is always filled in, the others are filled on success. //returns -1 if couldn't find. -int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *loc) +int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation_t *loc) { int depth=0, len; searchpath_t *search; + char cleanpath[MAX_QPATH]; void *pf; //Con_Printf("Finding %s: ", filename); - if (Sys_PathProtection(filename)) + filename = FS_GetCleanPath(filename, cleanpath, sizeof(cleanpath)); + if (!filename) { pf = NULL; goto fail; @@ -1722,7 +510,7 @@ int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *lo com_file_copyprotected = search->copyprotected; goto out; } - depth += (search->funcs != &osfilefuncs || returntype == FSLFRT_DEPTH_ANYPATH); + depth += (search->isexplicit || returntype == FSLFRT_DEPTH_ANYPATH); } } @@ -1743,7 +531,7 @@ int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *lo com_file_copyprotected = search->copyprotected; goto out; } - depth += (search->funcs != &osfilefuncs || returntype == FSLFRT_DEPTH_ANYPATH); + depth += (search->isexplicit || returntype == FSLFRT_DEPTH_ANYPATH); } fail: if (loc) @@ -1907,20 +695,31 @@ int COM_FOpenWriteFile(char *filename, FILE **file) #endif //int COM_FOpenFile (char *filename, FILE **file) {file_from_pak=0;return COM_FOpenFile2 (filename, file, false);} //FIXME: TEMPORARY -//true if protection kicks in -qboolean Sys_PathProtection(char *pattern) +//outbuf might not be written into +static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen) { char *s; + if (strchr(pattern, '\\')) { + Q_strncpyz(outbuf, pattern, outlen); + pattern = outbuf; + Con_Printf("Warning: \\ characters in filename %s\n", pattern); while((s = strchr(pattern, '\\'))) + { *s = '/'; + + } } if (strstr(pattern, "//")) { //amiga uses // as equivelent to /../ + + Q_strncpyz(outbuf, pattern, outlen); + pattern = outbuf; + Con_Printf("Warning: // characters in filename %s\n", pattern); while (s=strstr(pattern, "//")) { @@ -1941,9 +740,9 @@ qboolean Sys_PathProtection(char *pattern) Con_Printf("Error: absolute path in filename %s\n", pattern); else { - return false; + return pattern; } - return true; + return NULL; } #ifdef AVAIL_ZLIB @@ -1966,6 +765,9 @@ typedef struct { #define GZ_RESERVED (32|64|128) #include +#ifdef _WIN32 +#pragma comment( lib, "../libs/zlib.lib" ) +#endif vfsfile_t *FS_DecompressGZip(vfsfile_t *infile, gzheader_t *header) { @@ -2098,7 +900,7 @@ vfsfile_t *FS_DecompressGZip(vfsfile_t *infile, gzheader_t *header) } #endif -vfsfile_t *VFS_Filter(char *filename, vfsfile_t *handle) +vfsfile_t *VFS_Filter(const char *filename, vfsfile_t *handle) { // char *ext; @@ -2122,8 +924,49 @@ vfsfile_t *VFS_Filter(char *filename, vfsfile_t *handle) return handle; } -vfsfile_t *FS_OpenVFS(char *filename, char *mode, int relativeto) +qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out, int outlen) { + char cleanname[MAX_QPATH]; + fname = FS_GetCleanPath(fname, cleanname, sizeof(cleanname)); + if (!fname) + return false; + + switch (relativeto) + { + case FS_GAMEONLY: + case FS_GAME: + if (*com_homedir) + snprintf(out, outlen, "%s%s/%s", com_homedir, gamedirfile, fname); + else + snprintf(out, outlen, "%s%s/%s", com_quakedir, gamedirfile, fname); + break; + case FS_SKINS: + if (*com_homedir) + snprintf(out, outlen, "%sqw/skins/%s", com_homedir, fname); + else + snprintf(out, outlen, "%sqw/skins/%s", com_quakedir, fname); + break; + case FS_ROOT: + if (*com_homedir) + snprintf(out, outlen, "%s%s", com_homedir, fname); + else + snprintf(out, outlen, "%s%s", com_quakedir, fname); + break; + case FS_CONFIGONLY: + if (*com_homedir) + snprintf(out, outlen, "%sfte/%s", com_homedir, fname); + else + snprintf(out, outlen, "%sfte/%s", com_quakedir, fname); + break; + default: + Sys_Error("FS_Rename case not handled\n"); + } + return true; +} + +vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto) +{ + char cleanname[MAX_QPATH]; char fullname[MAX_OSPATH]; flocation_t loc; vfsfile_t *vfs; @@ -2132,7 +975,9 @@ vfsfile_t *FS_OpenVFS(char *filename, char *mode, int relativeto) //blanket-bans - if (Sys_PathProtection(filename) ) + + filename = FS_GetCleanPath(filename, cleanname, sizeof(cleanname)); + if (!filename) return NULL; @@ -2215,165 +1060,43 @@ vfsfile_t *FS_OpenReadLocation(flocation_t *location) return NULL; } -int FS_Rename2(char *oldf, char *newf, int oldrelativeto, int newrelativeto) +int FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto) { char oldfullname[MAX_OSPATH]; char newfullname[MAX_OSPATH]; - switch (oldrelativeto) - { - case FS_GAME: - if (*com_homedir) - snprintf(oldfullname, sizeof(oldfullname), "%s%s/", com_homedir, gamedirfile); - else - snprintf(oldfullname, sizeof(oldfullname), "%s%s/", com_quakedir, gamedirfile); - break; - case FS_SKINS: - if (*com_homedir) - snprintf(oldfullname, sizeof(oldfullname), "%sqw/skins/", com_homedir); - else - snprintf(oldfullname, sizeof(oldfullname), "%sqw/skins/", com_quakedir); - break; - case FS_ROOT: - if (*com_homedir) - snprintf(oldfullname, sizeof(oldfullname), "%s", com_homedir); - else - snprintf(oldfullname, sizeof(oldfullname), "%s", com_quakedir); - break; - default: - Sys_Error("FS_Rename case not handled\n"); - } - - switch (newrelativeto) - { - case FS_GAME: - if (*com_homedir) - snprintf(newfullname, sizeof(newfullname), "%s%s/", com_homedir, gamedirfile); - else - snprintf(newfullname, sizeof(newfullname), "%s%s/", com_quakedir, gamedirfile); - break; - case FS_SKINS: - if (*com_homedir) - snprintf(newfullname, sizeof(newfullname), "%sqw/skins/", com_homedir); - else - snprintf(newfullname, sizeof(newfullname), "%sqw/skins/", com_quakedir); - break; - case FS_ROOT: - if (*com_homedir) - snprintf(newfullname, sizeof(newfullname), "%s", com_homedir); - else - snprintf(newfullname, sizeof(newfullname), "%s", com_quakedir); - break; - default: - Sys_Error("FS_Rename case not handled\n"); - } - - Q_strncatz(oldfullname, oldf, sizeof(oldfullname)); - Q_strncatz(newfullname, newf, sizeof(newfullname)); + if (!FS_NativePath(oldf, oldrelativeto, oldfullname, sizeof(oldfullname))) + return EPERM; + if (!FS_NativePath(newf, newrelativeto, newfullname, sizeof(newfullname))) + return EPERM; FS_CreatePath(newf, newrelativeto); return rename(oldfullname, newfullname); } -int FS_Rename(char *oldf, char *newf, int relativeto) +int FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto) { - char oldfullname[MAX_OSPATH]; - char newfullname[MAX_OSPATH]; - - switch (relativeto) - { - case FS_GAME: - if (*com_homedir) - snprintf(oldfullname, sizeof(oldfullname), "%s%s/", com_homedir, gamedirfile); - else - snprintf(oldfullname, sizeof(oldfullname), "%s%s/", com_quakedir, gamedirfile); - break; - case FS_SKINS: - if (*com_homedir) - snprintf(oldfullname, sizeof(oldfullname), "%sqw/skins/", com_homedir); - else - snprintf(oldfullname, sizeof(oldfullname), "%sqw/skins/", com_quakedir); - break; - case FS_ROOT: - if (*com_homedir) - snprintf(oldfullname, sizeof(oldfullname), "%s", com_homedir); - else - snprintf(oldfullname, sizeof(oldfullname), "%s", com_quakedir); - break; - default: - Sys_Error("FS_Rename case not handled\n"); - } - - Q_strncpy(newfullname, oldfullname, sizeof(newfullname)); - Q_strncatz(oldfullname, oldf, sizeof(oldfullname)); - Q_strncatz(newfullname, newf, sizeof(newfullname)); - - return rename(oldfullname, newfullname); + return FS_Rename2(oldf, newf, relativeto, relativeto); } -int FS_Remove(char *fname, int relativeto) +int FS_Remove(const char *fname, enum fs_relative relativeto) { char fullname[MAX_OSPATH]; - switch (relativeto) - { - case FS_GAME: - if (*com_homedir) - snprintf(fullname, sizeof(fullname), "%s%s/%s", com_homedir, gamedirfile, fname); - else - snprintf(fullname, sizeof(fullname), "%s%s/%s", com_quakedir, gamedirfile, fname); - break; - case FS_SKINS: - if (*com_homedir) - snprintf(fullname, sizeof(fullname), "%sqw/skins/%s", com_homedir, fname); - else - snprintf(fullname, sizeof(fullname), "%sqw/skins/%s", com_quakedir, fname); - break; - case FS_ROOT: - if (*com_homedir) - snprintf(fullname, sizeof(fullname), "%s%s", com_homedir, fname); - else - snprintf(fullname, sizeof(fullname), "%s%s", com_quakedir, fname); - break; - default: - Sys_Error("FS_Rename case not handled\n"); - } + if (!FS_NativePath(fname, relativeto, fullname, sizeof(fullname))) + return EPERM; - return unlink (fullname); + return Sys_remove (fullname); } -void FS_CreatePath(char *pname, int relativeto) +//create a path for the given filename (dir-only must have trailing slash) +void FS_CreatePath(const char *pname, enum fs_relative relativeto) { char fullname[MAX_OSPATH]; - switch (relativeto) - { - case FS_GAMEONLY: - case FS_GAME: - snprintf(fullname, sizeof(fullname), "%s/%s", com_gamedir, pname); - break; - case FS_ROOT: - if (*com_homedir) - snprintf(fullname, sizeof(fullname), "%s%s", com_homedir, pname); - else - snprintf(fullname, sizeof(fullname), "%s%s", com_quakedir, pname); - break; - case FS_SKINS: - if (*com_homedir) - snprintf(fullname, sizeof(fullname), "%sqw/skins/%s", com_homedir, pname); - else - snprintf(fullname, sizeof(fullname), "%sqw/skins/%s", com_quakedir, pname); - break; - case FS_CONFIGONLY: - if (*com_homedir) - snprintf(fullname, sizeof(fullname), "%sfte/%s", com_homedir, pname); - else - snprintf(fullname, sizeof(fullname), "%sfte/%s", com_quakedir, pname); - break; - default: - Sys_Error("FS_CreatePath: Bad relative path (%i)", relativeto); - break; - } + if (!FS_NativePath(pname, relativeto, fullname, sizeof(fullname))) + return; + COM_CreatePath(fullname); } -qboolean FS_WriteFile (char *filename, void *data, int len, int relativeto) +qboolean FS_WriteFile (const char *filename, void *data, int len, enum fs_relative relativeto) { vfsfile_t *f; FS_CreatePath(filename, relativeto); @@ -2386,6 +1109,43 @@ qboolean FS_WriteFile (char *filename, void *data, int len, int relativeto) return true; } +qboolean FS_Copy(const char *source, const char *dest, enum fs_relative relativesource, enum fs_relative relativedest) +{ + vfsfile_t *d, *s; + char buffer[8192*8]; + int read; + qboolean result = false; + FS_CreatePath(dest, relativedest); + s = FS_OpenVFS(source, "rb", relativesource); + if (s) + { + d = FS_OpenVFS(dest, "wb", relativedest); + if (d) + { + result = true; + + for (;;) + { + read = VFS_READ(s, buffer, sizeof(buffer)); + if (read <= 0) + break; + if (VFS_WRITE(d, buffer, read) != read) + { + result = false; + break; + } + } + + VFS_CLOSE(d); + + if (!result) + FS_Remove(dest, relativedest); + } + VFS_CLOSE(s); + } + return result; +} + static cache_user_t *loadcache; static qbyte *loadbuf; @@ -2399,7 +1159,7 @@ Filename are reletive to the quake directory. Always appends a 0 qbyte to the loaded data. ============ */ -qbyte *COM_LoadFile (char *path, int usehunk) +qbyte *COM_LoadFile (const char *path, int usehunk) { vfsfile_t *f; qbyte *buf; @@ -2467,33 +1227,33 @@ qbyte *COM_LoadFile (char *path, int usehunk) return buf; } -qbyte *COM_LoadMallocFile (char *path) //used for temp info along side temp hunk +qbyte *COM_LoadMallocFile (const char *path) //used for temp info along side temp hunk { return COM_LoadFile (path, 5); } -qbyte *COM_LoadHunkFile (char *path) +qbyte *COM_LoadHunkFile (const char *path) { return COM_LoadFile (path, 1); } -qbyte *COM_LoadTempFile (char *path) +qbyte *COM_LoadTempFile (const char *path) { return COM_LoadFile (path, 2); } -qbyte *COM_LoadTempFile2 (char *path) +qbyte *COM_LoadTempFile2 (const char *path) { return COM_LoadFile (path, 6); } -void COM_LoadCacheFile (char *path, struct cache_user_s *cu) +void COM_LoadCacheFile (const char *path, struct cache_user_s *cu) { loadcache = cu; COM_LoadFile (path, 3); } // uses temp hunk if larger than bufsize -qbyte *COM_LoadStackFile (char *path, void *buffer, int bufsize) +qbyte *COM_LoadStackFile (const char *path, void *buffer, int bufsize) { qbyte *buf; @@ -2518,7 +1278,7 @@ void FS_FreeFile(void *file) -void COM_EnumerateFiles (char *match, int (*func)(char *, int, void *), void *parm) +void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *), void *parm) { searchpath_t *search; for (search = com_searchpaths; search ; search = search->next) @@ -2543,7 +1303,7 @@ void COM_FlushTempoaryPacks(void) } } -qboolean COM_LoadMapPackFile (char *filename, int ofs) +qboolean COM_LoadMapPackFile (const char *filename, int ofs) { return false; /* @@ -2625,22 +1385,22 @@ qboolean COM_LoadMapPackFile (char *filename, int ofs) */ } - +static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probablepath, const searchpathfuncs_t *funcs, void *handle, qboolean copyprotect, qboolean istemporary, qboolean isexplicit, unsigned int loadstuff); typedef struct { - searchpathfuncs_t *funcs; + const searchpathfuncs_t *funcs; searchpath_t *parentpath; - char *parentdesc; - char *puredesc; + const char *parentdesc; + const char *puredesc; } wildpaks_t; -static int COM_AddWildDataFiles (char *descriptor, int size, void *vparam) +static int FS_AddWildDataFiles (const char *descriptor, int size, void *vparam) { wildpaks_t *param = vparam; vfsfile_t *vfs; - searchpathfuncs_t *funcs = param->funcs; + const searchpathfuncs_t *funcs = param->funcs; searchpath_t *search; - pack_t *pak; + void *pak; char pakfile[MAX_OSPATH]; char purefile[MAX_OSPATH]; flocation_t loc; @@ -2669,13 +1429,13 @@ static int COM_AddWildDataFiles (char *descriptor, int size, void *vparam) snprintf (purefile, sizeof(purefile), "%s/%s", param->puredesc, descriptor); else Q_strncpyz(purefile, descriptor, sizeof(purefile)); - COM_AddPathHandle(purefile, pakfile, funcs, pak, true, false, (unsigned int)-1); + FS_AddPathHandle(purefile, pakfile, funcs, pak, true, false, false, (unsigned int)-1); return true; } -static void COM_AddDataFiles(char *purepath, char *pathto, searchpath_t *search, char *extension, searchpathfuncs_t *funcs) +static void FS_AddDataFiles(const char *purepath, const char *pathto, searchpath_t *search, const char *extension, searchpathfuncs_t *funcs) { //search is the parent int i; @@ -2702,7 +1462,7 @@ static void COM_AddDataFiles(char *purepath, char *pathto, searchpath_t *search, break; snprintf (pakfile, sizeof(pakfile), "%spak%i.%s/", pathto, i, extension); snprintf (purefile, sizeof(pakfile), "%spak%i.%s", purepath, i, extension); - COM_AddPathHandle(purefile, pakfile, funcs, handle, true, false, (unsigned int)-1); + FS_AddPathHandle(purefile, pakfile, funcs, handle, true, false, false, (unsigned int)-1); } //now load the random ones @@ -2711,7 +1471,46 @@ static void COM_AddDataFiles(char *purepath, char *pathto, searchpath_t *search, wp.parentdesc = pathto; wp.parentpath = search; wp.puredesc = purepath; - search->funcs->EnumerateFiles(search->handle, pakfile, COM_AddWildDataFiles, &wp); + search->funcs->EnumerateFiles(search->handle, pakfile, FS_AddWildDataFiles, &wp); +} + +static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probablepath, const searchpathfuncs_t *funcs, void *handle, qboolean copyprotect, qboolean istemporary, qboolean isexplicit, unsigned int loadstuff) +{ + unsigned int i; + + searchpath_t *search; + + if (!funcs) + { + Con_Printf("COM_AddPathHandle: %s format not supported in this build\n", probablepath); + return NULL; + } + + search = (searchpath_t*)Z_Malloc (sizeof(searchpath_t)); + search->copyprotected = copyprotect; + search->istemporary = istemporary; + search->isexplicit = isexplicit; + search->handle = handle; + search->funcs = funcs; + Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); + + search->next = com_searchpaths; + com_searchpaths = search; + + com_fschanged = true; + + + for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + { + if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew) + continue; + if (loadstuff & (1<next) { if (search->funcs != &osfilefuncs) continue; - if (!stricmp(search->handle, com_gamedir)) + if (!stricmp(search->handle, dir)) return; //already loaded (base paths?) } @@ -2758,7 +1556,7 @@ void COM_AddGameDirectory (char *puredir, char *dir, unsigned int loadstuff) p = Z_Malloc(strlen(dir)+1); strcpy(p, dir); - COM_AddPathHandle((*dir?puredir:""), va("%s/", dir), &osfilefuncs, p, false, false, loadstuff); + FS_AddPathHandle((*dir?puredir:""), va("%s/", dir), &osfilefuncs, p, false, false, true, loadstuff); } char *COM_NextPath (char *prevpath) @@ -2766,10 +1564,7 @@ char *COM_NextPath (char *prevpath) searchpath_t *s; char *prev; - if (!prevpath) - return com_gamedir; - - prev = com_gamedir; + prev = NULL; for (s=com_searchpaths ; s ; s=s->next) { if (s->funcs != &osfilefuncs) @@ -2821,6 +1616,10 @@ char *COM_GetPathInfo (int i, int *crc) #endif +char *FS_GetGamedir(void) +{ + return gamedirfile; +} /* ================ COM_Gamedir @@ -2828,19 +1627,43 @@ COM_Gamedir Sets the gamedir and path to a different directory. ================ */ -void COM_Gamedir (char *dir) +void COM_Gamedir (const char *dir) { searchpath_t *next; + int plen, dlen; + char *p; - if (!*dir || strstr(dir, "..") || strstr(dir, "/") + if (!*dir || !strcmp(dir, ".") || strstr(dir, "..") || strstr(dir, "/") || strstr(dir, "\\") || strstr(dir, ":") ) { Con_TPrintf (TL_GAMEDIRAINTPATH); return; } - if (!strcmp(gamedirfile, dir)) - return; // still the same + dlen = strlen(dir); + for (next = com_base_searchpaths; next; next = next->next) + { + if (next->funcs == &osfilefuncs) + { + p = next->handle; + plen = strlen(p); + if (plen == dlen) + { + //no basedir, maybe + if (!strcmp(p, dir)) + return; + } + else if (plen > dlen) + { + if (*(p+plen-dlen-1) == '/') + { + if (strcmp(p+plen-dlen, dir)) + return; + } + } + + } + } FS_ForceToPure(NULL, NULL, 0); @@ -2877,24 +1700,38 @@ void COM_Gamedir (char *dir) // Cache_Flush (); - COM_AddGameDirectory(dir, va("%s%s", com_quakedir, dir), (unsigned int)-1); - if (*com_homedir) - COM_AddGameDirectory(dir, va("%s%s", com_homedir, dir), (unsigned int)-1); + if (strchr(dir, ';')) + { + //separate case because parsestringset splits by whitespace too + while (dir = COM_ParseStringSet(dir)) + { + if (!strcmp(dir, ";")) + continue; + if (!*dir) + continue; + + FS_AddGameDirectory(dir, va("%s%s", com_quakedir, com_token), ~0); + if (*com_homedir) + FS_AddGameDirectory(dir, va("%s%s", com_homedir, com_token), ~0); + } + } + else + { + FS_AddGameDirectory(dir, va("%s%s", com_quakedir, dir), ~0); + if (*com_homedir) + FS_AddGameDirectory(dir, va("%s%s", com_homedir, dir), ~0); + } #ifndef SERVERONLY if (!isDedicated) { - char fn[MAX_OSPATH]; - FILE *f; - -// if (qrenderer) //only do this if we have already started the renderer +// if (qrenderer>0) //only do this if we have already started the renderer // Cbuf_InsertText("vid_restart\n", RESTRICT_LOCAL); - sprintf(fn, "%s/%s", com_gamedir, "config.cfg"); - if ((f = fopen(fn, "r")) != NULL) + + if (COM_FDepthFile("config.cfg", true) <= (*com_homedir?1:0)) { - fclose(f); Cbuf_InsertText("cl_warncmd 0\n" "exec config.cfg\n" "exec fte.cfg\n" @@ -2938,19 +1775,16 @@ potentialgamepath_t pgp[] = { #define NEXCFG "set sv_maxairspeed \"400\"\nset sv_mintic \"0.01\"\ncl_nolerp 0\n" typedef struct { - char *gamename; //sent to the master server when this is the current gamemode. - char *exename; //used if the exe name contains this - char *argname; //used if this was used as a parameter. - char *auniquefile; //used if this file is relative from the gamedir + const char *gamename; //sent to the master server when this is the current gamemode. + const char *exename; //used if the exe name contains this + const char *argname; //used if this was used as a parameter. + const char *auniquefile; //used if this file is relative from the gamedir - char *customexec; + const char *customexec; - char *dir1; - char *dir2; - char *dir3; - char *dir4; + const char *dir[4]; } gamemode_info_t; -gamemode_info_t gamemode_info[] = { +const gamemode_info_t gamemode_info[] = { //note that there is no basic 'fte' gamemode, this is because we aim for network compatability. Darkplaces-Quake is the closest we get. //this is to avoid having too many gamemodes anyway. @@ -2958,23 +1792,23 @@ gamemode_info_t gamemode_info[] = { {"Darkplaces-Quake", "darkplaces", "-quake", "id1/pak0.pak", NULL, "id1", "qw", "fte"}, {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", NULL, NULL, "id1", "qw", "hipnotic", "fte"}, {"Darkplaces-Rogue", "rogue", "-rogue", NULL, NULL, "id1", "qw", "rogue", "fte"}, - {"Nexuiz", "nexuiz", "-nexuiz", "nexuiz.exe", NEXCFG, "id1", "qw", "data", "fte"}, + {"Nexuiz", "nexuiz", "-nexuiz", "nexuiz.exe", NEXCFG, "data", "ftedata"}, //supported commercial mods (some are currently only partially supported) {"FTE-Hexen2", "hexen", "-hexen2", "data1/pak0.pak", NULL, "data1", "fte"}, - {"FTE-Quake2", "q2", "-q2", "baseq2/pak0.pak", NULL, "baseq2", "fte"}, - {"FTE-Quake3", "q3", "-q3", "baseq3/pak0.pk3", NULL, "baseq3", "fte"}, + {"FTE-Quake2", "q2", "-q2", "baseq2/pak0.pak", NULL, "baseq2", "fteq2"}, + {"FTE-Quake3", "q3", "-q3", "baseq3/pak0.pk3", NULL, "baseq3", "fteq3"}, {"FTE-JK2", "jk2", "-jk2", "base/assets0.pk3", NULL, "base", "fte"}, - {"FTE-HalfLife", "hl", "-hl", "valve/liblist.gam",NULL, "valve", "fte"}, + {"FTE-HalfLife", "hl", "-halflife", "valve/liblist.gam",NULL, "valve", "ftehl"}, {NULL} }; //space-seperate pk3 names followed by space-seperated crcs //note that we'll need to reorder and filter out files that don't match the crc. -void FS_ForceToPure(char *str, char *crcs, int seed) +void FS_ForceToPure(const char *str, const char *crcs, int seed) { //pure files are more important than non-pure. @@ -3050,8 +1884,9 @@ void FS_ForceToPure(char *str, char *crcs, int seed) FS_FlushFSHash(); } -char *FS_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum) -{ +char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum) +{ //this is for q3 compatibility. + flocation_t loc; int numpaks = 0; searchpath_t *sp; @@ -3133,7 +1968,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) com_base_searchpaths = com_searchpaths; if (oldpaths->funcs == &osfilefuncs) - COM_AddGameDirectory(oldpaths->purepath, oldpaths->handle, reloadflags); + FS_AddGameDirectory(oldpaths->purepath, oldpaths->handle, reloadflags); oldpaths->funcs->ClosePath(oldpaths->handle); Z_Free(oldpaths); @@ -3151,7 +1986,7 @@ void FS_UnloadPackFiles(void) void FS_ReloadPackFiles(void) { - FS_ReloadPackFilesFlags((unsigned int)-1); + FS_ReloadPackFilesFlags(~0); } void FS_ReloadPackFiles_f(void) @@ -3159,12 +1994,12 @@ void FS_ReloadPackFiles_f(void) if (atoi(Cmd_Argv(1))) FS_ReloadPackFilesFlags(atoi(Cmd_Argv(1))); else - FS_ReloadPackFilesFlags((unsigned int)-1); + FS_ReloadPackFilesFlags(~0); } #ifdef _WIN32 #include -qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen) +qboolean Sys_FindGameData(const char *gamename, char *basepath, int basepathlen) { if (!strcmp(gamename, "q1")) { @@ -3265,7 +2100,7 @@ qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen) } */ - if (!strcmp(gamename, "h3")) + if (!strcmp(gamename, "h2")) { //try and find it via steam //reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath @@ -3281,6 +2116,26 @@ qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen) } #endif +void FS_Shutdown(void) +{ + searchpath_t *next; + FS_FlushFSHash(); + + // + // free up any current game dir info + // + while (com_searchpaths) + { + com_searchpaths->funcs->ClosePath(com_searchpaths->handle); + next = com_searchpaths->next; + Z_Free (com_searchpaths); + com_searchpaths = next; + } + + com_fschanged = true; + +} + /* ================ COM_InitFilesystem @@ -3296,6 +2151,8 @@ void COM_InitFilesystem (void) int gamenum=-1; + FS_RegisterDefaultFileSystems(); + Cmd_AddCommand("fs_restart", FS_ReloadPackFiles_f); // @@ -3322,6 +2179,7 @@ void COM_InitFilesystem (void) Cvar_Register(&com_gamename, "evil hacks"); + Cvar_Register(&com_modname, "evil hacks"); //identify the game from a telling file for (i = 0; gamemode_info[i].gamename; i++) { @@ -3335,7 +2193,7 @@ void COM_InitFilesystem (void) break; } } - //use the game based on an exe name over the filesystem one. + //use the game based on an exe name over the filesystem one (could easily have multiple fs path matches). for (i = 0; gamemode_info[i].gamename; i++) { if (strstr(com_argv[0], gamemode_info[i].exename)) @@ -3415,6 +2273,19 @@ void COM_InitFilesystem (void) FreeLibrary(shfolder); } + if (!*com_homedir) + { + ev = getenv("USERPROFILE"); + if (ev) + Q_snprintfz(com_homedir, sizeof(com_homedir), "%s/My Documents/My Games/%s/", ev, FULLENGINENAME); + } + +#ifdef NPQTV + if (!*com_homedir) + Q_snprintfz(com_homedir, sizeof(com_homedir), "/%s/", ev, FULLENGINENAME); + //as a browser plugin, always use their home directory + usehome = true; +#else if (winver >= 0x6) // Windows Vista and above usehome = true; // always use home directory by default, as Vista+ mimics this behavior anyway else if (winver >= 0x5) // Windows 2000/XP/2003 @@ -3462,13 +2333,7 @@ void COM_InitFilesystem (void) FreeLibrary(advapi32); } } - - if (!*com_homedir) - { - ev = getenv("USERPROFILE"); - if (ev) - Q_snprintfz(com_homedir, sizeof(com_homedir), "%s/My Documents/My Games/%s/", ev, FULLENGINENAME); - } +#endif } #else //yay for unix!. @@ -3502,7 +2367,9 @@ void COM_InitFilesystem (void) { do //use multiple -basegames { - COM_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), (unsigned int)-1); + FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), ~0); + if (*com_homedir) + FS_AddGameDirectory (com_argv[i+1], va("%s%s", com_homedir, com_argv[i+1]), ~0); i = COM_CheckNextParm ("-basegame", i); } @@ -3510,30 +2377,55 @@ void COM_InitFilesystem (void) } else { - if (gamemode_info[gamenum].dir1) - COM_AddGameDirectory (gamemode_info[gamenum].dir1, va("%s%s", com_quakedir, gamemode_info[gamenum].dir1), (unsigned int)-1); - if (gamemode_info[gamenum].dir2) - COM_AddGameDirectory (gamemode_info[gamenum].dir2, va("%s%s", com_quakedir, gamemode_info[gamenum].dir2), (unsigned int)-1); - if (gamemode_info[gamenum].dir3) - COM_AddGameDirectory (gamemode_info[gamenum].dir3, va("%s%s", com_quakedir, gamemode_info[gamenum].dir3), (unsigned int)-1); - if (gamemode_info[gamenum].dir4) - COM_AddGameDirectory (gamemode_info[gamenum].dir4, va("%s%s", com_quakedir, gamemode_info[gamenum].dir4), (unsigned int)-1); + for (i = 0; i < sizeof(gamemode_info[gamenum].dir)/sizeof(gamemode_info[gamenum].dir[0]); i++) + { + if (gamemode_info[gamenum].dir[i]) + { + FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_quakedir, gamemode_info[gamenum].dir[i]), ~0); + if (*com_homedir) + FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_homedir, gamemode_info[gamenum].dir[i]), ~0); + } + } } - if (*com_homedir) - COM_AddGameDirectory ("fte", va("%sfte", com_homedir), (unsigned int)-1); - // any set gamedirs will be freed up to here com_base_searchpaths = com_searchpaths; + //-game specifies the mod gamedir to use in NQ i = COM_CheckParm ("-game"); //effectivly replace with +gamedir x (But overridable) if (i && i < com_argc-1) { - COM_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), (unsigned int)-1); + COM_Gamedir(com_argv[i+1]); + } -#ifndef CLIENTONLY - Info_SetValueForStarKey (svs.info, "*gamedir", com_argv[i+1], MAX_SERVERINFO_STRING); -#endif + //+gamedir specifies the mod gamedir to use in QW + //hack - we parse the commandline after the config so commandline always overrides + //but this means ktpro/server.cfg (for example) is not found + //so if they specify a gamedir on the commandline, let the default configs be loaded from that gamedir + //note that -game +gamedir will result in both being loaded. but hey, who cares + i = COM_CheckParm ("+gamedir"); //effectivly replace with +gamedir x (But overridable) + if (i && i < com_argc-1) + { + COM_Gamedir(com_argv[i+1]); } } + + + + +//this is at the bottom of the file to ensure these globals are not used elsewhere +extern searchpathfuncs_t packfilefuncs; +extern searchpathfuncs_t zipfilefuncs; +extern searchpathfuncs_t doomwadfilefuncs; +void FS_RegisterDefaultFileSystems(void) +{ + FS_RegisterFileSystemType("pak", &packfilefuncs); +#ifdef AVAIL_ZLIB + FS_RegisterFileSystemType("pk3", &zipfilefuncs); + FS_RegisterFileSystemType("pk4", &zipfilefuncs); +#endif +#ifdef DOOMWADS + FS_RegisterFileSystemType("wad", &doomwadfilefuncs); +#endif +} \ No newline at end of file diff --git a/engine/common/fs.h b/engine/common/fs.h new file mode 100644 index 000000000..7f3cd65c5 --- /dev/null +++ b/engine/common/fs.h @@ -0,0 +1,30 @@ +#include "hash.h" +extern hashtable_t filesystemhash; //this table is the one to build your hash references into +extern int fs_hash_dups; //for tracking efficiency. no functional use. +extern int fs_hash_files; //for tracking efficiency. no functional use. + + +typedef struct { + void (*PrintPath)(void *handle); + void (*ClosePath)(void *handle); + void (*BuildHash)(void *handle); + qboolean (*FindFile)(void *handle, flocation_t *loc, const char *name, void *hashedresult); //true if found (hashedresult can be NULL) + //note that if rawfile and offset are set, many Com_FileOpens will read the raw file + //otherwise ReadFile will be called instead. + void (*ReadFile)(void *handle, flocation_t *loc, char *buffer); //reads the entire file in one go (size comes from loc, so make sure the loc is valid, this is for performance with compressed archives) + int (*EnumerateFiles)(void *handle, const char *match, int (*func)(const char *, int, void *), void *parm); + + void *(*OpenNew)(vfsfile_t *file, const char *desc); //returns a handle to a new pak/path + + int (*GeneratePureCRC) (void *handle, int seed, int usepure); + + vfsfile_t *(*OpenVFS)(void *handle, flocation_t *loc, const char *mode); +} searchpathfuncs_t; + +//the stdio filesystem is special as that's the starting point of the entire filesystem +//warning: the handle is known to be a string pointer to the dir name +extern searchpathfuncs_t osfilefuncs; +vfsfile_t *VFSOS_Open(const char *osname, const char *mode); + +int FS_RegisterFileSystemType(const char *extension, searchpathfuncs_t *funcs); +void FS_UnRegisterFileSystemType(int idx); \ No newline at end of file diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c new file mode 100644 index 000000000..abe4fc388 --- /dev/null +++ b/engine/common/fs_pak.c @@ -0,0 +1,544 @@ +#include "quakedef.h" +#include "fs.h" + +// +// in memory +// + +typedef struct +{ + char name[MAX_QPATH]; + int filepos, filelen; + + bucket_t bucket; +} packfile_t; + +typedef struct pack_s +{ + char descname[MAX_OSPATH]; + vfsfile_t *handle; + unsigned int filepos; //the pos the subfiles left it at (to optimize calls to vfs_seek) + int numfiles; + packfile_t *files; + int references; //seeing as all vfiles from a pak file use the parent's vfsfile, we need to keep the parent open until all subfiles are closed. +} pack_t; + +// +// on disk +// +typedef struct +{ + char name[56]; + int filepos, filelen; +} dpackfile_t; + +typedef struct +{ + int filepos, filelen; + char name[8]; +} dwadfile_t; + +typedef struct +{ + char id[4]; + int dirofs; + int dirlen; +} dpackheader_t; + +typedef struct +{ + char id[4]; + int dirlen; + int dirofs; +} dwadheader_t; + +#define MAX_FILES_IN_PACK 2048 + +void FSPAK_PrintPath(void *handle) +{ + pack_t *pak = handle; + + if (pak->references != 1) + Con_Printf("%s (%i)\n", pak->descname, pak->references-1); + else + Con_Printf("%s\n", pak->descname); +} +void FSPAK_ClosePath(void *handle) +{ + pack_t *pak = handle; + + pak->references--; + if (pak->references > 0) + return; //not free yet + + + VFS_CLOSE (pak->handle); + if (pak->files) + Z_Free(pak->files); + Z_Free(pak); +} +void FSPAK_BuildHash(void *handle) +{ + pack_t *pak = handle; + int i; + + for (i = 0; i < pak->numfiles; i++) + { + if (!Hash_GetInsensative(&filesystemhash, pak->files[i].name)) + { + fs_hash_files++; + Hash_AddInsensative(&filesystemhash, pak->files[i].name, &pak->files[i], &pak->files[i].bucket); + } + else + fs_hash_dups++; + } +} +qboolean FSPAK_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +{ + packfile_t *pf = hashedresult; + int i, len; + pack_t *pak = handle; + +// look through all the pak file elements + + if (pf) + { //is this a pointer to a file in this pak? + if (pf < pak->files || pf > pak->files + pak->numfiles) + return false; //was found in a different path + } + else + { + for (i=0 ; inumfiles ; i++) //look for the file + { + if (!strcmp (pak->files[i].name, filename)) + { + pf = &pak->files[i]; + break; + } + } + } + + if (pf) + { + len = pf->filelen; + if (loc) + { + loc->index = pf - pak->files; + snprintf(loc->rawname, sizeof(loc->rawname), "%s", pak->descname); + loc->offset = pf->filepos; + loc->len = pf->filelen; + } + return true; + } + return false; +} +int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) +{ + pack_t *pak = handle; + int num; + + for (num = 0; num<(int)pak->numfiles; num++) + { + if (wildcmp(match, pak->files[num].name)) + { + if (!func(pak->files[num].name, pak->files[num].filelen, parm)) + return false; + } + } + + return true; +} +/* +================= +COM_LoadPackFile + +Takes an explicit (not game tree related) path to a pak file. + +Loads the header and directory, adding the files at the beginning +of the list so they override previous pack files. +================= +*/ +void *FSPAK_LoadPackFile (vfsfile_t *file, const char *desc) +{ + dpackheader_t header; + int i; +// int j; + packfile_t *newfiles; + int numpackfiles; + pack_t *pack; + vfsfile_t *packhandle; + dpackfile_t info; + int read; +// unsigned short crc; + + packhandle = file; + if (packhandle == NULL) + return NULL; + + VFS_READ(packhandle, &header, sizeof(header)); + if (header.id[0] != 'P' || header.id[1] != 'A' + || header.id[2] != 'C' || header.id[3] != 'K') + { + VFS_CLOSE(packhandle); + return NULL; +// Sys_Error ("%s is not a packfile", packfile); + } + header.dirofs = LittleLong (header.dirofs); + header.dirlen = LittleLong (header.dirlen); + + numpackfiles = header.dirlen / sizeof(dpackfile_t); + +// if (numpackfiles > MAX_FILES_IN_PACK) +// Sys_Error ("%s has %i files", packfile, numpackfiles); + +// if (numpackfiles != PAK0_COUNT) +// com_modified = true; // not the original file + + newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t)); + + VFS_SEEK(packhandle, header.dirofs); +// fread (&info, 1, header.dirlen, packhandle); + +// crc the directory to check for modifications +// crc = QCRC_Block((qbyte *)info, header.dirlen); + + +// QCRC_Init (&crc); + + pack = (pack_t*)Z_Malloc (sizeof (pack_t)); +// parse the directory + for (i=0 ; idescname, desc); + pack->handle = packhandle; + pack->numfiles = numpackfiles; + pack->files = newfiles; + pack->filepos = 0; + VFS_SEEK(packhandle, pack->filepos); + + pack->references++; + + Con_TPrintf (TL_ADDEDPACKFILE, desc, numpackfiles); + return pack; +} + + +typedef struct { + vfsfile_t funcs; + pack_t *parentpak; + unsigned long startpos; + unsigned long length; + unsigned long currentpos; +} vfspack_t; +int VFSPAK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread) +{ + vfspack_t *vfsp = (vfspack_t*)vfs; + int read; + + if (bytestoread == 0) + return 0; + + if (vfsp->currentpos - vfsp->startpos + bytestoread > vfsp->length) + bytestoread = vfsp->length - (vfsp->currentpos - vfsp->startpos); + if (bytestoread <= 0) + { + return -1; + } + + if (vfsp->parentpak->filepos != vfsp->currentpos) + VFS_SEEK(vfsp->parentpak->handle, vfsp->currentpos); + read = VFS_READ(vfsp->parentpak->handle, buffer, bytestoread); + vfsp->currentpos += read; + vfsp->parentpak->filepos = vfsp->currentpos; + + return read; +} +int VFSPAK_WriteBytes (struct vfsfile_s *vfs, const void *buffer, int bytestoread) +{ //not supported. + Sys_Error("Cannot write to pak files\n"); + return 0; +} +qboolean VFSPAK_Seek (struct vfsfile_s *vfs, unsigned long pos) +{ + vfspack_t *vfsp = (vfspack_t*)vfs; + if (pos < 0 || pos > vfsp->length) + return false; + vfsp->currentpos = pos + vfsp->startpos; + + return true; +} +unsigned long VFSPAK_Tell (struct vfsfile_s *vfs) +{ + vfspack_t *vfsp = (vfspack_t*)vfs; + return vfsp->currentpos - vfsp->startpos; +} +unsigned long VFSPAK_GetLen (struct vfsfile_s *vfs) +{ + vfspack_t *vfsp = (vfspack_t*)vfs; + return vfsp->length; +} +void VFSPAK_Close(vfsfile_t *vfs) +{ + vfspack_t *vfsp = (vfspack_t*)vfs; + FSPAK_ClosePath(vfsp->parentpak); //tell the parent that we don't need it open any more (reference counts) + Z_Free(vfsp); //free ourselves. +} +vfsfile_t *FSPAK_OpenVFS(void *handle, flocation_t *loc, const char *mode) +{ + pack_t *pack = (pack_t*)handle; + vfspack_t *vfs; + + if (strcmp(mode, "rb")) + return NULL; //urm, unable to write/append + + vfs = Z_Malloc(sizeof(vfspack_t)); + + vfs->parentpak = pack; + vfs->parentpak->references++; + + vfs->startpos = loc->offset; + vfs->length = loc->len; + vfs->currentpos = vfs->startpos; + + vfs->funcs.Close = VFSPAK_Close; + vfs->funcs.GetLen = VFSPAK_GetLen; + vfs->funcs.ReadBytes = VFSPAK_ReadBytes; + vfs->funcs.Seek = VFSPAK_Seek; + vfs->funcs.Tell = VFSPAK_Tell; + vfs->funcs.WriteBytes = VFSPAK_WriteBytes; //not supported + + return (vfsfile_t *)vfs; +} + +void FSPAK_ReadFile(void *handle, flocation_t *loc, char *buffer) +{ + vfsfile_t *f; + f = FSPAK_OpenVFS(handle, loc, "rb"); + if (!f) //err... + return; + VFS_READ(f, buffer, loc->len); + VFS_CLOSE(f); +/* + FILE *f; + f = fopen(loc->rawname, "rb"); + if (!f) //err... + return; + fseek(f, loc->offset, SEEK_SET); + fread(buffer, 1, loc->len, f); + fclose(f); +*/ +} + +searchpathfuncs_t packfilefuncs = { + FSPAK_PrintPath, + FSPAK_ClosePath, + FSPAK_BuildHash, + FSPAK_FLocate, + FSPAK_ReadFile, + FSPAK_EnumerateFiles, + FSPAK_LoadPackFile, + NULL, + FSPAK_OpenVFS +}; + + + +#ifdef DOOMWADS +void *FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, char *desc) +{ + dwadheader_t header; + int i; + packfile_t *newfiles; + int numpackfiles; + pack_t *pack; + dwadfile_t info; + + int section=0; + char sectionname[MAX_QPATH]; + char filename[52]; + char neatwadname[52]; + + if (packhandle == NULL) + return NULL; + + VFS_READ(packhandle, &header, sizeof(header)); + if (header.id[1] != 'W' || header.id[2] != 'A' || header.id[3] != 'D') + return NULL; //not a doom wad + + //doom wads come in two sorts. iwads and pwads. + //iwads are the master wads, pwads are meant to replace parts of the master wad. + //this is awkward, of course. + //we ignore the i/p bit for the most part, but with maps, pwads are given a prefixed name. + if (header.id[0] == 'I') + *neatwadname = '\0'; + else if (header.id[0] == 'P') + { + COM_FileBase(desc, neatwadname, sizeof(neatwadname)); + strcat(neatwadname, "#"); + } + else + return NULL; + + header.dirofs = LittleLong (header.dirofs); + header.dirlen = LittleLong (header.dirlen); + + numpackfiles = header.dirlen; + newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t)); + VFS_SEEK(packhandle, header.dirofs); + + //doom wads are awkward. + //they have no directory structure, except for start/end 'files'. + //they follow along the lines of lumps after the parent name. + //a map is the name of that map, and then a squence of the lumps that form that map (found by next-with-that-name). + //this is a problem for a real virtual filesystem, so we add a hack to recognise special names and expand them specially. + for (i=0 ; idescname, desc); + pack->handle = packhandle; + pack->numfiles = numpackfiles; + pack->files = newfiles; + pack->filepos = 0; + VFS_SEEK(packhandle, pack->filepos); + + pack->references++; + + Con_TPrintf (TL_ADDEDPACKFILE, desc, numpackfiles); + return pack; +} +searchpathfuncs_t doomwadfilefuncs = { + FSPAK_PrintPath, + FSPAK_ClosePath, + FSPAK_BuildHash, + FSPAK_FLocate, + FSPAK_ReadFile, + FSPAK_EnumerateFiles, + FSPAK_LoadDoomWadFile, + NULL, + FSPAK_OpenVFS +}; +#endif \ No newline at end of file diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c new file mode 100644 index 000000000..9c0ebc1e1 --- /dev/null +++ b/engine/common/fs_stdio.c @@ -0,0 +1,226 @@ +#include "quakedef.h" +#include "fs.h" + +typedef struct { + vfsfile_t funcs; + FILE *handle; +} vfsosfile_t; +int VFSOS_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + return fread(buffer, 1, bytestoread, intfile->handle); +} +int VFSOS_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + return fwrite(buffer, 1, bytestoread, intfile->handle); +} +qboolean VFSOS_Seek (struct vfsfile_s *file, unsigned long pos) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + return fseek(intfile->handle, pos, SEEK_SET) == 0; +} +unsigned long VFSOS_Tell (struct vfsfile_s *file) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + return ftell(intfile->handle); +} +void VFSOS_Flush(struct vfsfile_s *file) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + fflush(intfile->handle); +} +unsigned long VFSOS_GetSize (struct vfsfile_s *file) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + + unsigned int curpos; + unsigned int maxlen; + curpos = ftell(intfile->handle); + fseek(intfile->handle, 0, SEEK_END); + maxlen = ftell(intfile->handle); + fseek(intfile->handle, curpos, SEEK_SET); + + return maxlen; +} +void VFSOS_Close(vfsfile_t *file) +{ + vfsosfile_t *intfile = (vfsosfile_t*)file; + fclose(intfile->handle); + Z_Free(file); +} + +vfsfile_t *FS_OpenTemp(void) +{ + FILE *f; + vfsosfile_t *file; + + f = tmpfile(); + if (!f) + return NULL; + + file = Z_Malloc(sizeof(vfsosfile_t)); + file->funcs.ReadBytes = VFSOS_ReadBytes; + file->funcs.WriteBytes = VFSOS_WriteBytes; + file->funcs.Seek = VFSOS_Seek; + file->funcs.Tell = VFSOS_Tell; + file->funcs.GetLen = VFSOS_GetSize; + file->funcs.Close = VFSOS_Close; + file->funcs.Flush = VFSOS_Flush; + file->handle = f; + + return (vfsfile_t*)file; +} + +vfsfile_t *VFSOS_Open(const char *osname, const char *mode) +{ + FILE *f; + vfsosfile_t *file; + qboolean read = !!strchr(mode, 'r'); + qboolean write = !!strchr(mode, 'w'); + qboolean append = !!strchr(mode, 'a'); + qboolean text = !!strchr(mode, 't'); + char newmode[3]; + int modec = 0; + + if (read) + newmode[modec++] = 'r'; + if (write) + newmode[modec++] = 'w'; + if (append) + newmode[modec++] = 'a'; + if (text) + newmode[modec++] = 't'; + else + newmode[modec++] = 'b'; + newmode[modec++] = '\0'; + + f = fopen(osname, newmode); + if (!f) + return NULL; + + file = Z_Malloc(sizeof(vfsosfile_t)); + file->funcs.ReadBytes = strchr(mode, 'r')?VFSOS_ReadBytes:NULL; + file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSOS_WriteBytes:NULL; + file->funcs.Seek = VFSOS_Seek; + file->funcs.Tell = VFSOS_Tell; + file->funcs.GetLen = VFSOS_GetSize; + file->funcs.Close = VFSOS_Close; + file->funcs.Flush = VFSOS_Flush; + file->handle = f; + + return (vfsfile_t*)file; +} + +vfsfile_t *FSOS_OpenVFS(void *handle, flocation_t *loc, const char *mode) +{ + char diskname[MAX_OSPATH]; + + //path is already cleaned, as anything that gets a valid loc needs cleaning up first. + + snprintf(diskname, sizeof(diskname), "%s/%s", (char*)handle, loc->rawname); + + return VFSOS_Open(diskname, mode); +} + +void FSOS_PrintPath(void *handle) +{ + Con_Printf("%s\n", handle); +} +void FSOS_ClosePath(void *handle) +{ + Z_Free(handle); +} +int FSOS_RebuildFSHash(const char *filename, int filesize, void *data) +{ + if (filename[strlen(filename)-1] == '/') + { //this is actually a directory + + char childpath[256]; + sprintf(childpath, "%s*", filename); + Sys_EnumerateFiles((char*)data, childpath, FSOS_RebuildFSHash, data); + return true; + } + if (!Hash_GetInsensative(&filesystemhash, filename)) + { + bucket_t *bucket = (bucket_t*)BZ_Malloc(sizeof(bucket_t) + strlen(filename)+1); + strcpy((char *)(bucket+1), filename); +#ifdef _WIN32 + Q_strlwr((char *)(bucket+1)); +#endif + Hash_AddInsensative(&filesystemhash, (char *)(bucket+1), data, bucket); + + fs_hash_files++; + } + else + fs_hash_dups++; + return true; +} +void FSOS_BuildHash(void *handle) +{ + Sys_EnumerateFiles(handle, "*", FSOS_RebuildFSHash, handle); +} +qboolean FSOS_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +{ + FILE *f; + int len; + char netpath[MAX_OSPATH]; + + + if (hashedresult && (void *)hashedresult != handle) + return false; + +/* + if (!static_registered) + { // if not a registered version, don't ever go beyond base + if ( strchr (filename, '/') || strchr (filename,'\\')) + continue; + } +*/ + +// check a file in the directory tree + snprintf (netpath, sizeof(netpath)-1, "%s/%s",(char*)handle, filename); + + f = fopen(netpath, "rb"); + if (!f) + return false; + + fseek(f, 0, SEEK_END); + len = ftell(f); + fclose(f); + if (loc) + { + loc->len = len; + loc->offset = 0; + loc->index = 0; + Q_strncpyz(loc->rawname, filename, sizeof(loc->rawname)); + } + + return true; +} +void FSOS_ReadFile(void *handle, flocation_t *loc, char *buffer) +{ + FILE *f; + f = fopen(loc->rawname, "rb"); + if (!f) //err... + return; + fseek(f, loc->offset, SEEK_SET); + fread(buffer, 1, loc->len, f); + fclose(f); +} +int FSOS_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) +{ + return Sys_EnumerateFiles(handle, match, func, parm); +} + +searchpathfuncs_t osfilefuncs = { + FSOS_PrintPath, + FSOS_ClosePath, + FSOS_BuildHash, + FSOS_FLocate, + FSOS_ReadFile, + FSOS_EnumerateFiles, + NULL, + NULL, + FSOS_OpenVFS +}; diff --git a/engine/common/fs_zip.c b/engine/common/fs_zip.c new file mode 100644 index 000000000..1919ae141 --- /dev/null +++ b/engine/common/fs_zip.c @@ -0,0 +1,461 @@ +#include "quakedef.h" +#include "fs.h" + +#ifdef AVAIL_ZLIB + +#ifndef ZEXPORT +#define ZEXPORT VARGS +#endif + +#include +#include "unzip.c" + +#ifdef _WIN32 +#pragma comment( lib, "../libs/zlib.lib" ) +#endif + +typedef struct +{ + char name[MAX_QPATH]; + int filepos, filelen; + + bucket_t bucket; +} zpackfile_t; + + +typedef struct zipfile_s +{ + char filename[MAX_QPATH]; + unzFile handle; + int numfiles; + zpackfile_t *files; + +#ifdef HASH_FILESYSTEM + hashtable_t hash; +#endif + + vfsfile_t *raw; + vfsfile_t *currentfile; //our unzip.c can only handle one active file at any one time + //so we have to keep closing and switching. + //slow, but it works. most of the time we'll only have a single file open anyway. + int references; //and a reference count +} zipfile_t; + + +static void FSZIP_PrintPath(void *handle) +{ + zipfile_t *zip = handle; + + if (zip->references != 1) + Con_Printf("%s (%i)\n", zip->filename, zip->references-1); + else + Con_Printf("%s\n", zip->filename); +} +static void FSZIP_ClosePath(void *handle) +{ + zipfile_t *zip = handle; + + if (--zip->references > 0) + return; //not yet time + + unzClose(zip->handle); + if (zip->files) + Z_Free(zip->files); + Z_Free(zip); +} +static void FSZIP_BuildHash(void *handle) +{ + zipfile_t *zip = handle; + int i; + + for (i = 0; i < zip->numfiles; i++) + { + if (!Hash_GetInsensative(&filesystemhash, zip->files[i].name)) + { + fs_hash_files++; + Hash_AddInsensative(&filesystemhash, zip->files[i].name, &zip->files[i], &zip->files[i].bucket); + } + else + fs_hash_dups++; + } +} +static qboolean FSZIP_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +{ + zpackfile_t *pf = hashedresult; + int i, len; + zipfile_t *zip = handle; + +// look through all the pak file elements + + if (pf) + { //is this a pointer to a file in this pak? + if (pf < zip->files || pf >= zip->files + zip->numfiles) + return false; //was found in a different path + } + else + { + for (i=0 ; inumfiles ; i++) //look for the file + { + if (!stricmp (zip->files[i].name, filename)) + { + pf = &zip->files[i]; + break; + } + } + } + + if (pf) + { + len = pf->filelen; + if (loc) + { + loc->index = pf - zip->files; + strcpy(loc->rawname, zip->filename); + loc->offset = pf->filepos; + loc->len = pf->filelen; + + unzLocateFileMy (zip->handle, loc->index, zip->files[loc->index].filepos); + loc->offset = unzGetCurrentFileUncompressedPos(zip->handle); +// if (loc->offset<0) +// { //file not found, or is compressed. +// *loc->rawname = '\0'; +// loc->offset=0; +// } + } + return true; + } + return false; +} + +static void FSZIP_ReadFile(void *handle, flocation_t *loc, char *buffer) +{ + zipfile_t *zip = handle; + int err; + + unzLocateFileMy (zip->handle, loc->index, zip->files[loc->index].filepos); + + unzOpenCurrentFile (zip->handle); + err = unzReadCurrentFile (zip->handle, buffer, zip->files[loc->index].filelen); + unzCloseCurrentFile (zip->handle); + + if (err!=zip->files[loc->index].filelen) + { + Con_Printf ("Can't extract file \"%s:%s\" (corrupt)\n", zip->filename, zip->files[loc->index].name); + return; + } + return; +} + +static int FSZIP_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) +{ + zipfile_t *zip = handle; + int num; + + for (num = 0; num<(int)zip->numfiles; num++) + { + if (wildcmp(match, zip->files[num].name)) + { + if (!func(zip->files[num].name, zip->files[num].filelen, parm)) + return false; + } + } + + return true; +} + +/* +================= +COM_LoadZipFile + +Takes an explicit (not game tree related) path to a pak file. + +Loads the header and directory, adding the files at the beginning +of the list so they override previous pack files. +================= +*/ +static void *FSZIP_LoadZipFile (vfsfile_t *packhandle, const char *desc) +{ + int i; + int nextfileziphandle; + + zipfile_t *zip; + zpackfile_t *newfiles; + + unz_global_info globalinf = {0}; + unz_file_info file_info; + + zip = Z_Malloc(sizeof(zipfile_t)); + Q_strncpyz(zip->filename, desc, sizeof(zip->filename)); + zip->handle = unzOpen ((zip->raw = packhandle)); + if (!zip->handle) + { + Z_Free(zip); + Con_TPrintf (TL_COULDNTOPENZIP, desc); + return NULL; + } + + unzGetGlobalInfo (zip->handle, &globalinf); + + zip->numfiles = globalinf.number_entry; + + zip->files = newfiles = Z_Malloc (zip->numfiles * sizeof(zpackfile_t)); + for (i = 0; i < zip->numfiles; i++) + { + if (unzGetCurrentFileInfo (zip->handle, &file_info, newfiles[i].name, sizeof(newfiles[i].name), NULL, 0, NULL, 0) != UNZ_OK) + Con_Printf("Zip Error\n"); + Q_strlwr(newfiles[i].name); + newfiles[i].filelen = file_info.uncompressed_size; + newfiles[i].filepos = file_info.c_offset; + + nextfileziphandle = unzGoToNextFile (zip->handle); + if (nextfileziphandle == UNZ_END_OF_LIST_OF_FILE) + break; + else if (nextfileziphandle != UNZ_OK) + Con_Printf("Zip Error\n"); + } + + zip->references = 1; + zip->currentfile = NULL; + + Con_TPrintf (TL_ADDEDZIPFILE, desc, zip->numfiles); + return zip; +} + +int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) +{ + zipfile_t *zip = handle; + unz_file_info file_info; + + int *filecrcs; + int numcrcs=0; + int i; + + filecrcs = BZ_Malloc((zip->numfiles+1)*sizeof(int)); + filecrcs[numcrcs++] = seed; + + unzGoToFirstFile(zip->handle); + for (i = 0; i < zip->numfiles; i++) + { + if (zip->files[i].filelen>0) + { + unzGetCurrentFileInfo (zip->handle, &file_info, NULL, 0, NULL, 0, NULL, 0); + filecrcs[numcrcs++] = file_info.crc; + } + unzGoToNextFile (zip->handle); + } + + if (crctype) + return Com_BlockChecksum(filecrcs, numcrcs*sizeof(int)); + else + return Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int)); +} + +typedef struct { + vfsfile_t funcs; + + vfsfile_t *defer; + + //in case we're forced away. + zipfile_t *parent; + qboolean iscompressed; + int pos; + int length; //try and optimise some things + int index; + int startpos; +} vfszip_t; +void VFSZIP_MakeActive(vfszip_t *vfsz) +{ + int i; + char buffer[8192]; //must be power of two + + if ((vfszip_t*)vfsz->parent->currentfile == vfsz) + return; //already us + if (vfsz->parent->currentfile) + unzCloseCurrentFile(vfsz->parent->handle); + + unzLocateFileMy(vfsz->parent->handle, vfsz->index, vfsz->startpos); + unzOpenCurrentFile(vfsz->parent->handle); + + + if (vfsz->pos > 0) + { + Con_DPrintf("VFSZIP_MakeActive: Shockingly inefficient\n"); + + //now we need to seek up to where we had previously gotten to. + for (i = 0; i < vfsz->pos-sizeof(buffer); i++) + unzReadCurrentFile(vfsz->parent->handle, buffer, sizeof(buffer)); + unzReadCurrentFile(vfsz->parent->handle, buffer, vfsz->pos - i); + } + + vfsz->parent->currentfile = (vfsfile_t*)vfsz; +} + +int VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +{ + int read; + vfszip_t *vfsz = (vfszip_t*)file; + + if (vfsz->defer) + return VFS_READ(vfsz->defer, buffer, bytestoread); + + if (vfsz->iscompressed) + { + VFSZIP_MakeActive(vfsz); + read = unzReadCurrentFile(vfsz->parent->handle, buffer, bytestoread); + } + else + { + if (vfsz->parent->currentfile != file) + { + unzCloseCurrentFile(vfsz->parent->handle); + VFS_SEEK(vfsz->parent->raw, vfsz->pos+vfsz->startpos); + vfsz->parent->currentfile = file; + } + read = VFS_READ(vfsz->parent->raw, buffer, bytestoread); + } + + vfsz->pos += read; + return read; +} +int VFSZIP_WriteBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +{ + Sys_Error("VFSZIP_WriteBytes: Not supported\n"); + return 0; +} +qboolean VFSZIP_Seek (struct vfsfile_s *file, unsigned long pos) +{ + vfszip_t *vfsz = (vfszip_t*)file; + + if (vfsz->defer) + return VFS_SEEK(vfsz->defer, pos); + + //This is *really* inefficient + if (vfsz->parent->currentfile == file) + { + if (vfsz->iscompressed) + { //if they're going to seek on a file in a zip, let's just copy it out + char buffer[8192]; + unsigned int chunk; + unsigned int i; + unsigned int length; + + vfsz->defer = FS_OpenTemp(); + if (vfsz->defer) + { + unzCloseCurrentFile(vfsz->parent->handle); + vfsz->parent->currentfile = NULL; //make it not us + + length = vfsz->length; + i = 0; + vfsz->pos = 0; + VFSZIP_MakeActive(vfsz); + while (1) + { + chunk = length - i; + if (chunk > sizeof(buffer)) + chunk = sizeof(buffer); + if (chunk == 0) + break; + unzReadCurrentFile(vfsz->parent->handle, buffer, chunk); + VFS_WRITE(vfsz->defer, buffer, chunk); + + i += chunk; + } + } + } + + unzCloseCurrentFile(vfsz->parent->handle); + vfsz->parent->currentfile = NULL; //make it not us + + if (vfsz->defer) + return VFS_SEEK(vfsz->defer, pos); + } + + + + if (pos < 0 || pos > vfsz->length) + return false; + vfsz->pos = pos; + + return true; +} +unsigned long VFSZIP_Tell (struct vfsfile_s *file) +{ + vfszip_t *vfsz = (vfszip_t*)file; + + if (vfsz->defer) + return VFS_TELL(vfsz->defer); + + return vfsz->pos; +} +unsigned long VFSZIP_GetLen (struct vfsfile_s *file) +{ + vfszip_t *vfsz = (vfszip_t*)file; + return vfsz->length; +} +void VFSZIP_Close (struct vfsfile_s *file) +{ + vfszip_t *vfsz = (vfszip_t*)file; + + if (vfsz->parent->currentfile == file) + vfsz->parent->currentfile = NULL; //make it not us + + if (vfsz->defer) + VFS_CLOSE(vfsz->defer); + + FSZIP_ClosePath(vfsz->parent); + Z_Free(vfsz); +} + +vfsfile_t *FSZIP_OpenVFS(void *handle, flocation_t *loc, const char *mode) +{ + int rawofs; + zipfile_t *zip = handle; + vfszip_t *vfsz; + + if (strcmp(mode, "rb")) + return NULL; //urm, unable to write/append + + vfsz = Z_Malloc(sizeof(vfszip_t)); + + vfsz->parent = zip; + vfsz->index = loc->index; + vfsz->startpos = zip->files[loc->index].filepos; + vfsz->length = loc->len; + + vfsz->funcs.Close = VFSZIP_Close; + vfsz->funcs.GetLen = VFSZIP_GetLen; + vfsz->funcs.ReadBytes = VFSZIP_ReadBytes; + vfsz->funcs.Seek = VFSZIP_Seek; + vfsz->funcs.Tell = VFSZIP_Tell; + vfsz->funcs.WriteBytes = NULL; + vfsz->funcs.seekingisabadplan = true; + + unzLocateFileMy(vfsz->parent->handle, vfsz->index, vfsz->startpos); + rawofs = unzGetCurrentFileUncompressedPos(zip->handle); + vfsz->iscompressed = rawofs<0; + if (!vfsz->iscompressed) + { + vfsz->startpos = rawofs; + VFS_SEEK(zip->raw, vfsz->startpos); + vfsz->parent->currentfile = (vfsfile_t*)vfsz; + } + + zip->references++; + + return (vfsfile_t*)vfsz; +} + +searchpathfuncs_t zipfilefuncs = { + FSZIP_PrintPath, + FSZIP_ClosePath, + FSZIP_BuildHash, + FSZIP_FLocate, + FSZIP_ReadFile, + FSZIP_EnumerateFiles, + FSZIP_LoadZipFile, + FSZIP_GeneratePureCRC, + FSZIP_OpenVFS +}; + +#endif \ No newline at end of file diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 631e3584f..6201d96ab 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -388,15 +388,24 @@ void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) sr = sin(angle); cr = cos(angle); - forward[0] = cp*cy; - forward[1] = cp*sy; - forward[2] = -sp; - right[0] = (-1*sr*sp*cy+-1*cr*-sy); - right[1] = (-1*sr*sp*sy+-1*cr*cy); - right[2] = -1*sr*cp; - up[0] = (cr*sp*cy+-sr*-sy); - up[1] = (cr*sp*sy+-sr*cy); - up[2] = cr*cp; + if (forward) + { + forward[0] = cp*cy; + forward[1] = cp*sy; + forward[2] = -sp; + } + if (right) + { + right[0] = (-1*sr*sp*cy+-1*cr*-sy); + right[1] = (-1*sr*sp*sy+-1*cr*cy); + right[2] = -1*sr*cp; + } + if (up) + { + up[0] = (cr*sp*cy+-sr*-sy); + up[1] = (cr*sp*sy+-sr*cy); + up[2] = cr*cp; + } } int VectorCompare (vec3_t v1, vec3_t v2) diff --git a/engine/common/net.h b/engine/common/net.h index f46af3d0c..41dc62b70 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -89,13 +89,13 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b); qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b); char *NET_AdrToString (char *s, int len, netadr_t a); char *NET_BaseAdrToString (char *s, int len, netadr_t a); -qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr); -qboolean NET_StringToAdr (char *s, netadr_t *a); +qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr); +qboolean NET_StringToAdr (const char *s, netadr_t *a); qboolean NET_IsClientLegal(netadr_t *adr); qboolean NET_IsLoopBackAddress (netadr_t adr); -qboolean NET_StringToAdrMasked (char *s, netadr_t *a, netadr_t *amask); +qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask); char *NET_AdrToStringMasked (char *s, int len, netadr_t a, netadr_t amask); void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits); qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask); diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 1867ceca8..e1d9e79da 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -563,7 +563,7 @@ any form of ipv6, including port number. sscanf (copy, "%x", &val); \ ((struct sockaddr_ipx *)sadr)->dest = val -qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr) +qboolean NET_StringToSockaddr (const char *s, struct sockaddr_qstorage *sadr) { struct hostent *h; char *colon; @@ -619,9 +619,12 @@ qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr) error = EAI_NONAME; else { - *port = 0; - error = pgetaddrinfo(s+1, port+2, &udp6hint, &addrinfo); - *port = ']'; + len = port - (s+1); + if (len >= sizeof(dupbase)) + len = sizeof(dupbase)-1; + strncpy(dupbase, s+1, len); + dupbase[len] = '\0'; + error = pgetaddrinfo(dupbase, port+2, &udp6hint, &addrinfo); } } else @@ -709,7 +712,7 @@ dblbreak: accepts anything that NET_StringToSockaddr accepts plus certain url schemes including: tcp, irc */ -qboolean NET_StringToAdr (char *s, netadr_t *a) +qboolean NET_StringToAdr (const char *s, netadr_t *a) { struct sockaddr_qstorage sadr; @@ -872,9 +875,9 @@ void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits) // ParsePartialIPv4: check string to see if it is a partial IPv4 address and // return bits to mask and set netadr_t or 0 if not an address -int ParsePartialIPv4(char *s, netadr_t *a) +int ParsePartialIPv4(const char *s, netadr_t *a) { - char *colon = NULL; + const char *colon = NULL; char *address = a->address.ip; int bits = 8; @@ -920,7 +923,7 @@ int ParsePartialIPv4(char *s, netadr_t *a) // NET_StringToAdrMasked: extension to NET_StringToAdr to handle IP addresses // with masks or integers representing the bit masks -qboolean NET_StringToAdrMasked (char *s, netadr_t *a, netadr_t *amask) +qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask) { char t[64]; char *spoint; @@ -1300,10 +1303,10 @@ void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) #define FTENET_ADDRTYPES 2 typedef struct ftenet_generic_connection_s { - char *name; + const char *name; int (*GetLocalAddress)(struct ftenet_generic_connection_s *con, netadr_t *local, int adridx); - qboolean (*ChangeLocalAddress)(struct ftenet_generic_connection_s *con, char *newaddress); + qboolean (*ChangeLocalAddress)(struct ftenet_generic_connection_s *con, const char *newaddress); qboolean (*GetPacket)(struct ftenet_generic_connection_s *con); qboolean (*SendPacket)(struct ftenet_generic_connection_s *con, int length, void *data, netadr_t to); void (*Close)(struct ftenet_generic_connection_s *con); @@ -1327,7 +1330,7 @@ ftenet_connections_t *FTENET_CreateCollection(qboolean listen) return col; } -qboolean FTENET_AddToCollection(ftenet_connections_t *col, char *name, char *address, ftenet_generic_connection_t *(*establish)(qboolean isserver, char *address)) +qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, const char *address, ftenet_generic_connection_t *(*establish)(qboolean isserver, const char *address)) { int i; if (!col) @@ -1423,7 +1426,7 @@ qboolean FTENET_Loop_SendPacket(ftenet_generic_connection_t *con, int length, vo return false; } -ftenet_generic_connection_t *FTENET_Loop_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_Loop_EstablishConnection(qboolean isserver, const char *address) { ftenet_generic_connection_t *newcon; newcon = Z_Malloc(sizeof(*newcon)); @@ -1626,7 +1629,7 @@ qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length, return true; } -qboolean NET_PortToAdr (int adrfamily, char *s, netadr_t *a) +qboolean NET_PortToAdr (int adrfamily, const char *s, netadr_t *a) { char *e; int port; @@ -1658,7 +1661,7 @@ qboolean NET_PortToAdr (int adrfamily, char *s, netadr_t *a) return false; } -ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, int protocol, qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, int protocol, qboolean isserver, const char *address) { //this is written to support either ipv4 or ipv6, depending on the remote addr. ftenet_generic_connection_t *newcon; @@ -1735,17 +1738,17 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i } #ifdef IPPROTO_IPV6 -ftenet_generic_connection_t *FTENET_UDP6_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_UDP6_EstablishConnection(qboolean isserver, const char *address) { return FTENET_Generic_EstablishConnection(AF_INET6, IPPROTO_UDP, isserver, address); } #endif -ftenet_generic_connection_t *FTENET_UDP4_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_UDP4_EstablishConnection(qboolean isserver, const char *address) { return FTENET_Generic_EstablishConnection(AF_INET, IPPROTO_UDP, isserver, address); } #ifdef USEIPX -ftenet_generic_connection_t *FTENET_IPX_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_IPX_EstablishConnection(qboolean isserver, const char *address) { return FTENET_Generic_EstablishConnection(AF_IPX, NSPROTO_IPX, isserver, address); } @@ -1946,7 +1949,7 @@ void FTENET_TCPConnect_Close(ftenet_generic_connection_t *gcon) FTENET_Generic_Close(gcon); } -ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, qboolean isserver, const char *address) { //this is written to support either ipv4 or ipv6, depending on the remote addr. ftenet_tcpconnect_connection_t *newcon; @@ -2055,13 +2058,13 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, } #ifdef IPPROTO_IPV6 -ftenet_generic_connection_t *FTENET_TCP6Connect_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_TCP6Connect_EstablishConnection(qboolean isserver, const char *address) { return FTENET_TCPConnect_EstablishConnection(AF_INET6, isserver, address); } #endif -ftenet_generic_connection_t *FTENET_TCP4Connect_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_TCP4Connect_EstablishConnection(qboolean isserver, const char *address) { return FTENET_TCPConnect_EstablishConnection(AF_INET, isserver, address); } @@ -2606,7 +2609,7 @@ void FTENET_IRCConnect_Close(ftenet_generic_connection_t *gcon) FTENET_Generic_Close(gcon); } -ftenet_generic_connection_t *FTENET_IRCConnect_EstablishConnection(qboolean isserver, char *address) +ftenet_generic_connection_t *FTENET_IRCConnect_EstablishConnection(qboolean isserver, const char *address) { //this is written to support either ipv4 or ipv6, depending on the remote addr. ftenet_ircconnect_connection_t *newcon; @@ -3254,7 +3257,7 @@ void NET_Init (void) #ifndef SERVERONLY void NET_InitClient(void) { - char *port; + const char *port; int p; port = STRINGIFY(PORT_CLIENT); @@ -3474,7 +3477,7 @@ int VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) return 0; //signal nothing available } } -int VFSTCP_WriteBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +int VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) { tcpfile_t *tf = (tcpfile_t*)file; int len; @@ -3510,7 +3513,7 @@ void VFSTCP_Close (struct vfsfile_s *file) Z_Free(file); } -vfsfile_t *FS_OpenTCP(char *name) +vfsfile_t *FS_OpenTCP(const char *name) { tcpfile_t *newf; int sock; diff --git a/engine/common/plugin.c b/engine/common/plugin.c index aec85c3b0..00b35a637 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -329,10 +329,10 @@ plugin_t *Plug_Load(char *file) return newplug; } -int Plug_Emumerated (char *name, int size, void *param) +int Plug_Emumerated (const char *name, int size, void *param) { char vmname[MAX_QPATH]; - strcpy(vmname, name); + Q_strncpyz(vmname, name, sizeof(vmname)); vmname[strlen(vmname) - strlen(param)] = '\0'; if (!Plug_Load(vmname)) Con_Printf("Couldn't load plugin %s\n", vmname); diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index 40e99212c..a4f195843 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -123,6 +123,8 @@ int PM_PointContents (vec3_t p) model_t *pm; pm = pmove.physents[0].model; + if (!pm) + return FTECONTENTS_EMPTY; pc = pm->funcs.PointContents(pm, p); //we need this for e2m2 - waterjumping on to plats wouldn't work otherwise. for (num = 1; num < pmove.numphysent; num++) diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 4bcd7a3ad..c6afa9ca8 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -469,7 +469,7 @@ void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) //////////////////////////////////////////////////// //File access -#define MAX_QC_FILES 8 +#define MAX_QC_FILES 256 #define FIRST_QC_FILE_INDEX 1000 @@ -496,6 +496,7 @@ void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (i == MAX_QC_FILES) //too many already open { + Con_Printf("qcfopen: too many files open (trying %s)\n", name); G_FLOAT(OFS_RETURN) = -1; return; } @@ -550,6 +551,14 @@ void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; pf_fopen_files[i].prinst = prinst; break; + case 3: + pf_fopen_files[i].bufferlen = 0; + pf_fopen_files[i].data = ""; + pf_fopen_files[i].len = 0; + pf_fopen_files[i].ofs = 0; + G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; + pf_fopen_files[i].prinst = prinst; + break; default: //bad G_FLOAT(OFS_RETURN) = -1; break; @@ -580,6 +589,8 @@ void PF_fclose_i (int fnum) COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); BZ_Free(pf_fopen_files[fnum].data); break; + case 3: + break; } pf_fopen_files[fnum].data = NULL; pf_fopen_files[fnum].prinst = NULL; @@ -606,7 +617,7 @@ void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char c, *s, *o, *max; + char c, *s, *o, *max, *eof; int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; char pr_string_temp[4096]; @@ -632,9 +643,10 @@ void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) //read up to the next \n, ignoring any \rs. o = pr_string_temp; - max = o + MAXTEMPBUFFERLEN-1; + max = o + sizeof(pr_string_temp)-1; s = pf_fopen_files[fnum].data+pf_fopen_files[fnum].ofs; - while(*s) + eof = pf_fopen_files[fnum].data+pf_fopen_files[fnum].len; + while(s < eof) { c = *s++; if (c == '\n') @@ -650,7 +662,7 @@ void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) pf_fopen_files[fnum].ofs = s - pf_fopen_files[fnum].data; - if (!pr_string_temp[0] && !*s) + if (!pr_string_temp[0] && s == eof) G_INT(OFS_RETURN) = 0; //EOF else RETURN_TSTRING(pr_string_temp); @@ -679,20 +691,28 @@ void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) return; //this just isn't ours. } - if (pf_fopen_files[fnum].bufferlen < pf_fopen_files[fnum].ofs + len) + switch(pf_fopen_files[fnum].accessmode) { - char *newbuf; - pf_fopen_files[fnum].bufferlen = pf_fopen_files[fnum].bufferlen*2 + len; - newbuf = BZF_Malloc(pf_fopen_files[fnum].bufferlen); - memcpy(newbuf, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); - BZ_Free(pf_fopen_files[fnum].data); - pf_fopen_files[fnum].data = newbuf; - } + default: + break; + case 1: + case 2: + if (pf_fopen_files[fnum].bufferlen < pf_fopen_files[fnum].ofs + len) + { + char *newbuf; + pf_fopen_files[fnum].bufferlen = pf_fopen_files[fnum].bufferlen*2 + len; + newbuf = BZF_Malloc(pf_fopen_files[fnum].bufferlen); + memcpy(newbuf, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); + BZ_Free(pf_fopen_files[fnum].data); + pf_fopen_files[fnum].data = newbuf; + } - memcpy(pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, msg, len); - if (pf_fopen_files[fnum].len < pf_fopen_files[fnum].ofs + len) - pf_fopen_files[fnum].len = pf_fopen_files[fnum].ofs + len; - pf_fopen_files[fnum].ofs+=len; + memcpy(pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, msg, len); + if (pf_fopen_files[fnum].len < pf_fopen_files[fnum].ofs + len) + pf_fopen_files[fnum].len = pf_fopen_files[fnum].ofs + len; + pf_fopen_files[fnum].ofs+=len; + break; + } } void PF_fcloseall (progfuncs_t *prinst) @@ -815,7 +835,7 @@ void search_close_progs(progfuncs_t *prinst, qboolean complain) prvm_nextsearchhandle = 0; //might as well. } -int search_enumerate(char *name, int fsize, void *parm) +int search_enumerate(const char *name, int fsize, void *parm) { prvmsearch_t *s = parm; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index e73c51eb2..908b45ec6 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -257,6 +257,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcfte_pointparticles 81 // [short] effectnum [vector] start [vector] velocity [short] count #define svcfte_pointparticles1 82 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 +#define svcfte_cgamepacket 83 //DP extended svcs diff --git a/engine/common/q3common.c b/engine/common/q3common.c index 657e54b26..a84474c71 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -186,7 +186,7 @@ typedef struct { int bufferleft; int skip; } vmsearch_t; -static int VMEnum(char *match, int size, void *args) +static int VMEnum(const char *match, int size, void *args) { char *check; int newlen; @@ -210,13 +210,13 @@ static int VMEnum(char *match, int size, void *args) return true; } -static int IfFound(char *match, int size, void *args) +static int IfFound(const char *match, int size, void *args) { *(qboolean*)args = true; return true; } -static int VMEnumMods(char *match, int size, void *args) +static int VMEnumMods(const char *match, int size, void *args) { char *check; char desc[1024]; @@ -227,21 +227,23 @@ static int VMEnumMods(char *match, int size, void *args) newlen = strlen(match)+1; - if (*match && match[newlen-2] != '/') + if (newlen <= 2) return true; - match[newlen-2] = '\0'; - newlen--; - if (!stricmp(match, "baseq3")) + //make sure match is a directory + if (match[newlen-2] != '/') + return true; + + if (!stricmp(match, "baseq3/")) return true; //we don't want baseq3 foundone = false; - Sys_EnumerateFiles(va("%s/%s/", ((vmsearch_t *)args)->dir, match), "*.pk3", IfFound, &foundone); + Sys_EnumerateFiles(va("%s%s/", ((vmsearch_t *)args)->dir, match), "*.pk3", IfFound, &foundone); if (foundone == false) return true; //we only count directories with a pk3 file Q_strncpyz(desc, match, sizeof(desc)); - f = FS_OpenVFS(va("%s/description.txt", match), "rb", FS_ROOT); + f = FS_OpenVFS(va("%sdescription.txt", match), "rb", FS_ROOT); if (f) { VFS_GETS(f, desc, sizeof(desc)); diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 6ae325dfb..6bf673b5d 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -116,7 +116,7 @@ dllhandle_t *QVM_LoadDLL(const char *name, void **vmMain, int (EXPORT_FN *syscal return NULL; // couldn't find one anywhere snprintf (name, sizeof(name), "%s/%s", gpath, dllname); - Con_Printf("Loading native: %s\n", name); + Con_DPrintf("Loading native: %s\n", name); hVM = Sys_LoadLibrary(name, funcs); if (hVM) { diff --git a/engine/common/sys.h b/engine/common/sys.h index 5b22e710b..ebd2caee7 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -21,23 +21,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // file IO +// for the most part, we use stdio. +// if your system doesn't have stdio then urm... well. // - -// returns the file size -// return -1 if file is not present -// the file should be in BINARY mode for stupid OSs that care -int Sys_FileOpenRead (char *path, int *hndl); - -int Sys_FileOpenWrite (char *path); -void Sys_FileClose (int handle); -void Sys_FileSeek (int handle, int position); -int Sys_FileRead (int handle, void *dest, int count); -int Sys_FileWrite (int handle, void *data, int count); -int Sys_FileTime (char *path); -void Sys_mkdir (char *path); +void Sys_mkdir (char *path); //not all pre-unix systems have directories (including dos 1) qboolean Sys_remove (char *path); - -qboolean Sys_FindGameData(char *gamename, char *basepath, int basepathlen); +qboolean Sys_FindGameData(const char *gamename, char *basepath, int basepathlen); // // memory protection @@ -95,7 +84,7 @@ void Sys_LowFPPrecision (void); void Sys_HighFPPrecision (void); void VARGS Sys_SetFPCW (void); -int Sys_EnumerateFiles (char *gpath, char *match, int (*func)(char *, int, void *), void *parm); +int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm); qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate); diff --git a/engine/common/zone.c b/engine/common/zone.c index f9111b061..782476eb3 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -159,8 +159,8 @@ void *VARGS Z_TagMalloc(int size, int tag) else { zone->pvdn = zone_head; - if (s->next) - s->next->pvdn = zone; + // if (s->next) + // s->next->pvdn = zone; zone_head = zone; } } @@ -2166,6 +2166,9 @@ void Memory_Init (void *buf, int size) void Memory_DeInit(void) { + Hunk_TempFree(); + Cache_Flush(); + #ifdef MULTITHREAD if (zonelock) { diff --git a/engine/d3d/d3d_draw.c b/engine/d3d/d3d_draw.c index bdc78f7f6..51cb13e56 100644 --- a/engine/d3d/d3d_draw.c +++ b/engine/d3d/d3d_draw.c @@ -326,7 +326,7 @@ mpic_t *(D3D7_Draw_SafePicFromWad) (char *name) pic->pic.width = qpic->width; pic->pic.height = qpic->height; - p = (LPDIRECTDRAWSURFACE7*)&pic->pic.data; + p = (LPDIRECTDRAWSURFACE7*)&pic->pic.d.data; if (!strcmp(name, "conchars")) *p = draw_chars_tex; else @@ -367,7 +367,7 @@ mpic_t *(D3D7_Draw_SafeCachePic) (char *path) pic->pic.width = qpic->width; pic->pic.height = qpic->height; - p = (LPDIRECTDRAWSURFACE7*)&pic->pic.data; + p = (LPDIRECTDRAWSURFACE7*)&pic->pic.d.data; *p = (LPDIRECTDRAWSURFACE7)Mod_LoadReplacementTexture(pic->name, "gfx", false, true, true); if (!*p) *p = D3D7_LoadTexture_8_Pal24(path, (unsigned char*)(qpic+1), qpic->width, qpic->height, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 255); @@ -422,7 +422,7 @@ void (D3D7_Draw_ReInit) (void) strcpy(d3dmenu_cachepics[d3dmenu_numcachepics].name, "conchars"); d3dmenu_cachepics[d3dmenu_numcachepics].pic.width = 128; d3dmenu_cachepics[d3dmenu_numcachepics].pic.height = 128; - *(int *)&d3dmenu_cachepics[d3dmenu_numcachepics].pic.data = (int)draw_chars_tex; + *(int *)&d3dmenu_cachepics[d3dmenu_numcachepics].pic.d.data = (int)draw_chars_tex; d3dmenu_numcachepics++; @@ -713,7 +713,7 @@ void (D3D7_Draw_Image) (float x, float y, float w, float h, float s1, float t d3dquadvert[3].s = s1;// - 3.0/pic->width; d3dquadvert[3].t = t2; - p = (LPDIRECTDRAWSURFACE7*)&pic->data; + p = (LPDIRECTDRAWSURFACE7*)&pic->d.data; pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, *p); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); @@ -780,7 +780,7 @@ void (D3D7_Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inhei { mpic_t pic; LPDIRECTDRAWSURFACE7 *p; - p = (LPDIRECTDRAWSURFACE7*)&pic.data; + p = (LPDIRECTDRAWSURFACE7*)&pic.d.data; *p = D3D7_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); D3D7_Set2D (); @@ -799,7 +799,7 @@ void (D3D7_Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight pic.width = inwidth; pic.height = inheight; pic.flags = 0; - p = (LPDIRECTDRAWSURFACE7*)&pic.data; + p = (LPDIRECTDRAWSURFACE7*)&pic.d.data; *p = D3D7_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); D3D7_Set2D (); @@ -814,7 +814,7 @@ void (D3D7_Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, { mpic_t pic; LPDIRECTDRAWSURFACE7 *p; - p = (LPDIRECTDRAWSURFACE7*)&pic.data; + p = (LPDIRECTDRAWSURFACE7*)&pic.d.data; *p = D3D7_LoadTexture_8_Pal24("", (unsigned char*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP, palette, 256); D3D7_Set2D (); diff --git a/engine/d3d/d3d_mesh.c b/engine/d3d/d3d_mesh.c index 340f2a52e..3440c1a03 100644 --- a/engine/d3d/d3d_mesh.c +++ b/engine/d3d/d3d_mesh.c @@ -113,33 +113,6 @@ static galiastexnum_t *D3D7_ChooseSkin(galiasinfo_t *inf, char *modelname, int s Skin_Find(e->scoreboard); tc = e->scoreboard->ttopcolor; bc = e->scoreboard->tbottomcolor; - - //colour forcing - if (cl.splitclients<2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. - { - if (cl.teamplay && cl.spectator) - { - local = Cam_TrackNum(0); - if (local < 0) - local = cl.playernum[0]; - } - else - local = cl.playernum[0]; - if (cl.teamplay && !strcmp(e->scoreboard->team, cl.players[local].team)) - { - if (cl_teamtopcolor>=0) - tc = cl_teamtopcolor; - if (cl_teambottomcolor>=0) - bc = cl_teambottomcolor; - } - else - { - if (cl_enemytopcolor>=0) - tc = cl_enemytopcolor; - if (cl_enemybottomcolor>=0) - bc = cl_enemybottomcolor; - } - } } else { diff --git a/engine/d3d/d3d_rmain.c b/engine/d3d/d3d_rmain.c index 61c7700d8..1237f5075 100644 --- a/engine/d3d/d3d_rmain.c +++ b/engine/d3d/d3d_rmain.c @@ -672,7 +672,7 @@ static void D3D7_DrawSpriteModel (entity_t *e) right[1]*=e->scale; right[2]*=e->scale; - pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)frame->gl_texturenum); + pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, *(LPDIRECTDRAWSURFACE7*)frame->p.d.data); /* { extern int gldepthfunc; diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index a6dce7524..73b8d0b45 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -255,65 +255,16 @@ qboolean D3DAppActivate(BOOL fActive, BOOL minimize) sound_active = true; } + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); + if (fActive) { -/* if (modestate != MS_WINDOWED) - { - IN_ActivateMouse (); - IN_HideMouse (); -// if (vid_canalttab && vid_wassuspended) - { -// vid_wassuspended = false; -// ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); - ShowWindow(mainwindow, SW_SHOWNORMAL); - - // Fix for alt-tab bug in NVidia drivers -// MoveWindow (mainwindow, 0, 0, gdevmode.dmPelsWidth, gdevmode.dmPelsHeight, false); - } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && (key_dest == key_game || key_dest == key_menu)) - { - IN_ActivateMouse (); - IN_HideMouse (); - } -*/ Cvar_ForceCallback(&v_gamma); } if (!fActive) { -/* if (modestate != MS_WINDOWED) - { - IN_DeactivateMouse (); - IN_ShowMouse (); -// if (vid_canalttab) -// { -// ChangeDisplaySettings (NULL, 0); -// vid_wassuspended = true; -// } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } -*/ Cvar_ForceCallback(&v_gamma); //wham bam thanks. -/* - if (qSetDeviceGammaRamp) - { - if (vid_desktopgamma.value) - { - HDC hDC = GetDC(GetDesktopWindow()); - qSetDeviceGammaRamp (hDC, originalgammaramps); - ReleaseDC(GetDesktopWindow(), hDC); - } - else - { - qSetDeviceGammaRamp(maindc, originalgammaramps); - } - } - */ } return true; @@ -950,6 +901,14 @@ void (D3D7_SCR_UpdateScreen) (void) extern cvar_t vid_conwidth, vid_conheight; vid.conwidth = vid_conwidth.value; vid.conheight = vid_conheight.value; + { + DWORD w, h; + pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &w, &h); + if (vid.conwidth <= 0) + vid.conwidth = w; + if (vid.conheight <= 0) + vid.conheight = h; + } if (vid.width != vid.conwidth || vid.height != vid.conheight) vid.recalc_refdef = true; vid.width = vid.conwidth; @@ -1067,32 +1026,7 @@ void (D3D7_SCR_UpdateScreen) (void) - if (modestate == MS_WINDOWED) - { - extern int mouseusedforgui; - extern qboolean mouseactive; - if (!_windowed_mouse.value) - { - if (mouseactive) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - else - { - if ((key_dest == key_game||mouseusedforgui) && !mouseactive && ActiveApp) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - else if (mouseactive && key_dest == key_console) - {//!(key_dest == key_game || mouseusedforgui)) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); } diff --git a/engine/d3d9/d3d9_draw.c b/engine/d3d9/d3d9_draw.c index a69d9b426..236bf5f79 100644 --- a/engine/d3d9/d3d9_draw.c +++ b/engine/d3d9/d3d9_draw.c @@ -343,7 +343,7 @@ mpic_t *D3D9_Draw_SafePicFromWad (char *name) Q_strncpyz (pic->name, name, sizeof(pic->name)); - p = (LPDIRECT3DBASETEXTURE9*)&pic->pic.data; + p = (LPDIRECT3DBASETEXTURE9*)&pic->pic.d.data; if (!strcmp(name, "conchars")) { pic->pic.width = 256; @@ -396,7 +396,7 @@ mpic_t *D3D9_Draw_SafeCachePic (char *path) Q_strncpyz (pic->name, path, sizeof(pic->name)); - p = (LPDIRECT3DBASETEXTURE9*)&pic->pic.data; + p = (LPDIRECT3DBASETEXTURE9*)&pic->pic.d.data; if (qpic) { @@ -453,7 +453,7 @@ void D3D9_Draw_ReInit (void) strcpy(d3dmenu_cachepics[d3dmenu_numcachepics].name, "conchars"); d3dmenu_cachepics[d3dmenu_numcachepics].pic.width = 128; d3dmenu_cachepics[d3dmenu_numcachepics].pic.height = 128; - *(int *)&d3dmenu_cachepics[d3dmenu_numcachepics].pic.data = (int)d3d9chars_tex; + *(int *)&d3dmenu_cachepics[d3dmenu_numcachepics].pic.d.data = (int)d3d9chars_tex; d3dmenu_numcachepics++; @@ -751,7 +751,7 @@ void D3D9_Draw_Image (float x, float y, float w, float h, float s1, float t1 d3d9quadvert[3].s = s1;// - 3.0/pic->width; d3d9quadvert[3].t = t2; - p = (LPDIRECT3DBASETEXTURE9*)&pic->data; + p = (LPDIRECT3DBASETEXTURE9*)&pic->d.data; IDirect3DDevice9_SetTexture(pD3DDev9, 0, *p); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); @@ -820,7 +820,7 @@ void D3D9_Media_ShowFrameBGR_24_Flip (qbyte *framedata, int inwidth, int inheigh { mpic_t pic; LPDIRECT3DBASETEXTURE9 *p; - p = (LPDIRECT3DBASETEXTURE9*)&pic.data; + p = (LPDIRECT3DBASETEXTURE9*)&pic.d.data; *p = D3D9_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); D3D9_Set2D (); @@ -839,7 +839,7 @@ void D3D9_Media_ShowFrameRGBA_32 (qbyte *framedata, int inwidth, int inheight) pic.width = inwidth; pic.height = inheight; pic.flags = 0; - p = (LPDIRECT3DBASETEXTURE9*)&pic.data; + p = (LPDIRECT3DBASETEXTURE9*)&pic.d; *p = D3D9_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); D3D9_Set2D (); @@ -854,7 +854,7 @@ void (D3D9_Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, { mpic_t pic; LPDIRECT3DBASETEXTURE9 *p; - p = (LPDIRECT3DBASETEXTURE9*)&pic.data; + p = (LPDIRECT3DBASETEXTURE9*)&pic.d; *p = D3D9_LoadTexture_8_Pal24("", (unsigned char*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP, palette, 256); D3D9_Set2D (); diff --git a/engine/d3d9/d3d9_rmain.c b/engine/d3d9/d3d9_rmain.c index 0c470e0ca..04c5cbfd0 100644 --- a/engine/d3d9/d3d9_rmain.c +++ b/engine/d3d9/d3d9_rmain.c @@ -997,7 +997,7 @@ static void D3D9_DrawSpriteModel (entity_t *e) IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHABLENDENABLE, TRUE); if (pic) - IDirect3DDevice9_SetTexture(pD3DDev9, 0, *(LPDIRECT3DBASETEXTURE9*)&pic->data); + IDirect3DDevice9_SetTexture(pD3DDev9, 0, *(LPDIRECT3DBASETEXTURE9*)&pic->d); else IDirect3DDevice9_SetTexture(pD3DDev9, 0, NULL); @@ -1085,7 +1085,7 @@ static void D3D9_DrawSpriteModel (entity_t *e) right[1]*=e->scale; right[2]*=e->scale; - IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)frame->gl_texturenum); + IDirect3DDevice9_SetTexture(pD3DDev9, 0, *(void**)&frame->p.d); /* { extern int gldepthfunc; diff --git a/engine/d3d9/vid_d3d9.c b/engine/d3d9/vid_d3d9.c index 9d975abb6..791f14fd9 100644 --- a/engine/d3d9/vid_d3d9.c +++ b/engine/d3d9/vid_d3d9.c @@ -263,65 +263,15 @@ qboolean D3D9AppActivate(BOOL fActive, BOOL minimize) sound_active = true; } + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); + if (fActive) { -/* if (modestate != MS_WINDOWED) - { - IN_ActivateMouse (); - IN_HideMouse (); -// if (vid_canalttab && vid_wassuspended) - { -// vid_wassuspended = false; -// ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); - ShowWindow(mainwindow, SW_SHOWNORMAL); - - // Fix for alt-tab bug in NVidia drivers -// MoveWindow (mainwindow, 0, 0, gdevmode.dmPelsWidth, gdevmode.dmPelsHeight, false); - } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && (key_dest == key_game || key_dest == key_menu)) - { - IN_ActivateMouse (); - IN_HideMouse (); - } -*/ Cvar_ForceCallback(&v_gamma); } - if (!fActive) { -/* if (modestate != MS_WINDOWED) - { - IN_DeactivateMouse (); - IN_ShowMouse (); -// if (vid_canalttab) -// { -// ChangeDisplaySettings (NULL, 0); -// vid_wassuspended = true; -// } - } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } -*/ Cvar_ForceCallback(&v_gamma); //wham bam thanks. -/* - if (qSetDeviceGammaRamp) - { - if (vid_desktopgamma.value) - { - HDC hDC = GetDC(GetDesktopWindow()); - qSetDeviceGammaRamp (hDC, originalgammaramps); - ReleaseDC(GetDesktopWindow(), hDC); - } - else - { - qSetDeviceGammaRamp(maindc, originalgammaramps); - } - } - */ } return true; @@ -1335,28 +1285,7 @@ void (D3D9_SCR_UpdateScreen) (void) window_center_y = (window_rect.top + window_rect.bottom)/2; - - if (modestate == MS_WINDOWED) - { - extern int mouseusedforgui; - extern qboolean mouseactive; - qboolean wantactive; - - wantactive = _windowed_mouse.value && (key_dest == key_game||mouseusedforgui) && ActiveApp; - if (wantactive != mouseactive) - { - if (!mouseactive) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - else - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); VID_ShiftPalette (NULL); } diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 43f131018..ae6098792 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -260,7 +260,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /machine:I386 /out:"../../../fteglqw.exe" -# ADD LINK32 wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /pdb:none /map /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../fteminglqw.exe" /libpath:"../libs/dxsdk7/lib" +# ADD LINK32 wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /pdb:none /map /machine:I386 /out:"../../fteminglqw.exe" /libpath:"../libs/dxsdk7/lib" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" @@ -363,7 +363,7 @@ LINK32=link.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /D "AVAIL_OGGVORBIS" /D "Q3CLIENT" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /YX /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c # SUBTRACT BASE CPP /X -# ADD CPP /nologo /G5 /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /D "Q3CLIENT" /D "Q3SERVER" /FR /Fp".\GLDebugQ3/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebugQ3/" /Fd".\GLDebugQ3/" /FD /c +# ADD CPP /nologo /G5 /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR /Fp".\GLDebugQ3/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebugQ3/" /Fd".\GLDebugQ3/" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" @@ -550,6 +550,195 @@ SOURCE=..\server\sv_user.c # End Source File # Begin Source File +SOURCE=..\server\svhl_game.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svhl_phys.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svhl_world.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# ADD CPP /Yu"qwsvdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\server\svq2_ents.c # ADD CPP /Yu"qwsvdef.h" # End Source File @@ -565,45 +754,65 @@ SOURCE=..\server\svq3_game.c !IF "$(CFG)" == "ftequake - Win32 Release" # PROP Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug" # PROP Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" +# ADD CPP /Yu"qwsvdef.h" + !ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" +# ADD CPP /Yu"qwsvdef.h" + !ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" +# ADD CPP /Yu"qwsvdef.h" + !ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" +# ADD CPP /Yu"qwsvdef.h" + !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # PROP Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" # PROP Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" +# ADD CPP /Yu"qwsvdef.h" + !ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" -# PROP Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" # PROP Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" +# ADD CPP /Yu"qwsvdef.h" + !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" # PROP BASE Exclude_From_Build 1 +# ADD CPP /Yu"qwsvdef.h" !ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" +# ADD CPP /Yu"qwsvdef.h" + !ENDIF # End Source File @@ -1183,6 +1392,45 @@ SOURCE=..\client\cl_ui.c # End Source File # Begin Source File +SOURCE=..\client\clhl_game.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\client\clq2_cin.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -6165,6 +6413,18 @@ SOURCE=..\common\fs.c # End Source File # Begin Source File +SOURCE=..\common\fs_pak.c +# End Source File +# Begin Source File + +SOURCE=..\common\fs_stdio.c +# End Source File +# Begin Source File + +SOURCE=..\common\fs_zip.c +# End Source File +# Begin Source File + SOURCE=..\common\huff.c # End Source File # Begin Source File @@ -10457,9 +10717,6 @@ SOURCE=..\client\winquake.rc !IF "$(CFG)" == "ftequake - Win32 Release" -# ADD BASE RSC /l 0x809 /i "\engine\client" /i "\ftetgcvs\svn\engine\client" /i "\ftesvn - Copy\engine\client" /i "\ftesvn\engine\client" /i "\ftetgcvs\svnd3d\engine\client" /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" -# ADD RSC /l 0x809 /i "\engine\client" /i "\ftetgcvs\svn\engine\client" /i "\ftesvn - Copy\engine\client" /i "\ftesvn\engine\client" /i "\ftetgcvs\svnd3d\engine\client" /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" /d "MINIMAL" - !ELSEIF "$(CFG)" == "ftequake - Win32 Debug" !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" @@ -10537,6 +10794,10 @@ SOURCE=..\client\quakedef.h SOURCE=..\client\render.h # End Source File +# Begin Source File + +SOURCE=..\server\svhl_gcapi.h +# End Source File # End Group # Begin Group "Resource Files" diff --git a/engine/ftequake/ftequake.dsw b/engine/ftequake/ftequake.dsw index 82c7c4d17..c47d7b0f4 100644 --- a/engine/ftequake/ftequake.dsw +++ b/engine/ftequake/ftequake.dsw @@ -45,6 +45,21 @@ Package=<4> ############################################################################### +Project: "npqtv"=.\npqtv.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name qcvm + End Project Dependency +}}} + +############################################################################### + Project: "q3asm2"=..\..\Q3ASM2\q3asm2.dsp - Package Owner=<4> Package=<5> @@ -69,6 +84,18 @@ Package=<4> ############################################################################### +Project: "qcvm"=..\QCLIB\qcvm\qcvm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Global: Package=<5> diff --git a/engine/ftequake/npapi.def b/engine/ftequake/npapi.def new file mode 100644 index 000000000..c0d4c0856 --- /dev/null +++ b/engine/ftequake/npapi.def @@ -0,0 +1,5 @@ +EXPORTS + NP_GetEntryPoints + NP_GetMIMEDescription + NP_Initialize + NP_Shutdown \ No newline at end of file diff --git a/engine/ftequake/npplug.rc b/engine/ftequake/npplug.rc new file mode 100644 index 000000000..cc98f1968 --- /dev/null +++ b/engine/ftequake/npplug.rc @@ -0,0 +1,111 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Forethought Entertainment\0" + VALUE "FileDescription", "Quake in a browser\0" + VALUE "FileExtents", "qtv|mvd\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "npqtv\0" + VALUE "LegalCopyright", "Copyright © 2009\0" + VALUE "LegalTrademarks", "\0" + VALUE "MIMEType", "text/x-quaketvident|application/x-multiviewdemo\0" + VALUE "OriginalFilename", "npqtv.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "QTV Viewer\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/engine/ftequake/npqtv.dsp b/engine/ftequake/npqtv.dsp new file mode 100644 index 000000000..1927b856e --- /dev/null +++ b/engine/ftequake/npqtv.dsp @@ -0,0 +1,1044 @@ +# Microsoft Developer Studio Project File - Name="npqtv" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=npqtv - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "npqtv.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "npqtv.mak" CFG="npqtv - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "npqtv - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "npqtv - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "npqtv - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NPQTV_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NPQTV" /D "GLQUAKE" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib winmm.lib wsock32.lib /nologo /dll /machine:I386 /nodefaultlib:"libc" /out:"../../npqtv.dll" /libpath:"../libs/dxsdk7/lib" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "npqtv___Win32_Debug" +# PROP BASE Intermediate_Dir "npqtv___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "npqtv___Win32_Debug" +# PROP Intermediate_Dir "npqtv___Win32_Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NPQTV_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NPQTV" /D "GLQUAKE" /FR /Yu"quakedef.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib wsock32.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libc" /nodefaultlib:"libcd" /out:"../../npqtv.dll" /pdbtype:sept /libpath:"../libs/dxsdk7/lib" + +!ENDIF + +# Begin Target + +# Name "npqtv - Win32 Release" +# Name "npqtv - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\common\cmd.c +# End Source File +# Begin Source File + +SOURCE=..\common\com_mesh.c +# End Source File +# Begin Source File + +SOURCE=..\common\common.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yc"quakedef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\common\crc.c +# End Source File +# Begin Source File + +SOURCE=..\common\cvar.c +# End Source File +# Begin Source File + +SOURCE=..\common\fs.c +# End Source File +# Begin Source File + +SOURCE=..\common\fs_pak.c +# End Source File +# Begin Source File + +SOURCE=..\common\fs_stdio.c +# End Source File +# Begin Source File + +SOURCE=..\common\fs_zip.c +# End Source File +# Begin Source File + +SOURCE=..\common\gl_q2bsp.c +# End Source File +# Begin Source File + +SOURCE=..\common\huff.c +# End Source File +# Begin Source File + +SOURCE=..\common\log.c +# End Source File +# Begin Source File + +SOURCE=..\common\mathlib.c +# End Source File +# Begin Source File + +SOURCE=..\common\md4.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\common\net_chan.c +# End Source File +# Begin Source File + +SOURCE=..\common\net_wins.c +# End Source File +# Begin Source File + +SOURCE=..\common\plugin.c +# End Source File +# Begin Source File + +SOURCE=..\common\pmove.c +# End Source File +# Begin Source File + +SOURCE=..\common\pmovetst.c +# End Source File +# Begin Source File + +SOURCE=..\common\pr_bgcmd.c +# End Source File +# Begin Source File + +SOURCE=..\common\q1bsp.c +# End Source File +# Begin Source File + +SOURCE=..\common\q2pmove.c +# End Source File +# Begin Source File + +SOURCE=..\common\q3common.c +# End Source File +# Begin Source File + +SOURCE=..\common\qvm.c +# End Source File +# Begin Source File + +SOURCE=..\common\translate.c +# End Source File +# Begin Source File + +SOURCE=..\common\zone.c +# End Source File +# End Group +# Begin Group "client" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\client\cd_null.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_cam.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_cg.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_demo.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_ents.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_ignore.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_input.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_main.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_parse.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_pred.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_screen.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_tent.c +# End Source File +# Begin Source File + +SOURCE=..\client\cl_ui.c +# End Source File +# Begin Source File + +SOURCE=..\client\clhl_game.c +# End Source File +# Begin Source File + +SOURCE=..\client\clq2_cin.c +# End Source File +# Begin Source File + +SOURCE=..\client\clq2_ents.c +# End Source File +# Begin Source File + +SOURCE=..\client\clq3_parse.c +# End Source File +# Begin Source File + +SOURCE=..\client\console.c +# End Source File +# Begin Source File + +SOURCE=..\client\fragstats.c +# End Source File +# Begin Source File + +SOURCE=..\client\image.c +# End Source File +# Begin Source File + +SOURCE=..\client\in_win.c +# End Source File +# Begin Source File + +SOURCE=..\client\keys.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_download.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_items.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_master.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_mp3.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_multi.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_options.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_script.c +# End Source File +# Begin Source File + +SOURCE=..\client\m_single.c +# End Source File +# Begin Source File + +SOURCE=..\client\menu.c +# End Source File +# Begin Source File + +SOURCE=..\client\net_master.c +# End Source File +# Begin Source File + +SOURCE=..\client\p_classic.c +# End Source File +# Begin Source File + +SOURCE=..\client\p_null.c +# End Source File +# Begin Source File + +SOURCE=..\client\p_script.c +# End Source File +# Begin Source File + +SOURCE=..\client\pr_csqc.c +# End Source File +# Begin Source File + +SOURCE=..\client\pr_menu.c +# End Source File +# Begin Source File + +SOURCE=..\client\r_bulleten.c +# End Source File +# Begin Source File + +SOURCE=..\client\r_efrag.c +# End Source File +# Begin Source File + +SOURCE=..\client\r_part.c +# End Source File +# Begin Source File + +SOURCE=..\client\r_partset.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\client\renderer.c +# End Source File +# Begin Source File + +SOURCE=..\client\renderque.c +# End Source File +# Begin Source File + +SOURCE=..\client\roq_read.c +# End Source File +# Begin Source File + +SOURCE=..\client\sbar.c +# End Source File +# Begin Source File + +SOURCE=..\client\skin.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_directx.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_dma.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_mem.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_mix.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_mp3.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_ov.c +# End Source File +# Begin Source File + +SOURCE=..\client\snd_win.c +# End Source File +# Begin Source File + +SOURCE=..\client\sys_win.c +# End Source File +# Begin Source File + +SOURCE=..\client\teamplay.c +# End Source File +# Begin Source File + +SOURCE=..\client\textedit.c +# End Source File +# Begin Source File + +SOURCE=..\client\valid.c +# End Source File +# Begin Source File + +SOURCE=..\client\view.c +# End Source File +# Begin Source File + +SOURCE=..\client\wad.c +# End Source File +# Begin Source File + +SOURCE=..\client\zqtp.c +# End Source File +# End Group +# Begin Group "gl" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\gl\gl_alias.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_backend.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_bloom.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_draw.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_heightmap.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_hlmdl.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_model.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_ngraph.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_ppl.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_rlight.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_rmain.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_rmisc.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_rsurf.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_screen.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_shader.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_vidcommon.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_vidnt.c +# End Source File +# Begin Source File + +SOURCE=..\gl\gl_warp.c +# End Source File +# Begin Source File + +SOURCE=..\gl\glmod_doom.c +# End Source File +# Begin Source File + +SOURCE=..\gl\ltface.c +# End Source File +# End Group +# Begin Group "asm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\common\math.s + +!IF "$(CFG)" == "npqtv - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\common\math.s +InputName=math + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /I ..\common $(InputPath) > $(OUTDIR)\$(InputName).spp + ..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# Begin Custom Build +OutDir=.\npqtv___Win32_Debug +InputPath=..\common\math.s +InputName=math + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /I ..\common $(InputPath) > $(OUTDIR)\$(InputName).spp + ..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\client\sys_wina.s + +!IF "$(CFG)" == "npqtv - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\client\sys_wina.s +InputName=sys_wina + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /I ..\common $(InputPath) > $(OUTDIR)\$(InputName).spp + ..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# Begin Custom Build +OutDir=.\npqtv___Win32_Debug +InputPath=..\client\sys_wina.s +InputName=sys_wina + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /I ..\common $(InputPath) > $(OUTDIR)\$(InputName).spp + ..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\worlda.s + +!IF "$(CFG)" == "npqtv - Win32 Release" + +# Begin Custom Build +OutDir=.\Release +InputPath=..\server\worlda.s +InputName=worlda + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /I ..\common $(InputPath) > $(OUTDIR)\$(InputName).spp + ..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# Begin Custom Build +OutDir=.\npqtv___Win32_Debug +InputPath=..\server\worlda.s +InputName=worlda + +"$(OUTDIR)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + cl /EP /I ..\common $(InputPath) > $(OUTDIR)\$(InputName).spp + ..\gas2masm\debug\gas2masm < $(OUTDIR)\$(InputName).spp > $(OUTDIR)\$(InputName).asm + ml /c /Cp /coff /Fo$(OUTDIR)\$(InputName).obj /Zm /Zi $(OUTDIR)\$(InputName).asm + del $(OUTDIR)\$(InputName).spp + +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# Begin Group "server" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\server\net_preparse.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\pr_cmds.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\pr_q1qvm.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\savegame.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_ccmds.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_chat.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_demo.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_ents.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_init.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_main.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_master.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_move.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_mvd.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_nchan.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_phys.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_rankin.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_send.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\sv_user.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svhl_game.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svhl_phys.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svhl_world.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svmodel.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svq2_ents.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svq2_game.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\svq3_game.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\server\world.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu"qwsvdef.h" + +!ENDIF + +# End Source File +# End Group +# Begin Source File + +SOURCE=.\npapi.def +# End Source File +# Begin Source File + +SOURCE=..\client\sys_npqtv.c + +!IF "$(CFG)" == "npqtv - Win32 Release" + +!ELSEIF "$(CFG)" == "npqtv - Win32 Debug" + +# ADD CPP /Yu + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\npplug.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 69cd88fcc..6f1b65855 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -92,14 +92,8 @@ static unsigned cs_data[16*16]; static int externalhair; int gl_anisotropy_factor; -typedef struct -{ - int texnum; - float sl, tl, sh, th; -} glpic_t; - -qbyte conback_buffer[sizeof(mpic_t) + sizeof(glpic_t)]; -qbyte custconback_buffer[sizeof(mpic_t) + sizeof(glpic_t)]; +qbyte conback_buffer[sizeof(mpic_t)]; +qbyte custconback_buffer[sizeof(mpic_t)]; mpic_t *default_conback = (mpic_t *)&conback_buffer, *conback, *custom_conback = (mpic_t *)&custconback_buffer; #include "hash.h" @@ -245,7 +239,7 @@ qboolean Draw_RealPicFromWad (mpic_t *out, char *name) in = W_SafeGetLumpName (name+4); else in = W_SafeGetLumpName (name); - gl = (glpic_t *)out->data; + gl = &out->d.gl; if (in) { @@ -393,7 +387,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) if ((mem = ReadPCXFile(data, com_filesize, &pic->pic.width, &height))) { pic->pic.height = height; - gl = (glpic_t *)pic->pic.data; + gl = &pic->pic.d.gl; if (!(gl->texnum = Mod_LoadReplacementTexture(alternatename, "pics", false, true, false))) gl->texnum = GL_LoadTexture32(path, pic->pic.width, pic->pic.height, (unsigned *)mem, false, false); gl->sl = 0; @@ -434,7 +428,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) pic->pic.height = height; if (mem) { - gl = (glpic_t *)pic->pic.data; + gl = &pic->pic.d.gl; if (!(gl->texnum = Mod_LoadReplacementTexture(alternatename, NULL, false, true, false))) gl->texnum = GL_LoadTexture32(path, pic->pic.width, pic->pic.height, (unsigned *)mem, false, true); gl->sl = 0; @@ -463,7 +457,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) if ((mem = ReadJPEGFile(data, com_filesize, &pic->pic.width, &height))) { pic->pic.height = height; - gl = (glpic_t *)pic->pic.data; + gl = &pic->pic.d.gl; if (!(gl->texnum = Mod_LoadReplacementTexture(alternatename, NULL, false, true, false))) gl->texnum = GL_LoadTexture32(path, pic->pic.width, pic->pic.height, (unsigned *)mem, false, false); gl->sl = 0; @@ -491,7 +485,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) strcpy(pic->name, path); if (mem = ReadTargaFile ((qbyte *)dat, com_filesize, &pic->pic.width, &pic->pic.height, false)) { - gl = (glpic_t *)pic->pic.data; + gl = &pic->pic.d.gl; if (!(gl->texnum = Mod_LoadReplacementTexture(alternatename, false, true))) gl->texnum = GL_LoadTexture32(path, pic->pic.width, pic->pic.height, (unsigned *)dat, false, true); gl->sl = 0; @@ -542,7 +536,7 @@ mpic_t *GLDraw_SafeCachePic (char *path) pic->pic.width = qpic->width; pic->pic.height = qpic->height; - gl = (glpic_t *)pic->pic.data; + gl = &pic->pic.d.gl; if (!(gl->texnum = Mod_LoadReplacementTexture(path, NULL, false, true, false))) gl->texnum = GL_LoadPicTexture (qpic); gl->sl = 0; @@ -969,7 +963,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); strcpy(glmenu_cachepics[glmenu_numcachepics].name, "conchars"); glmenu_cachepics[glmenu_numcachepics].pic.width = 128; glmenu_cachepics[glmenu_numcachepics].pic.height = 128; - gl = (glpic_t *)&glmenu_cachepics[glmenu_numcachepics].pic.data; + gl = &glmenu_cachepics[glmenu_numcachepics].pic.d.gl; gl->texnum = char_texture; gl->sl = 0; gl->tl = 0; @@ -988,7 +982,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); strcpy(glmenu_cachepics[glmenu_numcachepics].name, "tinyfont"); glmenu_cachepics[glmenu_numcachepics].pic.width = 128; glmenu_cachepics[glmenu_numcachepics].pic.height = 32; - gl = (glpic_t *)&glmenu_cachepics[glmenu_numcachepics].pic.data; + gl = &glmenu_cachepics[glmenu_numcachepics].pic.d.gl; char_texturetiny = gl->texnum = GL_LoadTexture ("tinyfont", 128, 32, tinyfont, false, true); gl->sl = 0; gl->tl = 0; @@ -1008,7 +1002,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); strcpy(glmenu_cachepics[glmenu_numcachepics].name, "gfx/menu/bigfont.lmp"); glmenu_cachepics[glmenu_numcachepics].pic.width = bigfont->width; glmenu_cachepics[glmenu_numcachepics].pic.height = bigfont->height; - gl = (glpic_t *)&glmenu_cachepics[glmenu_numcachepics].pic.data; + gl = &glmenu_cachepics[glmenu_numcachepics].pic.d.gl; gl->texnum = GL_LoadTexture ("gfx/menu/bigfont.lmp", bigfont->width, bigfont->height, data, false, true); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1110,7 +1104,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl = (glpic_t *)conback->data; + gl = &conback->d.gl; if (!(gl->texnum=Mod_LoadReplacementTexture("gfx/conback.lmp", NULL, false, true, false))) { if (!ncdata) //no fallback @@ -1142,7 +1136,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); custom_conback->width = vid.conwidth; custom_conback->height = vid.conheight; - gl = (glpic_t *)custom_conback->data; + gl = &custom_conback->d.gl; gl->texnum = 0; gl->sl = 0; gl->sh = 1; @@ -1586,7 +1580,7 @@ void GLDraw_Pic (int x, int y, mpic_t *pic) if (scrap_dirty) Scrap_Upload (); - gl = (glpic_t *)pic->data; + gl = &pic->d.gl; draw_mesh_xyz[0][0] = x; draw_mesh_xyz[0][1] = y; @@ -1749,7 +1743,7 @@ void GLDraw_ScalePic (int x, int y, int width, int height, mpic_t *pic) if (scrap_dirty) Scrap_Upload (); - gl = (glpic_t *)pic->data; + gl = &pic->d.gl; // qglColor4f (1,1,1,1); GL_Bind (gl->texnum); qglBegin (GL_QUADS); @@ -1775,7 +1769,7 @@ void GLDraw_AlphaPic (int x, int y, mpic_t *pic, float alpha) if (scrap_dirty) Scrap_Upload (); - gl = (glpic_t *)pic->data; + gl = &pic->d.gl; qglDisable(GL_ALPHA_TEST); qglEnable (GL_BLEND); // qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1805,7 +1799,7 @@ void GLDraw_SubPic(int x, int y, mpic_t *pic, int srcx, int srcy, int width, int if (scrap_dirty) Scrap_Upload (); - gl = (glpic_t *)pic->data; + gl = &pic->d.gl; oldglwidth = gl->sh - gl->sl; oldglheight = gl->th - gl->tl; @@ -2005,7 +1999,7 @@ void GLDraw_TileClear (int x, int y, int w, int h) } else { - GL_Bind (*(int *)draw_backtile->data); + GL_Bind (draw_backtile->d.gl.texnum); qglBegin (GL_QUADS); qglTexCoord2f (x/64.0, y/64.0); qglVertex2f (x, y); @@ -2243,7 +2237,7 @@ void GLDraw_Image(float x, float y, float w, float h, float s1, float t1, float if (scrap_dirty) Scrap_Upload (); - gl = (glpic_t *)pic->data; + gl = &pic->d.gl; /* s2 = s2 @@ -2370,7 +2364,7 @@ void GL_Font_Callback(struct cvar_s *var, char *oldvalue) pic = GLDraw_IsCached("conchars"); if (pic) { - glpic_t *gl = (glpic_t *)pic->data; + glpic_t *gl = &pic->d.gl; gl->texnum = char_texture; } else @@ -2398,7 +2392,7 @@ void GL_Conback_Callback(struct cvar_s *var, char *oldvalue) else { conback = custom_conback; - ((glpic_t *)conback->data)->texnum = newtex; + conback->d.gl.texnum = newtex; } } diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 5d610edd0..f21081f11 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -234,6 +234,50 @@ void *Mod_GetHalfLifeModelData(model_t *mod) } #endif +int HLMod_FrameForName(model_t *mod, char *name) +{ + int i; + hlmdl_header_t *h; + hlmdl_sequencelist_t *seqs; + hlmodelcache_t *mc; + if (!mod || mod->type != mod_halflife) + return -1; //halflife models only, please + + mc = Mod_Extradata(mod); + + h = (hlmdl_header_t *)((char *)mc + mc->header); + seqs = (hlmdl_sequencelist_t*)((char*)h+h->seqindex); + + for (i = 0; i < h->numseq; i++) + { + if (!strcmp(seqs[i].name, name)) + return i; + } + return -1; +} + +int HLMod_BoneForName(model_t *mod, char *name) +{ + int i; + hlmdl_header_t *h; + hlmdl_bone_t *bones; + hlmodelcache_t *mc; + if (!mod || mod->type != mod_halflife) + return -1; //halflife models only, please + + mc = Mod_Extradata(mod); + + h = (hlmdl_header_t *)((char *)mc + mc->header); + bones = (hlmdl_bone_t*)((char*)h+h->boneindex); + + for (i = 0; i < h->numbones; i++) + { + if (!strcmp(bones[i].name, name)) + return i+1; + } + return 0; +} + /* ======================================================================================================================= HL_CalculateBones - calculate bone positions - quaternion+vector in one function @@ -403,10 +447,10 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl return; if(frame >= sequence->numframes) { - if (sequence->motiontype&1) - frame = sequence->numframes-1; - else + if (sequence->loop) frame %= sequence->numframes; + else + frame = sequence->numframes-1; } if (lastbone > model->header->numbones) @@ -576,6 +620,7 @@ void R_DrawHLModel(entity_t *curent) if (cbone >= lastbone) continue; HL_SetupBones(&model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, (curent->framestate.g[bgroup].subblendfrac+1)*0.5, curent->framestate.g[bgroup].frametime[0]); /* Setup the bones */ + cbone = lastbone; } /* Manipulate each mesh directly */ diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 4c6bc99d1..caf0eacfc 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -404,7 +404,6 @@ Mod_LoadModel Loads a model into the cache ================== */ -char *COM_FileExtension (char *in); model_t *GLMod_LoadModel (model_t *mod, qboolean crash) { void *d; @@ -2064,7 +2063,6 @@ void *suplementryclipnodes; void *suplementryplanes; void *crouchhullfile; -qbyte *COM_LoadMallocFile (char *path); void GLMod_LoadCrouchHull(void) { int i, h; @@ -2235,7 +2233,7 @@ qboolean GLMod_LoadClipnodes (lump_t *l) hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; - hull->clip_mins[2] = -32;//-36 is correct here, but we'll just copy mvdsv instead. + hull->clip_mins[2] = -36;//-36 is correct here, but mvdsv uses -32 instead. This breaks prediction between the two hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; hull->clip_maxs[2] = hull->clip_mins[2]+72; @@ -3028,8 +3026,8 @@ void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum *ppframe = pspriteframe; - pspriteframe->width = width; - pspriteframe->height = height; + pspriteframe->p.width = width; + pspriteframe->p.height = height; origin[0] = LittleLong (pinframe->origin[0]); origin[1] = LittleLong (pinframe->origin[1]); @@ -3038,42 +3036,46 @@ void * GLMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum pspriteframe->left = origin[0]; pspriteframe->right = width + origin[0]; - pspriteframe->gl_texturenum = 0; + pspriteframe->p.d.gl.texnum = 0; + pspriteframe->p.d.gl.sl = 0; + pspriteframe->p.d.gl.sh = 1; + pspriteframe->p.d.gl.tl = 0; + pspriteframe->p.d.gl.th = 1; - if (!pspriteframe->gl_texturenum) + if (!pspriteframe->p.d.gl.texnum) { //the dp way COM_StripExtension(loadmodel->name, name, sizeof(name)); Q_strncatz(name, va("_%i", framenum), sizeof(name)); - pspriteframe->gl_texturenum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); + pspriteframe->p.d.gl.texnum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); } - if (!pspriteframe->gl_texturenum) + if (!pspriteframe->p.d.gl.texnum) { //the older fte way. COM_StripExtension(loadmodel->name, name, sizeof(name)); Q_strncatz(name, va("_%i", framenum), sizeof(name)); - pspriteframe->gl_texturenum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); + pspriteframe->p.d.gl.texnum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); } - if (!pspriteframe->gl_texturenum) + if (!pspriteframe->p.d.gl.texnum) { //the fuhquake way COM_StripExtension(COM_SkipPath(loadmodel->name), name, sizeof(name)); Q_strncatz(name, va("_%i", framenum), sizeof(name)); - pspriteframe->gl_texturenum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); + pspriteframe->p.d.gl.texnum = Mod_LoadReplacementTexture(name, "sprites", true, true, true); } if (version == SPRITE32_VERSION) { size *= 4; - if (!pspriteframe->gl_texturenum) - pspriteframe->gl_texturenum = R_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), true, true); + if (!pspriteframe->p.d.gl.texnum) + pspriteframe->p.d.gl.texnum = R_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), true, true); } else if (version == SPRITEHL_VERSION) { - if (!pspriteframe->gl_texturenum) - pspriteframe->gl_texturenum = R_LoadTexture8Pal32 (name, width, height, (qbyte *)(pinframe + 1), (qbyte*)palette, true, true); + if (!pspriteframe->p.d.gl.texnum) + pspriteframe->p.d.gl.texnum = R_LoadTexture8Pal32 (name, width, height, (qbyte *)(pinframe + 1), (qbyte*)palette, true, true); } else { - if (!pspriteframe->gl_texturenum) - pspriteframe->gl_texturenum = R_LoadTexture8 (name, width, height, (qbyte *)(pinframe + 1), true, true); + if (!pspriteframe->p.d.gl.texnum) + pspriteframe->p.d.gl.texnum = R_LoadTexture8 (name, width, height, (qbyte *)(pinframe + 1), true, true); } return (void *)((qbyte *)(pinframe+1) + size); @@ -3330,17 +3332,17 @@ qboolean GLMod_LoadSprite2Model (model_t *mod, void *buffer) frame = psprite->frames[i].frameptr = Hunk_AllocName(sizeof(mspriteframe_t), loadname); - frame->gl_texturenum = Mod_LoadHiResTexture(pframetype->name, NULL, true, true, true); + frame->p.d.gl.texnum = Mod_LoadHiResTexture(pframetype->name, NULL, true, true, true); - frame->width = LittleLong(pframetype->width); - frame->height = LittleLong(pframetype->height); + frame->p.width = LittleLong(pframetype->width); + frame->p.height = LittleLong(pframetype->height); origin[0] = LittleLong (pframetype->origin_x); origin[1] = LittleLong (pframetype->origin_y); frame->up = -origin[1]; - frame->down = frame->height - origin[1]; + frame->down = frame->p.height - origin[1]; frame->left = -origin[0]; - frame->right = frame->width - origin[0]; + frame->right = frame->p.width - origin[0]; pframetype++; } diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 9c59cfd52..e28f143b0 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -416,13 +416,16 @@ SPRITE MODELS // FIXME: shorten these? typedef struct mspriteframe_s { + float up, down, left, right; +/* int width; int height; - float up, down, left, right; int gl_texturenum; #ifdef SWQUAKE qbyte pixels[4]; #endif + */ + mpic_t p; } mspriteframe_t; mspriteframe_t *R_GetSpriteFrame (entity_t *currententity); diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index 7868cb966..911bb9371 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -142,4 +142,64 @@ void GLR_NetGraph (void) qglEnd (); } +void GLR_FrameTimeGraph (int frametime) +{ + int a, x, i, y; + int lost; + char st[80]; + unsigned ngraph_pixels[NET_GRAPHHEIGHT][NET_TIMINGS]; + + static int timehistory[NET_TIMINGS]; + static int findex; + + timehistory[findex++&NET_TIMINGSMASK] = frametime; + + x = 0; + lost = CL_CalcNet(); + for (a=0 ; a>1); + x=-x; + y = vid.height - sb_lines - 24 - NET_GRAPHHEIGHT - 1; + + M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8 + 1); + y += 8; + + sprintf(st, "%3i%% packet loss", lost); + Draw_String(8, y, st); + y += 8; + + GL_Bind(netgraphtexture); + + qglTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, + NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA, + GL_UNSIGNED_BYTE, ngraph_pixels); + + GL_TexEnv(GL_MODULATE); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + x = 8; + qglColor3f (1,1,1); + qglBegin (GL_QUADS); + qglTexCoord2f (0, 0); + qglVertex2f (x, y); + qglTexCoord2f (1, 0); + qglVertex2f (x+NET_TIMINGS, y); + qglTexCoord2f (1, 1); + qglVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT); + qglTexCoord2f (0, 1); + qglVertex2f (x, y+NET_GRAPHHEIGHT); + qglEnd (); +} + #endif diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 783efdf4a..19401582d 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -598,7 +598,7 @@ void R_DrawSpriteModel (entity_t *e) GL_DisableMultitexture(); - GL_Bind(frame->gl_texturenum); + GL_Bind(frame->p.d.gl.texnum); { extern int gldepthfunc; diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index a4d5db707..adfbcb4bc 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -2061,8 +2061,10 @@ void GLR_DrawWaterSurfaces (void) } -static void GLR_DrawAlphaSurface(msurface_t *s) +static void GLR_DrawAlphaSurface(int count, msurface_t **surfs, void *type) { + msurface_t *s = (*surfs); + qglPushMatrix(); R_RotateForEntity(s->ownerent); #ifdef Q3SHADERS @@ -3620,7 +3622,6 @@ void GL_CreateSurfaceLightmap (msurface_t *surf, int shift) void GLSurf_DeInit(void) { int i; - qglDeleteTextures(numlightmaps, lightmap_textures); for (i = 0; i < numlightmaps; i++) { if (!lightmap[i]) @@ -3630,7 +3631,10 @@ void GLSurf_DeInit(void) } if (lightmap_textures) + { + qglDeleteTextures(numlightmaps, lightmap_textures); BZ_Free(lightmap_textures); + } if (lightmap) BZ_Free(lightmap); @@ -3650,7 +3654,7 @@ with all the surfaces from all brush models */ void GL_BuildLightmaps (void) { - int i, j; + int i, j, t; model_t *m; int shift; @@ -3740,13 +3744,19 @@ void GL_BuildLightmaps (void) currentmodel = m; shift = GLR_LightmapShift(currentmodel); - for (i=0 ; inumsurfaces ; i++) + for (t = 0; t < m->numtextures; t++) { - GL_CreateSurfaceLightmap (m->surfaces + i, shift); - P_EmitSkyEffectTris(m, &m->surfaces[i]); - if (m->surfaces[i].mesh) //there are some surfaces that have a display list already (the subdivided ones) - continue; - GL_BuildSurfaceDisplayList (m->surfaces + i); + for (i=0 ; inumsurfaces ; i++) + {//extra surface loop so we get slightly less texture switches + if (m->surfaces[i].texinfo->texture == m->textures[t]) + { + GL_CreateSurfaceLightmap (m->surfaces + i, shift); + P_EmitSkyEffectTris(m, &m->surfaces[i]); + if (m->surfaces[i].mesh) //there are some surfaces that have a display list already (the subdivided ones) + continue; + GL_BuildSurfaceDisplayList (m->surfaces + i); + } + } } } diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 253e761a9..29bc9f243 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -1140,7 +1140,7 @@ static shaderkey_t shaderpasskeys[] = // =============================================================== -int Shader_InitCallback (char *name, int size, void *param) +int Shader_InitCallback (const char *name, int size, void *param) { strcpy(shaderbuf+shaderbuflen, name); Shader_MakeCache(shaderbuf+shaderbuflen); @@ -2350,7 +2350,7 @@ void Shader_Default2D(char *shortname, shader_t *s) { mp = Draw_SafeCachePic(va("%s.lmp", shortname)); if (mp) - pass->anim_frames[0] = *(int*)mp->data; + pass->anim_frames[0] = mp->d.gl.texnum; if (!pass->anim_frames[0]) pass->anim_frames[0] = missing_texture; diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index f4ff64f9e..8a5e3218d 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -26,6 +26,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "resource.h" #include +#ifndef SetWindowLongPtr //yes its a define, for unicode support +#define SetWindowLongPtr SetWindowLong +#endif #ifndef CDS_FULLSCREEN #define CDS_FULLSCREEN 4 @@ -65,7 +68,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern cvar_t vid_conwidth, vid_conautoscale; -#define WINDOW_CLASS_NAME "WinQuake" +#define WINDOW_CLASS_NAME "FTEGLQuake" #define MAX_MODE_LIST 128 #define VID_ROW_SIZE 3 @@ -349,11 +352,20 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) DIBWidth = info->width; DIBHeight = info->height; - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX; - ExWindowStyle = 0; + if (sys_hijackwindow) + { + SetWindowLong(sys_hijackwindow, GWL_STYLE, GetWindowLong(sys_hijackwindow, GWL_STYLE)|WS_OVERLAPPED); + WindowStyle = WS_CHILDWINDOW|WS_OVERLAPPED; + ExWindowStyle = 0; + } + else + { + WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | + WS_MINIMIZEBOX; + ExWindowStyle = 0; - WindowStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; + WindowStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; + } rect = WindowRect; AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); @@ -370,7 +382,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) rect.left, rect.top, wwidth, wheight, - NULL, + sys_hijackwindow, NULL, global_hInstance, NULL); @@ -381,9 +393,14 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) return false; } - // Center and show the DIB window - CenterWindow(dibwindow, WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, false); + if (!sys_hijackwindow) + { + // Center and show the DIB window + CenterWindow(dibwindow, WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, false); + } + else + SetFocus(dibwindow); // ShowWindow (dibwindow, SW_SHOWDEFAULT); // UpdateWindow (dibwindow); @@ -575,13 +592,9 @@ static qboolean CreateMainWindow(rendererstate_t *info) { TRACE(("dbg: GLVID_SetMode: VID_SetWindowedMode\n")); stat = VID_SetWindowedMode(info); - IN_ActivateMouse (); - IN_HideMouse (); } else { - IN_DeactivateMouse (); - IN_ShowMouse (); TRACE(("dbg: GLVID_SetMode: VID_SetWindowedMode 2\n")); stat = VID_SetWindowedMode(info); } @@ -590,12 +603,10 @@ static qboolean CreateMainWindow(rendererstate_t *info) { TRACE(("dbg: GLVID_SetMode: VID_SetFullDIBMode\n")); stat = VID_SetFullDIBMode(info); - if (stat) - { - IN_ActivateMouse (); - IN_HideMouse (); - } } + + IN_UpdateGrabs(info->fullscreen, ActiveApp); + return stat; } BOOL CheckForcePixelFormat(rendererstate_t *info); @@ -604,7 +615,9 @@ int GLVID_SetMode (rendererstate_t *info, unsigned char *palette) { int temp; qboolean stat; +#ifndef NPQTV MSG msg; +#endif // HDC hdc; TRACE(("dbg: GLVID_SetMode\n")); @@ -676,12 +689,13 @@ int GLVID_SetMode (rendererstate_t *info, unsigned char *palette) SetForegroundWindow (mainwindow); VID_SetPalette (palette); - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) +#ifndef NPQTV + while (PeekMessage (&msg, mainwindow, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); } - +#endif Sleep (100); SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, @@ -750,7 +764,9 @@ void VID_UnSetMode (void) if (mainwindow) { dibwindow=NULL; -// SendMessage(mainwindow, WM_CLOSE, 0, 0); + // ShowWindow(mainwindow, SW_HIDE); + // SetWindowLongPtr(mainwindow, GWL_WNDPROC, DefWindowProc); + // PostMessage(mainwindow, WM_CLOSE, 0, 0); DestroyWindow(mainwindow); mainwindow = NULL; } @@ -915,33 +931,8 @@ void GL_DoSwap (void) qSwapBuffers(maindc); // handle the mouse state when windowed if that's changed - if (modestate == MS_WINDOWED) - { - if (!_windowed_mouse.value) - { - if (mouseactive) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - else - { - if ((key_dest == key_game||(mouseusedforgui && key_dest != key_console)) && ActiveApp) - { - if (!mouseactive) - { - IN_ActivateMouse (); - IN_HideMouse (); - } - } - else if (mouseactive && key_dest == key_console) - {//!(key_dest == key_game || mouseusedforgui)) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } - } - } + + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); } void GL_EndRendering (void) @@ -1042,13 +1033,6 @@ void GLVID_ShiftPalette (unsigned char *palette) } } - -void VID_SetDefaultMode (void) -{ - IN_DeactivateMouse (); -} - - void GLVID_Shutdown (void) { if (qSetDeviceGammaRamp) @@ -1324,12 +1308,12 @@ qboolean GLAppActivate(BOOL fActive, BOOL minimize) sound_active = true; } + IN_UpdateGrabs(modestate != MS_WINDOWED, ActiveApp); + if (fActive) { if (modestate != MS_WINDOWED) { - IN_ActivateMouse (); - IN_HideMouse (); if (vid_canalttab && vid_wassuspended) { vid_wassuspended = false; ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); @@ -1339,11 +1323,6 @@ qboolean GLAppActivate(BOOL fActive, BOOL minimize) MoveWindow (mainwindow, 0, 0, gdevmode.dmPelsWidth, gdevmode.dmPelsHeight, false); } } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && (key_dest == key_game || key_dest == key_menu)) - { - IN_ActivateMouse (); - IN_HideMouse (); - } Cvar_ForceCallback(&v_gamma); } @@ -1352,18 +1331,11 @@ qboolean GLAppActivate(BOOL fActive, BOOL minimize) { if (modestate != MS_WINDOWED) { - IN_DeactivateMouse (); - IN_ShowMouse (); if (vid_canalttab) { ChangeDisplaySettings (NULL, 0); vid_wassuspended = true; } } - else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) - { - IN_DeactivateMouse (); - IN_ShowMouse (); - } Cvar_ForceCallback(&v_gamma); //wham bam thanks. @@ -1405,16 +1377,33 @@ LONG WINAPI GLMainWndProc ( switch (uMsg) { case WM_KILLFOCUS: + GLAppActivate(FALSE, Minimized); if (modestate == MS_FULLDIB) ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); + ClearAllStates (); + break; + case WM_SETFOCUS: + if (!GLAppActivate(TRUE, Minimized)) + break; + ClearAllStates (); break; case WM_CREATE: break; case WM_MOVE: - window_x = (int) LOWORD(lParam); - window_y = (int) HIWORD(lParam); + { + RECT r; +// window_x = (int) LOWORD(lParam); +// window_y = (int) HIWORD(lParam); + GetWindowRect(hWnd, &r); + window_x = r.left; + window_y = r.top; + window_width = r.right - r.left; + window_height = r.bottom - r.top; + glwidth = window_width; + glheight = window_height; + } VID_UpdateWindowStatus (); break; @@ -1448,7 +1437,12 @@ LONG WINAPI GLMainWndProc ( temp = 0; if (wParam & MK_LBUTTON) + { temp |= 1; +#ifdef NPQTV + SetFocus(hWnd); +#endif + } if (wParam & MK_RBUTTON) temp |= 2; @@ -1606,6 +1600,7 @@ void VID_Init8bitPalette() void GLVID_DeInit (void) { GLVID_Shutdown(); + ActiveApp = false; Cvar_Unhook(&_vid_wait_override); @@ -1636,11 +1631,8 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) wc.lpszMenuName = 0; wc.lpszClassName = WINDOW_CLASS_NAME; - if (!RegisterClass (&wc) ) - { - Con_Printf(CON_ERROR "Couldn't register window class\n"); - return false; - } + if (!RegisterClass (&wc)) //this isn't really fatal, we'll let the CreateWindow fail instead. + MessageBox(NULL, "RegisterClass failed", "GAH", 0); hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); diff --git a/engine/gl/gltod3d/gl_fakegl.cpp b/engine/gl/gltod3d/gl_fakegl.cpp index b9ee64073..ec54bcce0 100644 --- a/engine/gl/gltod3d/gl_fakegl.cpp +++ b/engine/gl/gltod3d/gl_fakegl.cpp @@ -4144,6 +4144,7 @@ rendererinfo_t d3drendererinfo = { Mod_GetTag, Mod_TagNumForName, NULL, + NULL, D3DVID_Init, GLVID_DeInit, diff --git a/engine/gl/model_hl.h b/engine/gl/model_hl.h index 961c3101a..32e56b332 100644 --- a/engine/gl/model_hl.h +++ b/engine/gl/model_hl.h @@ -167,7 +167,8 @@ typedef struct { char name[32]; float timing; - int unknown1[5]; + int loop; + int unknown1[4]; int numframes; int unknown2[2]; int motiontype; diff --git a/engine/http/ftpserver.c b/engine/http/ftpserver.c index a917f4c68..31e43159c 100644 --- a/engine/http/ftpserver.c +++ b/engine/http/ftpserver.c @@ -14,8 +14,6 @@ int ftpfilelistsocket; -char *COM_ParseOut (char *data, char *out, int outlen); - static iwboolean ftpserverinitied = false; iwboolean ftpserverfailed = false; static int ftpserversocket; @@ -103,22 +101,26 @@ void FTP_ServerShutdown(void) IWebPrintf("FTP server is deactivated\n"); } -static int SendFileNameTo(char *fname, int size, void *param) +static int SendFileNameTo(const char *rawname, int size, void *param) { int socket = ftpfilelistsocket; //64->32... this is safe due to where it's called from. It's just not so portable. // int i; char buffer[256+1]; char *slash; - int isdir = fname[strlen(fname)-1] == '/'; + char nondirname[MAX_QPATH]; + int isdir = rawname[strlen(rawname)-1] == '/'; + char *fname; #ifndef WEBSVONLY //copy protection of the like that QWSV normally has. if (!isdir) - if (!SV_AllowDownload(fname)) //don't advertise if we're going to disallow it + if (!SV_AllowDownload(rawname)) //don't advertise if we're going to disallow it return true; #endif + Q_strncpyz(nondirname, rawname, sizeof(nondirname)); if (isdir) - fname[strlen(fname)-1] = '\0'; + nondirname[strlen(nondirname)-1] = '\0'; + fname = nondirname; while((slash = strchr(fname, '/'))) fname = slash+1; diff --git a/engine/http/iweb.h b/engine/http/iweb.h index 200a46e30..5893f8d06 100644 --- a/engine/http/iweb.h +++ b/engine/http/iweb.h @@ -71,7 +71,7 @@ struct sockaddr; struct sockaddr_qstorage; int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s); -qboolean SV_AllowDownload (char *name); +qboolean SV_AllowDownload (const char *name); typedef qboolean iwboolean; @@ -108,11 +108,11 @@ vfsfile_t *IWebGenerateFile(char *name, char *content, int contentlength); -char *COM_ParseOut (char *data, char *out, int outlen); -void COM_EnumerateFiles (char *match, int (*func)(char *, int, void *), void *parm); +char *COM_ParseOut (const char *data, char *out, int outlen); +void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *), void *parm); -char *Q_strcpyline(char *out, char *in, int maxlen); +char *Q_strcpyline(char *out, const char *in, int maxlen); diff --git a/engine/http/iwebiface.c b/engine/http/iwebiface.c index ac452218f..ae3587668 100644 --- a/engine/http/iwebiface.c +++ b/engine/http/iwebiface.c @@ -512,7 +512,7 @@ iwboolean FTP_StringToAdr (const char *s, qbyte ip[4], qbyte port[2]) return true; } -char *Q_strcpyline(char *out, char *in, int maxlen) +char *Q_strcpyline(char *out, const char *in, int maxlen) { char *w = out; while (*in && maxlen > 0) diff --git a/engine/http/webgen.c b/engine/http/webgen.c index 040f1ae65..1a58d8fc7 100644 --- a/engine/http/webgen.c +++ b/engine/http/webgen.c @@ -347,7 +347,7 @@ int VFSGen_ReadBytes(vfsfile_t *f, void *buffer, int bytes) return bytes; } -int VFSGen_WriteBytes(vfsfile_t *f, void *buffer, int bytes) +int VFSGen_WriteBytes(vfsfile_t *f, const void *buffer, int bytes) { Sys_Error("VFSGen_WriteBytes: Readonly\n"); return 0; diff --git a/engine/libs/npapi/npapi.h b/engine/libs/npapi/npapi.h new file mode 100644 index 000000000..6f783a1dd --- /dev/null +++ b/engine/libs/npapi/npapi.h @@ -0,0 +1,766 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +/* + * npapi.h $Revision: 3.48 $ + * Netscape client plug-in API spec + */ + +#ifndef _NPAPI_H_ +#define _NPAPI_H_ + +#ifdef __OS2__ +#pragma pack(1) +#endif + +#include "prtypes.h" +/* Copied from xp_core.h */ +/* removed #ifdef for hpux defined in /usr/include/model.h */ +#ifndef _INT16 +#define _INT16 +#endif +#ifndef _INT32 +#define _INT32 +#endif +#ifndef _UINT16 +#define _UINT16 +#endif +#ifndef _UINT32 +#define _UINT32 +#endif + +/* + * NO_NSPR_10_SUPPORT disables the inclusion + * of obsolete/protypes.h, whose int16, uint16, + * int32, and uint32 typedefs conflict with those + * in this file. + */ +#ifndef NO_NSPR_10_SUPPORT +#define NO_NSPR_10_SUPPORT +#endif +#ifdef OJI +#include "jri.h" /* Java Runtime Interface */ +#endif + +#if defined (__OS2__ ) || defined (OS2) +# ifndef XP_OS2 +# define XP_OS2 1 +# endif /* XP_OS2 */ +#endif /* __OS2__ */ + +#ifdef _WINDOWS +# include +# ifndef XP_WIN +# define XP_WIN 1 +# endif /* XP_WIN */ +#endif /* _WINDOWS */ + +#ifdef __MWERKS__ +# define _declspec __declspec +# ifdef __INTEL__ +# undef NULL +# ifndef XP_WIN +# define XP_WIN 1 +# endif /* XP_WIN */ +# endif /* __INTEL__ */ +#endif /* __MWERKS__ */ + +#ifdef XP_MACOSX +#include +#ifdef __LP64__ +#define NP_NO_QUICKDRAW +#endif +#endif + +#if defined(XP_UNIX) +# include +# if defined(MOZ_X11) +# include +# include +# endif +#endif + +/*----------------------------------------------------------------------*/ +/* Plugin Version Constants */ +/*----------------------------------------------------------------------*/ + +#define NP_VERSION_MAJOR 0 +#define NP_VERSION_MINOR 19 + + +/* The OS/2 version of Netscape uses RC_DATA to define the + mime types, file extensions, etc that are required. + Use a vertical bar to separate types, end types with \0. + FileVersion and ProductVersion are 32bit ints, all other + entries are strings the MUST be terminated wwith a \0. + +AN EXAMPLE: + +RCDATA NP_INFO_ProductVersion { 1,0,0,1,} + +RCDATA NP_INFO_MIMEType { "video/x-video|", + "video/x-flick\0" } +RCDATA NP_INFO_FileExtents { "avi|", + "flc\0" } +RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|", + "MMOS2 Flc/Fli player(*.flc)\0" } + +RCDATA NP_INFO_FileVersion { 1,0,0,1 } +RCDATA NP_INFO_CompanyName { "Netscape Communications\0" } +RCDATA NP_INFO_FileDescription { "NPAVI32 Extension DLL\0" +RCDATA NP_INFO_InternalName { "NPAVI32\0" ) +RCDATA NP_INFO_LegalCopyright { "Copyright Netscape Communications \251 1996\0" +RCDATA NP_INFO_OriginalFilename { "NVAPI32.DLL" } +RCDATA NP_INFO_ProductName { "NPAVI32 Dynamic Link Library\0" } + +*/ + + +/* RC_DATA types for version info - required */ +#define NP_INFO_ProductVersion 1 +#define NP_INFO_MIMEType 2 +#define NP_INFO_FileOpenName 3 +#define NP_INFO_FileExtents 4 + +/* RC_DATA types for version info - used if found */ +#define NP_INFO_FileDescription 5 +#define NP_INFO_ProductName 6 + +/* RC_DATA types for version info - optional */ +#define NP_INFO_CompanyName 7 +#define NP_INFO_FileVersion 8 +#define NP_INFO_InternalName 9 +#define NP_INFO_LegalCopyright 10 +#define NP_INFO_OriginalFilename 11 + +#ifndef RC_INVOKED + + + +/*----------------------------------------------------------------------*/ +/* Definition of Basic Types */ +/*----------------------------------------------------------------------*/ + +#ifndef _UINT16 +typedef unsigned short uint16; +#endif + +#ifndef _UINT32 +# if defined(__alpha) || defined(__amd64__) || defined(__x86_64__) +typedef unsigned int uint32; +# else /* __alpha */ +typedef unsigned long uint32; +# endif /* __alpha */ +#endif + +/* + * AIX defines these in sys/inttypes.h included from sys/types.h + */ +#ifndef AIX +#ifndef _INT16 +typedef short int16; +#endif + +#ifndef _INT32 +# if defined(__alpha) || defined(__amd64__) || defined(__x86_64__) +typedef int int32; +# else /* __alpha */ +typedef long int32; +# endif /* __alpha */ +#endif +#endif + +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef NULL +#define NULL (0L) +#endif + +#ifdef XP_MACOSX +typedef enum { +#ifndef NP_NO_QUICKDRAW + NPDrawingModelQuickDraw = 0, +#endif + NPDrawingModelCoreGraphics = 1 +} NPDrawingModel; +#endif + +typedef unsigned char NPBool; +typedef int16 NPError; +typedef int16 NPReason; +typedef char* NPMIMEType; + + + +/*----------------------------------------------------------------------*/ +/* Structures and definitions */ +/*----------------------------------------------------------------------*/ + +/* + * NPP is a plug-in's opaque instance handle + */ +typedef struct _NPP +{ + void* pdata; /* plug-in private data */ + void* ndata; /* netscape private data */ +} NPP_t; + +typedef NPP_t* NPP; + + +typedef struct _NPStream +{ + void* pdata; /* plug-in private data */ + void* ndata; /* netscape private data */ + const char* url; + uint32 end; + uint32 lastmodified; + void* notifyData; + const char* headers; /* Response headers from host. + * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS. + * Used for HTTP only; NULL for non-HTTP. + * Available from NPP_NewStream onwards. + * Plugin should copy this data before storing it. + * Includes HTTP status line and all headers, + * preferably verbatim as received from server, + * headers formatted as in HTTP ("Header: Value"), + * and newlines (\n, NOT \r\n) separating lines. + * Terminated by \n\0 (NOT \n\n\0). */ +} NPStream; + + +typedef struct _NPByteRange +{ + int32 offset; /* negative offset means from the end */ + uint32 length; + struct _NPByteRange* next; +} NPByteRange; + + +typedef struct _NPSavedData +{ + int32 len; + void* buf; +} NPSavedData; + + +typedef struct _NPRect +{ + uint16 top; + uint16 left; + uint16 bottom; + uint16 right; +} NPRect; + +typedef struct _NPSize +{ + int32 width; + int32 height; +} NPSize; + +#ifdef XP_UNIX +/* + * Unix specific structures and definitions + */ + +/* + * Callback Structures. + * + * These are used to pass additional platform specific information. + */ +enum { + NP_SETWINDOW = 1, + NP_PRINT +}; + +typedef struct +{ + int32 type; +} NPAnyCallbackStruct; + +typedef struct +{ + int32 type; +#ifdef MOZ_X11 + Display* display; + Visual* visual; + Colormap colormap; + unsigned int depth; +#endif +} NPSetWindowCallbackStruct; + +typedef struct +{ + int32 type; + FILE* fp; +} NPPrintCallbackStruct; + +#endif /* XP_UNIX */ + + +/* + * The following masks are applied on certain platforms to NPNV and + * NPPV selectors that pass around pointers to COM interfaces. Newer + * compilers on some platforms may generate vtables that are not + * compatible with older compilers. To prevent older plugins from + * not understanding a new browser's ABI, these masks change the + * values of those selectors on those platforms. To remain backwards + * compatible with differenet versions of the browser, plugins can + * use these masks to dynamically determine and use the correct C++ + * ABI that the browser is expecting. This does not apply to Windows + * as Microsoft's COM ABI will likely not change. + */ + +#define NP_ABI_GCC3_MASK 0x10000000 +/* + * gcc 3.x generated vtables on UNIX and OSX are incompatible with + * previous compilers. + */ +#if (defined (XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3)) +#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK +#else +#define _NP_ABI_MIXIN_FOR_GCC3 0 +#endif + + +#define NP_ABI_MACHO_MASK 0x01000000 +/* + * On OSX, the Mach-O executable format is significantly + * different than CFM. In addition to having a different + * C++ ABI, it also has has different C calling convention. + * You must use glue code when calling between CFM and + * Mach-O C functions. + */ +#if (defined(TARGET_RT_MAC_MACHO)) +#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK +#else +#define _NP_ABI_MIXIN_FOR_MACHO 0 +#endif + + +#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO) + +/* + * List of variable names for which NPP_GetValue shall be implemented + */ +typedef enum { + NPPVpluginNameString = 1, + NPPVpluginDescriptionString, + NPPVpluginWindowBool, + NPPVpluginTransparentBool, + NPPVjavaClass, /* Not implemented in Mozilla 1.0 */ + NPPVpluginWindowSize, + NPPVpluginTimerInterval, + + NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), + NPPVpluginScriptableIID = 11, + + /* Introduced in Mozilla 0.9.9 */ + NPPVjavascriptPushCallerBool = 12, + + /* Introduced in Mozilla 1.0 */ + NPPVpluginKeepLibraryInMemory = 13, + NPPVpluginNeedsXEmbed = 14, + + /* Get the NPObject for scripting the plugin. Introduced in Firefox + * 1.0 (NPAPI minor version 14). + */ + NPPVpluginScriptableNPObject = 15, + + /* Get the plugin value (as \0-terminated UTF-8 string data) for + * form submission if the plugin is part of a form. Use + * NPN_MemAlloc() to allocate memory for the string data. Introduced + * in Mozilla 1.8b2 (NPAPI minor version 15). + */ + NPPVformValue = 16 +#ifdef XP_MACOSX + /* Used for negotiating drawing models */ + , NPPVpluginDrawingModel = 1000 +#endif +} NPPVariable; + +/* + * List of variable names for which NPN_GetValue is implemented by Mozilla + */ +typedef enum { + NPNVxDisplay = 1, + NPNVxtAppContext, + NPNVnetscapeWindow, + NPNVjavascriptEnabledBool, + NPNVasdEnabledBool, + NPNVisOfflineBool, + + /* 10 and over are available on Mozilla builds starting with 0.9.4 */ + NPNVserviceManager = (10 | NP_ABI_MASK), + NPNVDOMElement = (11 | NP_ABI_MASK), /* available in Mozilla 1.2 */ + NPNVDOMWindow = (12 | NP_ABI_MASK), + NPNVToolkit = (13 | NP_ABI_MASK), + NPNVSupportsXEmbedBool = 14, + + /* Get the NPObject wrapper for the browser window. */ + NPNVWindowNPObject = 15, + + /* Get the NPObject wrapper for the plugins DOM element. */ + NPNVPluginElementNPObject = 16, + + NPNVSupportsWindowless = 17 + +#ifdef XP_MACOSX + /* Used for negotiating drawing models */ + , NPNVpluginDrawingModel = 1000 +#ifndef NP_NO_QUICKDRAW + , NPNVsupportsQuickDrawBool = 2000 +#endif + , NPNVsupportsCoreGraphicsBool = 2001 +#endif +} NPNVariable; + +/* + * The type of Tookkit the widgets use + */ +typedef enum { + NPNVGtk12 = 1, + NPNVGtk2 +} NPNToolkitType; + +/* + * The type of a NPWindow - it specifies the type of the data structure + * returned in the window field. + */ +typedef enum { + NPWindowTypeWindow = 1, + NPWindowTypeDrawable +} NPWindowType; + +typedef struct _NPWindow +{ + void* window; /* Platform specific window handle */ + /* OS/2: x - Position of bottom left corner */ + /* OS/2: y - relative to visible netscape window */ + int32 x; /* Position of top left corner relative */ + int32 y; /* to a netscape page. */ + uint32 width; /* Maximum window size */ + uint32 height; + NPRect clipRect; /* Clipping rectangle in port coordinates */ + /* Used by MAC only. */ +#if defined(XP_UNIX) && !defined(XP_MACOSX) + void * ws_info; /* Platform-dependent additonal data */ +#endif /* XP_UNIX */ + NPWindowType type; /* Is this a window or a drawable? */ +} NPWindow; + + +typedef struct _NPFullPrint +{ + NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */ + NPBool printOne; /* TRUE if plugin should print one copy to default printer */ + void* platformPrint; /* Platform-specific printing info */ +} NPFullPrint; + +typedef struct _NPEmbedPrint +{ + NPWindow window; + void* platformPrint; /* Platform-specific printing info */ +} NPEmbedPrint; + +typedef struct _NPPrint +{ + uint16 mode; /* NP_FULL or NP_EMBED */ + union + { + NPFullPrint fullPrint; /* if mode is NP_FULL */ + NPEmbedPrint embedPrint; /* if mode is NP_EMBED */ + } print; +} NPPrint; + +#ifdef XP_MACOSX +typedef EventRecord NPEvent; +#elif defined(XP_WIN) +typedef struct _NPEvent +{ + uint16 event; + uint32 wParam; + uint32 lParam; +} NPEvent; +#elif defined(XP_OS2) +typedef struct _NPEvent +{ + uint32 event; + uint32 wParam; + uint32 lParam; +} NPEvent; +#elif defined (XP_UNIX) && defined(MOZ_X11) +typedef XEvent NPEvent; +#else +typedef void* NPEvent; +#endif /* XP_MACOSX */ + +#ifdef XP_MACOSX +typedef void* NPRegion; +#ifndef NP_NO_QUICKDRAW +typedef RgnHandle NPQDRegion; +#endif +typedef CGPathRef NPCGRegion; +#elif defined(XP_WIN) +typedef HRGN NPRegion; +#elif defined(XP_UNIX) && defined(MOZ_X11) +typedef Region NPRegion; +#else +typedef void *NPRegion; +#endif /* XP_MACOSX */ + +#ifdef XP_MACOSX +/* + * Mac-specific structures and definitions. + */ + +typedef struct NP_Port +{ + CGrafPtr port; /* Grafport */ + int32 portx; /* position inside the topmost window */ + int32 porty; +} NP_Port; + +typedef struct NP_CGContext +{ + CGContextRef context; + WindowRef window; +} NP_CGContext; + +/* + * Non-standard event types that can be passed to HandleEvent + */ + +enum NPEventType { + NPEventType_GetFocusEvent = (osEvt + 16), + NPEventType_LoseFocusEvent, + NPEventType_AdjustCursorEvent, + NPEventType_MenuCommandEvent, + NPEventType_ClippingChangedEvent, + NPEventType_ScrollingBeginsEvent = 1000, + NPEventType_ScrollingEndsEvent +}; + +#ifdef OBSOLETE +#define getFocusEvent (osEvt + 16) +#define loseFocusEvent (osEvt + 17) +#define adjustCursorEvent (osEvt + 18) +#endif +#endif /* XP_MACOSX */ + +/* + * Values for mode passed to NPP_New: + */ +#define NP_EMBED 1 +#define NP_FULL 2 + +/* + * Values for stream type passed to NPP_NewStream: + */ +#define NP_NORMAL 1 +#define NP_SEEK 2 +#define NP_ASFILE 3 +#define NP_ASFILEONLY 4 + +#define NP_MAXREADY (((unsigned)(~0)<<1)>>1) + + +/*----------------------------------------------------------------------*/ +/* Error and Reason Code definitions */ +/*----------------------------------------------------------------------*/ + +/* + * Values of type NPError: + */ +#define NPERR_BASE 0 +#define NPERR_NO_ERROR (NPERR_BASE + 0) +#define NPERR_GENERIC_ERROR (NPERR_BASE + 1) +#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2) +#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3) +#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4) +#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5) +#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6) +#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7) +#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8) +#define NPERR_INVALID_PARAM (NPERR_BASE + 9) +#define NPERR_INVALID_URL (NPERR_BASE + 10) +#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11) +#define NPERR_NO_DATA (NPERR_BASE + 12) +#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13) + +/* + * Values of type NPReason: + */ +#define NPRES_BASE 0 +#define NPRES_DONE (NPRES_BASE + 0) +#define NPRES_NETWORK_ERR (NPRES_BASE + 1) +#define NPRES_USER_BREAK (NPRES_BASE + 2) + +/* + * Don't use these obsolete error codes any more. + */ +#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR +#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR +#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK + +/* + * Version feature information + */ +#define NPVERS_HAS_STREAMOUTPUT 8 +#define NPVERS_HAS_NOTIFICATION 9 +#define NPVERS_HAS_LIVECONNECT 9 +#define NPVERS_WIN16_HAS_LIVECONNECT 9 +#define NPVERS_68K_HAS_LIVECONNECT 11 +#define NPVERS_HAS_WINDOWLESS 11 +#define NPVERS_HAS_XPCONNECT_SCRIPTING 13 +#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14 +#define NPVERS_HAS_FORM_VALUES 15 +#define NPVERS_HAS_POPUPS_ENABLED_STATE 16 +#define NPVERS_HAS_RESPONSE_HEADERS 17 +#define NPVERS_HAS_NPOBJECT_ENUM 18 +#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19 + +/*----------------------------------------------------------------------*/ +/* Function Prototypes */ +/*----------------------------------------------------------------------*/ + +#if defined(_WINDOWS) && !defined(WIN32) +#define NP_LOADDS _loadds +#else +#if defined(__OS2__) +#define NP_LOADDS _System +#else +#define NP_LOADDS +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NPP_* functions are provided by the plugin and called by the navigator. + */ + +#ifdef XP_UNIX +char* NPP_GetMIMEDescription(void); +#endif /* XP_UNIX */ + +NPError NP_LOADDS NPP_Initialize(void); +void NP_LOADDS NPP_Shutdown(void); +NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, + uint16 mode, int16 argc, char* argn[], + char* argv[], NPSavedData* saved); +NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save); +NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window); +NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, + NPStream* stream, NPBool seekable, + uint16* stype); +NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, + NPReason reason); +int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream); +int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset, + int32 len, void* buffer); +void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, + const char* fname); +void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint); +int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event); +void NP_LOADDS NPP_URLNotify(NPP instance, const char* url, + NPReason reason, void* notifyData); +#ifdef OJI +jref NP_LOADDS NPP_GetJavaClass(void); +#endif +NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value); +NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value); + +/* + * NPN_* functions are provided by the navigator and called by the plugin. + */ +void NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor, + int* netscape_major, int* netscape_minor); +NPError NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url, + const char* target, void* notifyData); +NPError NP_LOADDS NPN_GetURL(NPP instance, const char* url, + const char* target); +NPError NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url, + const char* target, uint32 len, + const char* buf, NPBool file, + void* notifyData); +NPError NP_LOADDS NPN_PostURL(NPP instance, const char* url, + const char* target, uint32 len, + const char* buf, NPBool file); +NPError NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList); +NPError NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type, + const char* target, NPStream** stream); +int32 NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer); +NPError NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream, NPReason reason); +void NP_LOADDS NPN_Status(NPP instance, const char* message); +const char* NP_LOADDS NPN_UserAgent(NPP instance); +void* NP_LOADDS NPN_MemAlloc(uint32 size); +void NP_LOADDS NPN_MemFree(void* ptr); +uint32 NP_LOADDS NPN_MemFlush(uint32 size); +void NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages); +#ifdef OJI +JRIEnv* NP_LOADDS NPN_GetJavaEnv(void); +jref NP_LOADDS NPN_GetJavaPeer(NPP instance); +#endif +NPError NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable, void *value); +NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable, void *value); +void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect); +void NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion); +void NP_LOADDS NPN_ForceRedraw(NPP instance); +void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled); +void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance); +void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance, + void (*func) (void *), + void *userData); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* RC_INVOKED */ +#ifdef __OS2__ +#pragma pack() +#endif + +#endif /* _NPAPI_H_ */ diff --git a/engine/libs/npapi/npruntime.h b/engine/libs/npapi/npruntime.h new file mode 100644 index 000000000..5a2dc75d1 --- /dev/null +++ b/engine/libs/npapi/npruntime.h @@ -0,0 +1,423 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright © 2004, Apple Computer, Inc. and The Mozilla Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla + * Foundation ("Mozilla") nor the names of their contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR + * THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Revision 1 (March 4, 2004): + * Initial proposal. + * + * Revision 2 (March 10, 2004): + * All calls into script were made asynchronous. Results are + * provided via the NPScriptResultFunctionPtr callback. + * + * Revision 3 (March 10, 2004): + * Corrected comments to not refer to class retain/release FunctionPtrs. + * + * Revision 4 (March 11, 2004): + * Added additional convenience NPN_SetExceptionWithUTF8(). + * Changed NPHasPropertyFunctionPtr and NPHasMethodFunctionPtr to take NPClass + * pointers instead of NPObject pointers. + * Added NPIsValidIdentifier(). + * + * Revision 5 (March 17, 2004): + * Added context parameter to result callbacks from ScriptObject functions. + * + * Revision 6 (March 29, 2004): + * Renamed functions implemented by user agent to NPN_*. Removed _ from + * type names. + * Renamed "JavaScript" types to "Script". + * + * Revision 7 (April 21, 2004): + * NPIdentifier becomes a void*, was int32_t + * Remove NP_IsValidIdentifier, renamed NP_IdentifierFromUTF8 to NP_GetIdentifier + * Added NPVariant and modified functions to use this new type. + * + * Revision 8 (July 9, 2004): + * Updated to joint Apple-Mozilla license. + * + */ +#ifndef _NP_RUNTIME_H_ +#define _NP_RUNTIME_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nptypes.h" + +/* + This API is used to facilitate binding code written in C to script + objects. The API in this header does not assume the presence of a + user agent. That is, it can be used to bind C code to scripting + environments outside of the context of a user agent. + + However, the normal use of the this API is in the context of a + scripting environment running in a browser or other user agent. + In particular it is used to support the extended Netscape + script-ability API for plugins (NP-SAP). NP-SAP is an extension + of the Netscape plugin API. As such we have adopted the use of + the "NP" prefix for this API. + + The following NP{N|P}Variables were added to the Netscape plugin + API (in npapi.h): + + NPNVWindowNPObject + NPNVPluginElementNPObject + NPPVpluginScriptableNPObject + + These variables are exposed through NPN_GetValue() and + NPP_GetValue() (respectively) and are used to establish the + initial binding between the user agent and native code. The DOM + objects in the user agent can be examined and manipulated using + the NPN_ functions that operate on NPObjects described in this + header. + + To the extent possible the assumptions about the scripting + language used by the scripting environment have been minimized. +*/ + +#define NP_BEGIN_MACRO do { +#define NP_END_MACRO } while (0) + +/* + Objects (non-primitive data) passed between 'C' and script is + always wrapped in an NPObject. The 'interface' of an NPObject is + described by an NPClass. +*/ +typedef struct NPObject NPObject; +typedef struct NPClass NPClass; + +typedef char NPUTF8; +typedef struct _NPString { + const NPUTF8 *utf8characters; + uint32_t utf8length; +} NPString; + +typedef enum { + NPVariantType_Void, + NPVariantType_Null, + NPVariantType_Bool, + NPVariantType_Int32, + NPVariantType_Double, + NPVariantType_String, + NPVariantType_Object +} NPVariantType; + +typedef struct _NPVariant { + NPVariantType type; + union { + bool boolValue; + int32_t intValue; + double doubleValue; + NPString stringValue; + NPObject *objectValue; + } value; +} NPVariant; + +/* + NPN_ReleaseVariantValue is called on all 'out' parameters + references. Specifically it is to be called on variants that own + their value, as is the case with all non-const NPVariant* + arguments after a successful call to any methods (except this one) + in this API. + + After calling NPN_ReleaseVariantValue, the type of the variant + will be NPVariantType_Void. +*/ +void NPN_ReleaseVariantValue(NPVariant *variant); + +#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void) +#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null) +#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool) +#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32) +#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double) +#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String) +#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object) + +#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue) +#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue) +#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue) +#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue) +#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue) + +#define VOID_TO_NPVARIANT(_v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Void; \ + (_v).value.objectValue = NULL; \ +NP_END_MACRO + +#define NULL_TO_NPVARIANT(_v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Null; \ + (_v).value.objectValue = NULL; \ +NP_END_MACRO + +#define BOOLEAN_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Bool; \ + (_v).value.boolValue = !!(_val); \ +NP_END_MACRO + +#define INT32_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Int32; \ + (_v).value.intValue = _val; \ +NP_END_MACRO + +#define DOUBLE_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Double; \ + (_v).value.doubleValue = _val; \ +NP_END_MACRO + +#define STRINGZ_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_String; \ + NPString str = { _val, strlen(_val) }; \ + (_v).value.stringValue = str; \ +NP_END_MACRO + +#define STRINGN_TO_NPVARIANT(_val, _len, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_String; \ + NPString str = { _val, _len }; \ + (_v).value.stringValue = str; \ +NP_END_MACRO + +#define OBJECT_TO_NPVARIANT(_val, _v) \ +NP_BEGIN_MACRO \ + (_v).type = NPVariantType_Object; \ + (_v).value.objectValue = _val; \ +NP_END_MACRO + + +/* + Type mappings (JavaScript types have been used for illustration + purposes): + + JavaScript to C (NPVariant with type:) + undefined NPVariantType_Void + null NPVariantType_Null + Boolean NPVariantType_Bool + Number NPVariantType_Double or NPVariantType_Int32 + String NPVariantType_String + Object NPVariantType_Object + + C (NPVariant with type:) to JavaScript + NPVariantType_Void undefined + NPVariantType_Null null + NPVariantType_Bool Boolean + NPVariantType_Int32 Number + NPVariantType_Double Number + NPVariantType_String String + NPVariantType_Object Object +*/ + +typedef void *NPIdentifier; + +/* + NPObjects have methods and properties. Methods and properties are + identified with NPIdentifiers. These identifiers may be reflected + in script. NPIdentifiers can be either strings or integers, IOW, + methods and properties can be identified by either strings or + integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be + compared using ==. In case of any errors, the requested + NPIdentifier(s) will be NULL. +*/ +NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name); +void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, + NPIdentifier *identifiers); +NPIdentifier NPN_GetIntIdentifier(int32_t intid); +bool NPN_IdentifierIsString(NPIdentifier identifier); + +/* + The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed. +*/ +NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier); + +/* + Get the integer represented by identifier. If identifier is not an + integer identifier, the behaviour is undefined. +*/ +int32_t NPN_IntFromIdentifier(NPIdentifier identifier); + +/* + NPObject behavior is implemented using the following set of + callback functions. + + The NPVariant *result argument of these functions (where + applicable) should be released using NPN_ReleaseVariantValue(). +*/ +typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass); +typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj); +typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj); +typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name); +typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, NPIdentifier name, + const NPVariant *args, uint32_t argCount, + NPVariant *result); +typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj, + const NPVariant *args, + uint32_t argCount, + NPVariant *result); +typedef bool (*NPHasPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name); +typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name, + NPVariant *result); +typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name, + const NPVariant *value); +typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, + NPIdentifier name); +typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, + uint32_t *count); +typedef bool (*NPConstructFunctionPtr)(NPObject *npobj, + const NPVariant *args, + uint32_t argCount, + NPVariant *result); + +/* + NPObjects returned by create, retain, invoke, and getProperty pass + a reference count to the caller. That is, the callee adds a + reference count which passes to the caller. It is the caller's + responsibility to release the returned object. + + NPInvokeFunctionPtr function may return 0 to indicate a void + result. + + NPInvalidateFunctionPtr is called by the scripting environment + when the native code is shutdown. Any attempt to message a + NPObject instance after the invalidate callback has been + called will result in undefined behavior, even if the native code + is still retaining those NPObject instances. (The runtime + will typically return immediately, with 0 or NULL, from an attempt + to dispatch to a NPObject, but this behavior should not be + depended upon.) + + The NPEnumerationFunctionPtr function may pass an array of + NPIdentifiers back to the caller. The callee allocs the memory of + the array using NPN_MemAlloc(), and it's the caller's responsibility + to release it using NPN_MemFree(). +*/ +struct NPClass +{ + uint32_t structVersion; + NPAllocateFunctionPtr allocate; + NPDeallocateFunctionPtr deallocate; + NPInvalidateFunctionPtr invalidate; + NPHasMethodFunctionPtr hasMethod; + NPInvokeFunctionPtr invoke; + NPInvokeDefaultFunctionPtr invokeDefault; + NPHasPropertyFunctionPtr hasProperty; + NPGetPropertyFunctionPtr getProperty; + NPSetPropertyFunctionPtr setProperty; + NPRemovePropertyFunctionPtr removeProperty; + NPEnumerationFunctionPtr enumerate; + NPConstructFunctionPtr construct; +}; + +#define NP_CLASS_STRUCT_VERSION 3 + +#define NP_CLASS_STRUCT_VERSION_ENUM 2 +#define NP_CLASS_STRUCT_VERSION_CTOR 3 + +#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \ + ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM) + +#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \ + ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR) + +struct NPObject { + NPClass *_class; + uint32_t referenceCount; + /* + * Additional space may be allocated here by types of NPObjects + */ +}; + +/* + If the class has an allocate function, NPN_CreateObject invokes + that function, otherwise a NPObject is allocated and + returned. This method will initialize the referenceCount member of + the NPObject to 1. +*/ +NPObject *NPN_CreateObject(NPP npp, NPClass *aClass); + +/* + Increment the NPObject's reference count. +*/ +NPObject *NPN_RetainObject(NPObject *npobj); + +/* + Decremented the NPObject's reference count. If the reference + count goes to zero, the class's destroy function is invoke if + specified, otherwise the object is freed directly. +*/ +void NPN_ReleaseObject(NPObject *npobj); + +/* + Functions to access script objects represented by NPObject. + + Calls to script objects are synchronous. If a function returns a + value, it will be supplied via the result NPVariant + argument. Successful calls will return true, false will be + returned in case of an error. + + Calls made from plugin code to script must be made from the thread + on which the plugin was initialized. +*/ + +bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, + const NPVariant *args, uint32_t argCount, NPVariant *result); +bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result); +bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, + NPVariant *result); +bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, + NPVariant *result); +bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, + const NPVariant *value); +bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); +bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); +bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName); +bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, + uint32_t *count); +bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result); + +/* + NPN_SetException may be called to trigger a script exception upon + return from entry points into NPObjects. Typical usage: + + NPN_SetException (npobj, message); +*/ +void NPN_SetException(NPObject *npobj, const NPUTF8 *message); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/engine/libs/npapi/nptypes.h b/engine/libs/npapi/nptypes.h new file mode 100644 index 000000000..6f6e3fbf4 --- /dev/null +++ b/engine/libs/npapi/nptypes.h @@ -0,0 +1,105 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johnny Stenback (Original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Header file for ensuring that C99 types ([u]int32_t and bool) are + * available. + */ + +#if defined(WIN32) || defined(OS2) + /* + * Win32 and OS/2 don't know C99, so define [u]int_32 here. The bool + * is predefined tho, both in C and C++. + */ + typedef int int32_t; + typedef unsigned int uint32_t; +#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX) + /* + * AIX and SunOS ship a inttypes.h header that defines [u]int32_t, + * but not bool for C. + */ + #include + + #ifndef __cplusplus + typedef int bool; + #endif +#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD) + /* + * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and + * u_int32_t. + */ + #include + + /* + * BSD/OS ships no header that defines uint32_t, nor bool (for C) + */ + #if defined(bsdi) + typedef u_int32_t uint32_t; + + #if !defined(__cplusplus) + typedef int bool; + #endif + #else + /* + * FreeBSD and OpenBSD define uint32_t and bool. + */ + #include + #include + #endif +#elif defined(BEOS) + #include +#else + /* + * For those that ship a standard C99 stdint.h header file, include + * it. Can't do the same for stdbool.h tho, since some systems ship + * with a stdbool.h file that doesn't compile! + */ + #include + + #ifndef __cplusplus + #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95) + #include + #else + /* + * GCC 2.91 can't deal with a typedef for bool, but a #define + * works. + */ + #define bool int + #endif + #endif +#endif diff --git a/engine/libs/npapi/npupp.h b/engine/libs/npapi/npupp.h new file mode 100644 index 000000000..b943f503d --- /dev/null +++ b/engine/libs/npapi/npupp.h @@ -0,0 +1,721 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +/* + * npupp.h $Revision: 3.26 $ + * function call mecahnics needed by platform specific glue code. + */ + + +#ifndef _NPUPP_H_ +#define _NPUPP_H_ + +#if defined(__OS2__) +#pragma pack(1) +#endif + +#ifndef GENERATINGCFM +#define GENERATINGCFM 0 +#endif + +#ifndef _NPAPI_H_ +#include "npapi.h" +#endif + +#include "npruntime.h" + +#ifdef DOJRI +#include "jri.h" +#else +typedef struct JRIGlobal* JRIGlobalRef; +typedef void *JRIEnv; +typedef void *jref; +#endif + + +/****************************************************************************************** + plug-in function table macros + for each function in and out of the plugin API we define + typedef NPP_FooUPP + #define NewNPP_FooProc + #define CallNPP_FooProc + *******************************************************************************************/ + + +/* NPP_Initialize */ +typedef void (* NP_LOADDS NPP_InitializeUPP)(void); +#define NewNPP_InitializeProc(FUNC) \ + ((NPP_InitializeUPP) (FUNC)) +#define CallNPP_InitializeProc(FUNC) \ + (*(FUNC))() + +/* NPP_Shutdown */ +typedef void (* NP_LOADDS NPP_ShutdownUPP)(void); +#define NewNPP_ShutdownProc(FUNC) \ + ((NPP_ShutdownUPP) (FUNC)) +#define CallNPP_ShutdownProc(FUNC) \ + (*(FUNC))() + +/* NPP_New */ +typedef NPError (* NP_LOADDS NPP_NewUPP)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); +#define NewNPP_NewProc(FUNC) \ + ((NPP_NewUPP) (FUNC)) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) + +/* NPP_Destroy */ +typedef NPError (* NP_LOADDS NPP_DestroyUPP)(NPP instance, NPSavedData** save); +#define NewNPP_DestroyProc(FUNC) \ + ((NPP_DestroyUPP) (FUNC)) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPP_SetWindow */ +typedef NPError (* NP_LOADDS NPP_SetWindowUPP)(NPP instance, NPWindow* window); +#define NewNPP_SetWindowProc(FUNC) \ + ((NPP_SetWindowUPP) (FUNC)) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPP_NewStream */ +typedef NPError (* NP_LOADDS NPP_NewStreamUPP)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); +#define NewNPP_NewStreamProc(FUNC) \ + ((NPP_NewStreamUPP) (FUNC)) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) + +/* NPP_DestroyStream */ +typedef NPError (* NP_LOADDS NPP_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPP_DestroyStreamProc(FUNC) \ + ((NPP_DestroyStreamUPP) (FUNC)) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (*(FUNC))((NPParg), (NPStreamPtr), (NPReasonArg)) + +/* NPP_WriteReady */ +typedef int32 (* NP_LOADDS NPP_WriteReadyUPP)(NPP instance, NPStream* stream); +#define NewNPP_WriteReadyProc(FUNC) \ + ((NPP_WriteReadyUPP) (FUNC)) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr)) + +/* NPP_Write */ +typedef int32 (* NP_LOADDS NPP_WriteUPP)(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); +#define NewNPP_WriteProc(FUNC) \ + ((NPP_WriteUPP) (FUNC)) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +/* NPP_StreamAsFile */ +typedef void (* NP_LOADDS NPP_StreamAsFileUPP)(NPP instance, NPStream* stream, const char* fname); +#define NewNPP_StreamAsFileProc(FUNC) \ + ((NPP_StreamAsFileUPP) (FUNC)) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPP_Print */ +typedef void (* NP_LOADDS NPP_PrintUPP)(NPP instance, NPPrint* platformPrint); +#define NewNPP_PrintProc(FUNC) \ + ((NPP_PrintUPP) (FUNC)) +#define CallNPP_PrintProc(FUNC, NPParg, NPPrintArg) \ + (*(FUNC))((NPParg), (NPPrintArg)) + +/* NPP_HandleEvent */ +typedef int16 (* NP_LOADDS NPP_HandleEventUPP)(NPP instance, void* event); +#define NewNPP_HandleEventProc(FUNC) \ + ((NPP_HandleEventUPP) (FUNC)) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (*(FUNC))((NPParg), (voidPtr)) + +/* NPP_URLNotify */ +typedef void (* NP_LOADDS NPP_URLNotifyUPP)(NPP instance, const char* url, NPReason reason, void* notifyData); +#define NewNPP_URLNotifyProc(FUNC) \ + ((NPP_URLNotifyUPP) (FUNC)) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +/* NPP_GetValue */ +typedef NPError (* NP_LOADDS NPP_GetValueUPP)(NPP instance, NPPVariable variable, void *ret_alue); +#define NewNPP_GetValueProc(FUNC) \ + ((NPP_GetValueUPP) (FUNC)) +#define CallNPP_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPP_SetValue */ +typedef NPError (* NP_LOADDS NPP_SetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPP_SetValueProc(FUNC) \ + ((NPP_SetValueUPP) (FUNC)) +#define CallNPP_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* + * Netscape entry points + */ + + +/* NPN_GetValue */ +typedef NPError (* NP_LOADDS NPN_GetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPN_GetValueProc(FUNC) \ + ((NPN_GetValueUPP) (FUNC)) +#define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_SetValue */ +typedef NPError (* NP_LOADDS NPN_SetValueUPP)(NPP instance, NPPVariable variable, void *ret_alue); +#define NewNPN_SetValueProc(FUNC) \ + ((NPN_SetValueUPP) (FUNC)) +#define CallNPN_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_GetUrlNotify */ +typedef NPError (* NP_LOADDS NPN_GetURLNotifyUPP)(NPP instance, const char* url, const char* window, void* notifyData); +#define NewNPN_GetURLNotifyProc(FUNC) \ + ((NPN_GetURLNotifyUPP) (FUNC)) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +/* NPN_PostUrlNotify */ +typedef NPError (* NP_LOADDS NPN_PostURLNotifyUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData); +#define NewNPN_PostURLNotifyProc(FUNC) \ + ((NPN_PostURLNotifyUPP) (FUNC)) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) + +/* NPN_GetUrl */ +typedef NPError (* NP_LOADDS NPN_GetURLUPP)(NPP instance, const char* url, const char* window); +#define NewNPN_GetURLProc(FUNC) \ + ((NPN_GetURLUPP) (FUNC)) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_PostUrl */ +typedef NPError (* NP_LOADDS NPN_PostURLUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file); +#define NewNPN_PostURLProc(FUNC) \ + ((NPN_PostURLUPP) (FUNC)) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) + +/* NPN_RequestRead */ +typedef NPError (* NP_LOADDS NPN_RequestReadUPP)(NPStream* stream, NPByteRange* rangeList); +#define NewNPN_RequestReadProc(FUNC) \ + ((NPN_RequestReadUPP) (FUNC)) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (*(FUNC))((stream), (range)) + +/* NPN_NewStream */ +typedef NPError (* NP_LOADDS NPN_NewStreamUPP)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); +#define NewNPN_NewStreamProc(FUNC) \ + ((NPN_NewStreamUPP) (FUNC)) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (*(FUNC))((npp), (type), (window), (stream)) + +/* NPN_Write */ +typedef int32 (* NP_LOADDS NPN_WriteUPP)(NPP instance, NPStream* stream, int32 len, void* buffer); +#define NewNPN_WriteProc(FUNC) \ + ((NPN_WriteUPP) (FUNC)) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (*(FUNC))((npp), (stream), (len), (buffer)) + +/* NPN_DestroyStream */ +typedef NPError (* NP_LOADDS NPN_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPN_DestroyStreamProc(FUNC) \ + ((NPN_DestroyStreamUPP) (FUNC)) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (*(FUNC))((npp), (stream), (reason)) + +/* NPN_Status */ +typedef void (* NP_LOADDS NPN_StatusUPP)(NPP instance, const char* message); +#define NewNPN_StatusProc(FUNC) \ + ((NPN_StatusUPP) (FUNC)) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (*(FUNC))((npp), (msg)) + +/* NPN_UserAgent */ +typedef const char* (* NP_LOADDS NPN_UserAgentUPP)(NPP instance); +#define NewNPN_UserAgentProc(FUNC) \ + ((NPN_UserAgentUPP) (FUNC)) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_MemAlloc */ +typedef void* (* NP_LOADDS NPN_MemAllocUPP)(uint32 size); +#define NewNPN_MemAllocProc(FUNC) \ + ((NPN_MemAllocUPP) (FUNC)) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN__MemFree */ +typedef void (* NP_LOADDS NPN_MemFreeUPP)(void* ptr); +#define NewNPN_MemFreeProc(FUNC) \ + ((NPN_MemFreeUPP) (FUNC)) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_MemFlush */ +typedef uint32 (* NP_LOADDS NPN_MemFlushUPP)(uint32 size); +#define NewNPN_MemFlushProc(FUNC) \ + ((NPN_MemFlushUPP) (FUNC)) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_ReloadPlugins */ +typedef void (* NP_LOADDS NPN_ReloadPluginsUPP)(NPBool reloadPages); +#define NewNPN_ReloadPluginsProc(FUNC) \ + ((NPN_ReloadPluginsUPP) (FUNC)) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_GetJavaEnv */ +typedef JRIEnv* (* NP_LOADDS NPN_GetJavaEnvUPP)(void); +#define NewNPN_GetJavaEnvProc(FUNC) \ + ((NPN_GetJavaEnvUPP) (FUNC)) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (*(FUNC))() + +/* NPN_GetJavaPeer */ +typedef jref (* NP_LOADDS NPN_GetJavaPeerUPP)(NPP instance); +#define NewNPN_GetJavaPeerProc(FUNC) \ + ((NPN_GetJavaPeerUPP) (FUNC)) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_InvalidateRect */ +typedef void (* NP_LOADDS NPN_InvalidateRectUPP)(NPP instance, NPRect *rect); +#define NewNPN_InvalidateRectProc(FUNC) \ + ((NPN_InvalidateRectUPP) (FUNC)) +#define CallNPN_InvalidateRectProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPN_InvalidateRegion */ +typedef void (* NP_LOADDS NPN_InvalidateRegionUPP)(NPP instance, NPRegion region); +#define NewNPN_InvalidateRegionProc(FUNC) \ + ((NPN_InvalidateRegionUPP) (FUNC)) +#define CallNPN_InvalidateRegionProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPN_ForceRedraw */ +typedef void (* NP_LOADDS NPN_ForceRedrawUPP)(NPP instance); +#define NewNPN_ForceRedrawProc(FUNC) \ + ((NPN_ForceRedrawUPP) (FUNC)) +#define CallNPN_ForceRedrawProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_GetStringIdentifier */ +typedef NPIdentifier (* NP_LOADDS NPN_GetStringIdentifierUPP)(const NPUTF8* name); +#define NewNPN_GetStringIdentifierProc(FUNC) \ + ((NPN_GetStringIdentifierUPP) (FUNC)) +#define CallNPN_GetStringIdentifierProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_GetStringIdentifiers */ +typedef void (* NP_LOADDS NPN_GetStringIdentifiersUPP)(const NPUTF8** names, + int32_t nameCount, + NPIdentifier* identifiers); +#define NewNPN_GetStringIdentifiersProc(FUNC) \ + ((NPN_GetStringIdentifiersUPP) (FUNC)) +#define CallNPN_GetStringIdentifiersProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_GetIntIdentifier */ +typedef NPIdentifier (* NP_LOADDS NPN_GetIntIdentifierUPP)(int32_t intid); +#define NewNPN_GetIntIdentifierProc(FUNC) \ + ((NPN_GetIntIdentifierUPP) (FUNC)) +#define CallNPN_GetIntIdentifierProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_IdentifierIsString */ +typedef bool (* NP_LOADDS NPN_IdentifierIsStringUPP)(NPIdentifier identifier); +#define NewNPN_IdentifierIsStringProc(FUNC) \ + ((NPN_IdentifierIsStringUPP) (FUNC)) +#define CallNPN_IdentifierIsStringProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_UTF8FromIdentifier */ +typedef NPUTF8* (* NP_LOADDS NPN_UTF8FromIdentifierUPP)(NPIdentifier identifier); +#define NewNPN_UTF8FromIdentifierProc(FUNC) \ + ((NPN_UTF8FromIdentifierUPP) (FUNC)) +#define CallNPN_UTF8FromIdentifierProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_IntFromIdentifier */ +typedef int32_t (* NP_LOADDS NPN_IntFromIdentifierUPP)(NPIdentifier identifier); +#define NewNPN_IntFromIdentifierProc(FUNC) \ + ((NPN_IntFromIdentifierUPP) (FUNC)) +#define CallNPN_IntFromIdentifierProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_CreateObject */ +typedef NPObject* (* NP_LOADDS NPN_CreateObjectUPP)(NPP npp, NPClass *aClass); +#define NewNPN_CreateObjectProc(FUNC) \ + ((NPN_CreateObjectUPP) (FUNC)) +#define CallNPN_CreateObjectProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPN_RetainObject */ +typedef NPObject* (* NP_LOADDS NPN_RetainObjectUPP)(NPObject *obj); +#define NewNPN_RetainObjectProc(FUNC) \ + ((NPN_RetainObjectUPP) (FUNC)) +#define CallNPN_RetainObjectProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_ReleaseObject */ +typedef void (* NP_LOADDS NPN_ReleaseObjectUPP)(NPObject *obj); +#define NewNPN_ReleaseObjectProc(FUNC) \ + ((NPN_ReleaseObjectUPP) (FUNC)) +#define CallNPN_ReleaseObjectProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_Invoke */ +typedef bool (* NP_LOADDS NPN_InvokeUPP)(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result); +#define NewNPN_InvokeProc(FUNC) \ + ((NPN_InvokeUPP) (FUNC)) +#define CallNPN_InvokeProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) + +/* NPN_InvokeDefault */ +typedef bool (* NP_LOADDS NPN_InvokeDefaultUPP)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result); +#define NewNPN_InvokeDefaultProc(FUNC) \ + ((NPN_InvokeDefaultUPP) (FUNC)) +#define CallNPN_InvokeDefaultProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) + +/* NPN_Evaluate */ +typedef bool (* NP_LOADDS NPN_EvaluateUPP)(NPP npp, NPObject *obj, NPString *script, NPVariant *result); +#define NewNPN_EvaluateProc(FUNC) \ + ((NPN_EvaluateUPP) (FUNC)) +#define CallNPN_EvaluateProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +/* NPN_GetProperty */ +typedef bool (* NP_LOADDS NPN_GetPropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result); +#define NewNPN_GetPropertyProc(FUNC) \ + ((NPN_GetPropertyUPP) (FUNC)) +#define CallNPN_GetPropertyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +/* NPN_SetProperty */ +typedef bool (* NP_LOADDS NPN_SetPropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value); +#define NewNPN_SetPropertyProc(FUNC) \ + ((NPN_SetPropertyUPP) (FUNC)) +#define CallNPN_SetPropertyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +/* NPN_RemoveProperty */ +typedef bool (* NP_LOADDS NPN_RemovePropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName); +#define NewNPN_RemovePropertyProc(FUNC) \ + ((NPN_RemovePropertyUPP) (FUNC)) +#define CallNPN_RemovePropertyProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_HasProperty */ +typedef bool (* NP_LOADDS NPN_HasPropertyUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName); +#define NewNPN_HasPropertyProc(FUNC) \ + ((NPN_HasPropertyUPP) (FUNC)) +#define CallNPN_HasPropertyProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_HasMethod */ +typedef bool (* NP_LOADDS NPN_HasMethodUPP)(NPP npp, NPObject *obj, NPIdentifier propertyName); +#define NewNPN_HasMethodProc(FUNC) \ + ((NPN_HasMethodUPP) (FUNC)) +#define CallNPN_HasMethodProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_ReleaseVariantValue */ +typedef void (* NP_LOADDS NPN_ReleaseVariantValueUPP)(NPVariant *variant); +#define NewNPN_ReleaseVariantValueProc(FUNC) \ + ((NPN_ReleaseVariantValueUPP) (FUNC)) +#define CallNPN_ReleaseVariantValueProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_SetException */ +typedef void (* NP_LOADDS NPN_SetExceptionUPP)(NPObject *obj, const NPUTF8 *message); +#define NewNPN_SetExceptionProc(FUNC) \ + ((NPN_SetExceptionUPP) (FUNC)) +#define CallNPN_SetExceptionProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPN_PushPopupsEnabledStateUPP */ +typedef bool (* NP_LOADDS NPN_PushPopupsEnabledStateUPP)(NPP npp, NPBool enabled); +#define NewNPN_PushPopupsEnabledStateProc(FUNC) \ + ((NPN_PushPopupsEnabledStateUPP) (FUNC)) +#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +/* NPN_PopPopupsEnabledState */ +typedef bool (* NP_LOADDS NPN_PopPopupsEnabledStateUPP)(NPP npp); +#define NewNPN_PopPopupsEnabledStateProc(FUNC) \ + ((NPN_PopPopupsEnabledStateUPP) (FUNC)) +#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +/* NPN_Enumerate */ +typedef bool (* NP_LOADDS NPN_EnumerateUPP)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32_t *count); +#define NewNPN_EnumerateProc(FUNC) \ + ((NPN_EnumerateUPP) (FUNC)) +#define CallNPN_EnumerateProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +/* NPN_PluginThreadAsyncCall */ +typedef void (* NP_LOADDS NPN_PluginThreadAsyncCallUPP)(NPP instance, void (*func)(void *), void *userData); +#define NewNPN_PluginThreadAsyncCallProc(FUNC) \ + ((NPN_PluginThreadAsyncCallUPP) (FUNC)) +#define CallNPN_PluginThreadAsyncCallProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) + +/* NPN_Construct */ +typedef bool (* NP_LOADDS NPN_ConstructUPP)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result); +#define NewNPN_ConstructProc(FUNC) \ + ((NPN_ConstructUPP) (FUNC)) +#define CallNPN_ConstructProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) + + + +/****************************************************************************************** + * The actual plugin function table definitions + *******************************************************************************************/ + +typedef struct _NPPluginFuncs { + uint16 size; + uint16 version; + NPP_NewUPP newp; + NPP_DestroyUPP destroy; + NPP_SetWindowUPP setwindow; + NPP_NewStreamUPP newstream; + NPP_DestroyStreamUPP destroystream; + NPP_StreamAsFileUPP asfile; + NPP_WriteReadyUPP writeready; + NPP_WriteUPP write; + NPP_PrintUPP print; + NPP_HandleEventUPP event; + NPP_URLNotifyUPP urlnotify; + JRIGlobalRef javaClass; + NPP_GetValueUPP getvalue; + NPP_SetValueUPP setvalue; +} NPPluginFuncs; + +typedef struct _NPNetscapeFuncs { + uint16 size; + uint16 version; + NPN_GetURLUPP geturl; + NPN_PostURLUPP posturl; + NPN_RequestReadUPP requestread; + NPN_NewStreamUPP newstream; + NPN_WriteUPP write; + NPN_DestroyStreamUPP destroystream; + NPN_StatusUPP status; + NPN_UserAgentUPP uagent; + NPN_MemAllocUPP memalloc; + NPN_MemFreeUPP memfree; + NPN_MemFlushUPP memflush; + NPN_ReloadPluginsUPP reloadplugins; + NPN_GetJavaEnvUPP getJavaEnv; + NPN_GetJavaPeerUPP getJavaPeer; + NPN_GetURLNotifyUPP geturlnotify; + NPN_PostURLNotifyUPP posturlnotify; + NPN_GetValueUPP getvalue; + NPN_SetValueUPP setvalue; + NPN_InvalidateRectUPP invalidaterect; + NPN_InvalidateRegionUPP invalidateregion; + NPN_ForceRedrawUPP forceredraw; + NPN_GetStringIdentifierUPP getstringidentifier; + NPN_GetStringIdentifiersUPP getstringidentifiers; + NPN_GetIntIdentifierUPP getintidentifier; + NPN_IdentifierIsStringUPP identifierisstring; + NPN_UTF8FromIdentifierUPP utf8fromidentifier; + NPN_IntFromIdentifierUPP intfromidentifier; + NPN_CreateObjectUPP createobject; + NPN_RetainObjectUPP retainobject; + NPN_ReleaseObjectUPP releaseobject; + NPN_InvokeUPP invoke; + NPN_InvokeDefaultUPP invokeDefault; + NPN_EvaluateUPP evaluate; + NPN_GetPropertyUPP getproperty; + NPN_SetPropertyUPP setproperty; + NPN_RemovePropertyUPP removeproperty; + NPN_HasPropertyUPP hasproperty; + NPN_HasMethodUPP hasmethod; + NPN_ReleaseVariantValueUPP releasevariantvalue; + NPN_SetExceptionUPP setexception; + NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate; + NPN_PopPopupsEnabledStateUPP poppopupsenabledstate; + NPN_EnumerateUPP enumerate; + NPN_PluginThreadAsyncCallUPP pluginthreadasynccall; + NPN_ConstructUPP construct; +} NPNetscapeFuncs; + + +#ifdef XP_MACOSX +/****************************************************************************************** + * Mac platform-specific plugin glue stuff + *******************************************************************************************/ + +/* + * Main entry point of the plugin. + * This routine will be called when the plugin is loaded. The function + * tables are passed in and the plugin fills in the NPPluginFuncs table + * and NPPShutdownUPP for Netscape's use. + */ +typedef NPError (* NP_LOADDS NPP_MainEntryUPP)(NPNetscapeFuncs*, NPPluginFuncs*, NPP_ShutdownUPP*); +#define NewNPP_MainEntryProc(FUNC) \ + ((NPP_MainEntryUPP) (FUNC)) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + (*(FUNC))((netscapeFunc), (pluginFunc), (shutdownUPP)) + +/* + * Mac OS X version(s) of NP_GetMIMEDescription(const char *) + * These can be called to retreive MIME information from the plugin dynamically + * + * Note: For compatibility with Quicktime, BPSupportedMIMEtypes is another way + * to get mime info from the plugin only on OSX and may not be supported + * in furture version -- use NP_GetMIMEDescription instead + */ + +enum +{ + kBPSupportedMIMETypesStructVers_1 = 1 +}; + +typedef struct _BPSupportedMIMETypes +{ + SInt32 structVersion; /* struct version */ + Handle typeStrings; /* STR# formated handle, allocated by plug-in */ + Handle infoStrings; /* STR# formated handle, allocated by plug-in */ +} BPSupportedMIMETypes; +OSErr BP_GetSupportedMIMETypes(BPSupportedMIMETypes *mimeInfo, UInt32 flags); + + /* NP_GetMIMEDescription */ +#define NP_GETMIMEDESCRIPTION_NAME "NP_GetMIMEDescription" +typedef const char* (* NP_LOADDS NP_GetMIMEDescriptionUPP)(); +#define NewNP_GetMIMEDescEntryProc(FUNC) \ + ((NP_GetMIMEDescriptionUPP) (FUNC)) +#define CallNP_GetMIMEDescEntryProc(FUNC) \ + (*(FUNC))() + +/* BP_GetSupportedMIMETypes */ +typedef OSErr (* NP_LOADDS BP_GetSupportedMIMETypesUPP)(BPSupportedMIMETypes*, UInt32); +#define NewBP_GetSupportedMIMETypesEntryProc(FUNC) \ + ((BP_GetSupportedMIMETypesUPP) (FUNC)) +#define CallBP_GetMIMEDescEntryProc(FUNC, mimeInfo, flags) \ + (*(FUNC))((mimeInfo), (flags)) + +#endif /* XP_MACOSX */ + +#if defined(_WINDOWS) +#define OSCALL WINAPI +#else +#if defined(__OS2__) +#define OSCALL _System +#else +#define OSCALL +#endif +#endif + +#if defined(XP_UNIX) +/* GCC 3.3 and later support the visibility attribute. */ +#if defined(__GNUC__) && \ + ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) +#define NP_VISIBILITY_DEFAULT __attribute__((visibility("default"))) +#else +#define NP_VISIBILITY_DEFAULT +#endif + +#define NP_EXPORT(__type) NP_VISIBILITY_DEFAULT __type +#endif + +#if defined( _WINDOWS ) || defined (__OS2__) + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ +#if defined(__OS2__) + +typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */ + char *pMimeTypes; + char *pFileExtents; + char *pFileOpenTemplate; + char *pProductName; + char *pProductDescription; + unsigned long dwProductVersionMS; + unsigned long dwProductVersionLS; +} NPPluginData; + +NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData); + +#endif + +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs); + +NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs); + +NPError OSCALL NP_Shutdown(); + +char* NP_GetMIMEDescription(); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINDOWS || __OS2__ */ + +#if defined(__OS2__) +#pragma pack() +#endif + +#ifdef XP_UNIX + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ + +NP_EXPORT(char*) NP_GetMIMEDescription(void); +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs*, NPPluginFuncs*); +NP_EXPORT(NPError) NP_Shutdown(void); +NP_EXPORT(NPError) NP_GetValue(void *future, NPPVariable aVariable, void *aValue); + +#ifdef __cplusplus +} +#endif + +#endif /* XP_UNIX */ + +#endif /* _NPUPP_H_ */ diff --git a/engine/libs/npapi/obsolete/protypes.h b/engine/libs/npapi/obsolete/protypes.h new file mode 100644 index 000000000..4405bfce2 --- /dev/null +++ b/engine/libs/npapi/obsolete/protypes.h @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * This header typedefs the old 'native' types to the new PRs. + * These definitions are scheduled to be eliminated at the earliest + * possible time. The NSPR API is implemented and documented using + * the new definitions. + */ + +#if !defined(PROTYPES_H) +#define PROTYPES_H + +typedef PRUintn uintn; +#ifndef _XP_Core_ +typedef PRIntn intn; +#endif + +/* + * It is trickier to define uint, int8, uint8, int16, uint16, + * int32, uint32, int64, and uint64 because some of these int + * types are defined by standard header files on some platforms. + * Our strategy here is to include all such standard headers + * first, and then define these int types only if they are not + * defined by those standard headers. + */ + +/* + * BeOS defines all the int types below in its standard header + * file SupportDefs.h. + */ +#ifdef XP_BEOS +#include +#endif + +/* + * OpenVMS defines all the int types below in its standard + * header files ints.h and types.h. + */ +#ifdef VMS +#include +#include +#endif + +/* + * SVR4 typedef of uint is commonly found on UNIX machines. + * + * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h) + * defines the types int8, int16, int32, and int64. + */ +#ifdef XP_UNIX +#include +#endif + +/* model.h on HP-UX defines int8, int16, and int32. */ +#ifdef HPUX +#include +#endif + +/* + * uint + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(XP_UNIX) || defined(NTO) +typedef PRUintn uint; +#endif + +/* + * uint64 + */ + +#if !defined(XP_BEOS) && !defined(VMS) +typedef PRUint64 uint64; +#endif + +/* + * uint32 + */ + +#if !defined(XP_BEOS) && !defined(VMS) +#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO) +typedef PRUint32 uint32; +#else +typedef unsigned long uint32; +#endif +#endif + +/* + * uint16 + */ + +#if !defined(XP_BEOS) && !defined(VMS) +typedef PRUint16 uint16; +#endif + +/* + * uint8 + */ + +#if !defined(XP_BEOS) && !defined(VMS) +typedef PRUint8 uint8; +#endif + +/* + * int64 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) +typedef PRInt64 int64; +#endif + +/* + * int32 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ + && !defined(HPUX) +#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO) +typedef PRInt32 int32; +#else +typedef long int32; +#endif +#endif + +/* + * int16 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ + && !defined(HPUX) +typedef PRInt16 int16; +#endif + +/* + * int8 + */ + +#if !defined(XP_BEOS) && !defined(VMS) \ + && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ + && !defined(HPUX) +typedef PRInt8 int8; +#endif + +typedef PRFloat64 float64; +typedef PRUptrdiff uptrdiff_t; +typedef PRUword uprword_t; +typedef PRWord prword_t; + + +/* Re: prbit.h */ +#define TEST_BIT PR_TEST_BIT +#define SET_BIT PR_SET_BIT +#define CLEAR_BIT PR_CLEAR_BIT + +/* Re: prarena.h->plarena.h */ +#define PRArena PLArena +#define PRArenaPool PLArenaPool +#define PRArenaStats PLArenaStats +#define PR_ARENA_ALIGN PL_ARENA_ALIGN +#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL +#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE +#define PR_ARENA_GROW PL_ARENA_GROW +#define PR_ARENA_MARK PL_ARENA_MARK +#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED +#define PR_CLEAR_ARENA PL_CLEAR_ARENA +#define PR_ARENA_RELEASE PL_ARENA_RELEASE +#define PR_COUNT_ARENA PL_COUNT_ARENA +#define PR_ARENA_DESTROY PL_ARENA_DESTROY +#define PR_InitArenaPool PL_InitArenaPool +#define PR_FreeArenaPool PL_FreeArenaPool +#define PR_FinishArenaPool PL_FinishArenaPool +#define PR_CompactArenaPool PL_CompactArenaPool +#define PR_ArenaFinish PL_ArenaFinish +#define PR_ArenaAllocate PL_ArenaAllocate +#define PR_ArenaGrow PL_ArenaGrow +#define PR_ArenaRelease PL_ArenaRelease +#define PR_ArenaCountAllocation PL_ArenaCountAllocation +#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth +#define PR_ArenaCountGrowth PL_ArenaCountGrowth +#define PR_ArenaCountRelease PL_ArenaCountRelease +#define PR_ArenaCountRetract PL_ArenaCountRetract + +/* Re: prhash.h->plhash.h */ +#define PRHashEntry PLHashEntry +#define PRHashTable PLHashTable +#define PRHashNumber PLHashNumber +#define PRHashFunction PLHashFunction +#define PRHashComparator PLHashComparator +#define PRHashEnumerator PLHashEnumerator +#define PRHashAllocOps PLHashAllocOps +#define PR_NewHashTable PL_NewHashTable +#define PR_HashTableDestroy PL_HashTableDestroy +#define PR_HashTableRawLookup PL_HashTableRawLookup +#define PR_HashTableRawAdd PL_HashTableRawAdd +#define PR_HashTableRawRemove PL_HashTableRawRemove +#define PR_HashTableAdd PL_HashTableAdd +#define PR_HashTableRemove PL_HashTableRemove +#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries +#define PR_HashTableLookup PL_HashTableLookup +#define PR_HashTableDump PL_HashTableDump +#define PR_HashString PL_HashString +#define PR_CompareStrings PL_CompareStrings +#define PR_CompareValues PL_CompareValues + +#if defined(XP_MAC) +#ifndef TRUE /* Mac standard is lower case true */ + #define TRUE 1 +#endif +#ifndef FALSE /* Mac standard is lower case false */ + #define FALSE 0 +#endif +#endif + +#endif /* !defined(PROTYPES_H) */ diff --git a/engine/libs/npapi/prcpucfg.h b/engine/libs/npapi/prcpucfg.h new file mode 100644 index 000000000..026258b8c --- /dev/null +++ b/engine/libs/npapi/prcpucfg.h @@ -0,0 +1,300 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nspr_cpucfg___ +#define nspr_cpucfg___ + +#ifndef XP_PC +#define XP_PC +#endif + +#ifndef WIN32 +#define WIN32 +#endif + +#ifndef WIN95 +#define WIN95 +#endif + +#define PR_AF_INET6 23 /* same as AF_INET6 */ + +#if defined(_M_IX86) || defined(_X86_) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_WORD 4 +#define PR_BYTES_PER_DWORD 8 +#define PR_BYTES_PER_DOUBLE 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_WORD 32 +#define PR_BITS_PER_DWORD 64 +#define PR_BITS_PER_DOUBLE 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_WORD_LOG2 5 +#define PR_BITS_PER_DWORD_LOG2 6 +#define PR_BITS_PER_DOUBLE_LOG2 6 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_WORD 4 +#define PR_ALIGN_OF_DWORD 8 +#define PR_ALIGN_OF_DOUBLE 4 +#define PR_ALIGN_OF_POINTER 4 + +#define PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 2 + +#elif defined(_ALPHA_) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_DOUBLE 8 +#define PR_BYTES_PER_WORD 4 +#define PR_BYTES_PER_DWORD 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_DOUBLE 64 +#define PR_BITS_PER_WORD 32 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_DOUBLE_LOG2 6 +#define PR_BITS_PER_WORD_LOG2 5 + +#define PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_DOUBLE 8 +#define PR_ALIGN_OF_POINTER 4 + +#elif defined(_AMD64_) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN +#define IS_64 + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_WORD 8 +#define PR_BYTES_PER_DWORD 8 +#define PR_BYTES_PER_DOUBLE 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_WORD 64 +#define PR_BITS_PER_DWORD 64 +#define PR_BITS_PER_DOUBLE 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_WORD_LOG2 6 +#define PR_BITS_PER_DWORD_LOG2 6 +#define PR_BITS_PER_DOUBLE_LOG2 6 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_WORD 8 +#define PR_ALIGN_OF_DWORD 8 +#define PR_ALIGN_OF_DOUBLE 8 +#define PR_ALIGN_OF_POINTER 8 + +#define PR_BYTES_PER_WORD_LOG2 3 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#elif defined(_IA64_) + +#define IS_LITTLE_ENDIAN 1 +#undef IS_BIG_ENDIAN +#define IS_64 + +#define PR_BYTES_PER_BYTE 1 +#define PR_BYTES_PER_SHORT 2 +#define PR_BYTES_PER_INT 4 +#define PR_BYTES_PER_INT64 8 +#define PR_BYTES_PER_LONG 4 +#define PR_BYTES_PER_FLOAT 4 +#define PR_BYTES_PER_WORD 8 +#define PR_BYTES_PER_DWORD 8 +#define PR_BYTES_PER_DOUBLE 8 + +#define PR_BITS_PER_BYTE 8 +#define PR_BITS_PER_SHORT 16 +#define PR_BITS_PER_INT 32 +#define PR_BITS_PER_INT64 64 +#define PR_BITS_PER_LONG 32 +#define PR_BITS_PER_FLOAT 32 +#define PR_BITS_PER_WORD 64 +#define PR_BITS_PER_DWORD 64 +#define PR_BITS_PER_DOUBLE 64 + +#define PR_BITS_PER_BYTE_LOG2 3 +#define PR_BITS_PER_SHORT_LOG2 4 +#define PR_BITS_PER_INT_LOG2 5 +#define PR_BITS_PER_INT64_LOG2 6 +#define PR_BITS_PER_LONG_LOG2 5 +#define PR_BITS_PER_FLOAT_LOG2 5 +#define PR_BITS_PER_WORD_LOG2 6 +#define PR_BITS_PER_DWORD_LOG2 6 +#define PR_BITS_PER_DOUBLE_LOG2 6 + +#define PR_ALIGN_OF_SHORT 2 +#define PR_ALIGN_OF_INT 4 +#define PR_ALIGN_OF_LONG 4 +#define PR_ALIGN_OF_INT64 8 +#define PR_ALIGN_OF_FLOAT 4 +#define PR_ALIGN_OF_WORD 8 +#define PR_ALIGN_OF_DWORD 8 +#define PR_ALIGN_OF_DOUBLE 8 +#define PR_ALIGN_OF_POINTER 8 + +#define PR_BYTES_PER_WORD_LOG2 3 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#else /* defined(_M_IX86) || defined(_X86_) */ + +#error unknown processor architecture + +#endif /* defined(_M_IX86) || defined(_X86_) */ + +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG +#endif + +#ifndef NO_NSPR_10_SUPPORT + +#define BYTES_PER_BYTE PR_BYTES_PER_BYTE +#define BYTES_PER_SHORT PR_BYTES_PER_SHORT +#define BYTES_PER_INT PR_BYTES_PER_INT +#define BYTES_PER_INT64 PR_BYTES_PER_INT64 +#define BYTES_PER_LONG PR_BYTES_PER_LONG +#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT +#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE +#define BYTES_PER_WORD PR_BYTES_PER_WORD +#define BYTES_PER_DWORD PR_BYTES_PER_DWORD + +#define BITS_PER_BYTE PR_BITS_PER_BYTE +#define BITS_PER_SHORT PR_BITS_PER_SHORT +#define BITS_PER_INT PR_BITS_PER_INT +#define BITS_PER_INT64 PR_BITS_PER_INT64 +#define BITS_PER_LONG PR_BITS_PER_LONG +#define BITS_PER_FLOAT PR_BITS_PER_FLOAT +#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE +#define BITS_PER_WORD PR_BITS_PER_WORD + +#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 +#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 +#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 +#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 +#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 +#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 +#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 +#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 + +#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT +#define ALIGN_OF_INT PR_ALIGN_OF_INT +#define ALIGN_OF_LONG PR_ALIGN_OF_LONG +#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 +#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT +#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE +#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER +#define ALIGN_OF_WORD PR_ALIGN_OF_WORD + +#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 +#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 +#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 + +#endif /* NO_NSPR_10_SUPPORT */ + +#endif /* nspr_cpucfg___ */ diff --git a/engine/libs/npapi/prtypes.h b/engine/libs/npapi/prtypes.h new file mode 100644 index 000000000..668148417 --- /dev/null +++ b/engine/libs/npapi/prtypes.h @@ -0,0 +1,575 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* +** File: prtypes.h +** Description: Definitions of NSPR's basic types +** +** Prototypes and macros used to make up for deficiencies that we have found +** in ANSI environments. +** +** Since we do not wrap and all the other standard headers, authors +** of portable code will not know in general that they need these definitions. +** Instead of requiring these authors to find the dependent uses in their code +** and take the following steps only in those C files, we take steps once here +** for all C files. +**/ + +#ifndef prtypes_h___ +#define prtypes_h___ + +#ifdef MDCPUCFG +#include MDCPUCFG +#else +#include "prcpucfg.h" +#endif + +#include + +/*********************************************************************** +** MACROS: PR_EXTERN +** PR_IMPLEMENT +** DESCRIPTION: +** These are only for externally visible routines and globals. For +** internal routines, just use "extern" for type checking and that +** will not export internal cross-file or forward-declared symbols. +** Define a macro for declaring procedures return types. We use this to +** deal with windoze specific type hackery for DLL definitions. Use +** PR_EXTERN when the prototype for the method is declared. Use +** PR_IMPLEMENT for the implementation of the method. +** +** Example: +** in dowhim.h +** PR_EXTERN( void ) DoWhatIMean( void ); +** in dowhim.c +** PR_IMPLEMENT( void ) DoWhatIMean( void ) { return; } +** +** +***********************************************************************/ +#if defined(WIN32) + +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPORT(__type) __declspec(dllimport) __type +#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type + +#define PR_EXTERN(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT(__type) __declspec(dllexport) __type +#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#elif defined(XP_BEOS) + +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPORT(__type) extern __declspec(dllexport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type + +#define PR_EXTERN(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT(__type) __declspec(dllexport) __type +#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#elif defined(WIN16) + +#define PR_CALLBACK_DECL __cdecl + +#if defined(_WINDLL) +#define PR_EXPORT(__type) extern __type _cdecl _export _loadds +#define PR_IMPORT(__type) extern __type _cdecl _export _loadds +#define PR_EXPORT_DATA(__type) extern __type _export +#define PR_IMPORT_DATA(__type) extern __type _export + +#define PR_EXTERN(__type) extern __type _cdecl _export _loadds +#define PR_IMPLEMENT(__type) __type _cdecl _export _loadds +#define PR_EXTERN_DATA(__type) extern __type _export +#define PR_IMPLEMENT_DATA(__type) __type _export + +#define PR_CALLBACK __cdecl __loadds +#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK + +#else /* this must be .EXE */ +#define PR_EXPORT(__type) extern __type _cdecl _export +#define PR_IMPORT(__type) extern __type _cdecl _export +#define PR_EXPORT_DATA(__type) extern __type _export +#define PR_IMPORT_DATA(__type) extern __type _export + +#define PR_EXTERN(__type) extern __type _cdecl _export +#define PR_IMPLEMENT(__type) __type _cdecl _export +#define PR_EXTERN_DATA(__type) extern __type _export +#define PR_IMPLEMENT_DATA(__type) __type _export + +#define PR_CALLBACK __cdecl __loadds +#define PR_STATIC_CALLBACK(__x) __x PR_CALLBACK +#endif /* _WINDLL */ + +#elif defined(XP_MAC) + +#define PR_EXPORT(__type) extern __declspec(export) __type +#define PR_EXPORT_DATA(__type) extern __declspec(export) __type +#define PR_IMPORT(__type) extern __declspec(export) __type +#define PR_IMPORT_DATA(__type) extern __declspec(export) __type + +#define PR_EXTERN(__type) extern __declspec(export) __type +#define PR_IMPLEMENT(__type) __declspec(export) __type +#define PR_EXTERN_DATA(__type) extern __declspec(export) __type +#define PR_IMPLEMENT_DATA(__type) __declspec(export) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#elif defined(XP_OS2) && defined(__declspec) + +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPORT(__type) extern __declspec(dllimport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type + +#define PR_EXTERN(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT(__type) __declspec(dllexport) __type +#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#elif defined(SYMBIAN) + +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#ifdef __WINS__ +#define PR_IMPORT(__type) extern __declspec(dllexport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type +#else +#define PR_IMPORT(__type) extern __declspec(dllimport) __type +#define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type +#endif + +#define PR_EXTERN(__type) extern __type +#define PR_IMPLEMENT(__type) __type +#define PR_EXTERN_DATA(__type) extern __type +#define PR_IMPLEMENT_DATA(__type) __type + +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#else /* Unix */ + +/* GCC 3.3 and later support the visibility attribute. */ +#if (__GNUC__ >= 4) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +#define PR_VISIBILITY_DEFAULT __attribute__((visibility("default"))) +#else +#define PR_VISIBILITY_DEFAULT +#endif + +#define PR_EXPORT(__type) extern PR_VISIBILITY_DEFAULT __type +#define PR_EXPORT_DATA(__type) extern PR_VISIBILITY_DEFAULT __type +#define PR_IMPORT(__type) extern PR_VISIBILITY_DEFAULT __type +#define PR_IMPORT_DATA(__type) extern PR_VISIBILITY_DEFAULT __type + +#define PR_EXTERN(__type) extern PR_VISIBILITY_DEFAULT __type +#define PR_IMPLEMENT(__type) PR_VISIBILITY_DEFAULT __type +#define PR_EXTERN_DATA(__type) extern PR_VISIBILITY_DEFAULT __type +#define PR_IMPLEMENT_DATA(__type) PR_VISIBILITY_DEFAULT __type +#define PR_CALLBACK +#define PR_CALLBACK_DECL +#define PR_STATIC_CALLBACK(__x) static __x + +#endif + +#if defined(_NSPR_BUILD_) +#define NSPR_API(__type) PR_EXPORT(__type) +#define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type) +#else +#define NSPR_API(__type) PR_IMPORT(__type) +#define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type) +#endif + +/*********************************************************************** +** MACROS: PR_BEGIN_MACRO +** PR_END_MACRO +** DESCRIPTION: +** Macro body brackets so that macros with compound statement definitions +** behave syntactically more like functions when called. +***********************************************************************/ +#define PR_BEGIN_MACRO do { +#define PR_END_MACRO } while (0) + +/*********************************************************************** +** MACROS: PR_BEGIN_EXTERN_C +** PR_END_EXTERN_C +** DESCRIPTION: +** Macro shorthands for conditional C++ extern block delimiters. +***********************************************************************/ +#ifdef __cplusplus +#define PR_BEGIN_EXTERN_C extern "C" { +#define PR_END_EXTERN_C } +#else +#define PR_BEGIN_EXTERN_C +#define PR_END_EXTERN_C +#endif + +/*********************************************************************** +** MACROS: PR_BIT +** PR_BITMASK +** DESCRIPTION: +** Bit masking macros. XXX n must be <= 31 to be portable +***********************************************************************/ +#define PR_BIT(n) ((PRUint32)1 << (n)) +#define PR_BITMASK(n) (PR_BIT(n) - 1) + +/*********************************************************************** +** MACROS: PR_ROUNDUP +** PR_MIN +** PR_MAX +** PR_ABS +** DESCRIPTION: +** Commonly used macros for operations on compatible types. +***********************************************************************/ +#define PR_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) +#define PR_MIN(x,y) ((x)<(y)?(x):(y)) +#define PR_MAX(x,y) ((x)>(y)?(x):(y)) +#define PR_ABS(x) ((x)<0?-(x):(x)) + +PR_BEGIN_EXTERN_C + +/************************************************************************ +** TYPES: PRUint8 +** PRInt8 +** DESCRIPTION: +** The int8 types are known to be 8 bits each. There is no type that +** is equivalent to a plain "char". +************************************************************************/ +#if PR_BYTES_PER_BYTE == 1 +typedef unsigned char PRUint8; +/* +** Some cfront-based C++ compilers do not like 'signed char' and +** issue the warning message: +** warning: "signed" not implemented (ignored) +** For these compilers, we have to define PRInt8 as plain 'char'. +** Make sure that plain 'char' is indeed signed under these compilers. +*/ +#if (defined(HPUX) && defined(__cplusplus) \ + && !defined(__GNUC__) && __cplusplus < 199707L) \ + || (defined(SCO) && defined(__cplusplus) \ + && !defined(__GNUC__) && __cplusplus == 1L) +typedef char PRInt8; +#else +typedef signed char PRInt8; +#endif +#else +#error No suitable type for PRInt8/PRUint8 +#endif + +/************************************************************************ + * MACROS: PR_INT8_MAX + * PR_INT8_MIN + * PR_UINT8_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt8 or PRUint8. +************************************************************************/ + +#define PR_INT8_MAX 127 +#define PR_INT8_MIN (-128) +#define PR_UINT8_MAX 255U + +/************************************************************************ +** TYPES: PRUint16 +** PRInt16 +** DESCRIPTION: +** The int16 types are known to be 16 bits each. +************************************************************************/ +#if PR_BYTES_PER_SHORT == 2 +typedef unsigned short PRUint16; +typedef short PRInt16; +#else +#error No suitable type for PRInt16/PRUint16 +#endif + +/************************************************************************ + * MACROS: PR_INT16_MAX + * PR_INT16_MIN + * PR_UINT16_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt16 or PRUint16. +************************************************************************/ + +#define PR_INT16_MAX 32767 +#define PR_INT16_MIN (-32768) +#define PR_UINT16_MAX 65535U + +/************************************************************************ +** TYPES: PRUint32 +** PRInt32 +** DESCRIPTION: +** The int32 types are known to be 32 bits each. +************************************************************************/ +#if PR_BYTES_PER_INT == 4 +typedef unsigned int PRUint32; +typedef int PRInt32; +#define PR_INT32(x) x +#define PR_UINT32(x) x ## U +#elif PR_BYTES_PER_LONG == 4 +typedef unsigned long PRUint32; +typedef long PRInt32; +#define PR_INT32(x) x ## L +#define PR_UINT32(x) x ## UL +#else +#error No suitable type for PRInt32/PRUint32 +#endif + +/************************************************************************ + * MACROS: PR_INT32_MAX + * PR_INT32_MIN + * PR_UINT32_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt32 or PRUint32. +************************************************************************/ + +#define PR_INT32_MAX PR_INT32(2147483647) +#define PR_INT32_MIN (-PR_INT32_MAX - 1) +#define PR_UINT32_MAX PR_UINT32(4294967295) + +/************************************************************************ +** TYPES: PRUint64 +** PRInt64 +** DESCRIPTION: +** The int64 types are known to be 64 bits each. Care must be used when +** declaring variables of type PRUint64 or PRInt64. Different hardware +** architectures and even different compilers have varying support for +** 64 bit values. The only guaranteed portability requires the use of +** the LL_ macros (see prlong.h). +************************************************************************/ +#ifdef HAVE_LONG_LONG +#if PR_BYTES_PER_LONG == 8 +typedef long PRInt64; +typedef unsigned long PRUint64; +#elif defined(WIN16) +typedef __int64 PRInt64; +typedef unsigned __int64 PRUint64; +#elif defined(WIN32) && !defined(__GNUC__) +typedef __int64 PRInt64; +typedef unsigned __int64 PRUint64; +#else +typedef long long PRInt64; +typedef unsigned long long PRUint64; +#endif /* PR_BYTES_PER_LONG == 8 */ +#else /* !HAVE_LONG_LONG */ +typedef struct { +#ifdef IS_LITTLE_ENDIAN + PRUint32 lo, hi; +#else + PRUint32 hi, lo; +#endif +} PRInt64; +typedef PRInt64 PRUint64; +#endif /* !HAVE_LONG_LONG */ + +/************************************************************************ +** TYPES: PRUintn +** PRIntn +** DESCRIPTION: +** The PRIntn types are most appropriate for automatic variables. They are +** guaranteed to be at least 16 bits, though various architectures may +** define them to be wider (e.g., 32 or even 64 bits). These types are +** never valid for fields of a structure. +************************************************************************/ +#if PR_BYTES_PER_INT >= 2 +typedef int PRIntn; +typedef unsigned int PRUintn; +#else +#error 'sizeof(int)' not sufficient for platform use +#endif + +/************************************************************************ +** TYPES: PRFloat64 +** DESCRIPTION: +** NSPR's floating point type is always 64 bits. +************************************************************************/ +typedef double PRFloat64; + +/************************************************************************ +** TYPES: PRSize +** DESCRIPTION: +** A type for representing the size of objects. +************************************************************************/ +typedef size_t PRSize; + + +/************************************************************************ +** TYPES: PROffset32, PROffset64 +** DESCRIPTION: +** A type for representing byte offsets from some location. +************************************************************************/ +typedef PRInt32 PROffset32; +typedef PRInt64 PROffset64; + +/************************************************************************ +** TYPES: PRPtrDiff +** DESCRIPTION: +** A type for pointer difference. Variables of this type are suitable +** for storing a pointer or pointer subtraction. +************************************************************************/ +typedef ptrdiff_t PRPtrdiff; + +/************************************************************************ +** TYPES: PRUptrdiff +** DESCRIPTION: +** A type for pointer difference. Variables of this type are suitable +** for storing a pointer or pointer sutraction. +************************************************************************/ +#ifdef _WIN64 +typedef unsigned __int64 PRUptrdiff; +#else +typedef unsigned long PRUptrdiff; +#endif + +/************************************************************************ +** TYPES: PRBool +** DESCRIPTION: +** Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE +** for clarity of target type in assignments and actual arguments. Use +** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans +** just as you would C int-valued conditions. +************************************************************************/ +typedef PRIntn PRBool; +#define PR_TRUE 1 +#define PR_FALSE 0 + +/************************************************************************ +** TYPES: PRPackedBool +** DESCRIPTION: +** Use PRPackedBool within structs where bitfields are not desirable +** but minimum and consistant overhead matters. +************************************************************************/ +typedef PRUint8 PRPackedBool; + +/* +** Status code used by some routines that have a single point of failure or +** special status return. +*/ +typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; + +#ifndef __PRUNICHAR__ +#define __PRUNICHAR__ +#if defined(WIN32) || defined(XP_MAC) +typedef wchar_t PRUnichar; +#else +typedef PRUint16 PRUnichar; +#endif +#endif + +/* +** WARNING: The undocumented data types PRWord and PRUword are +** only used in the garbage collection and arena code. Do not +** use PRWord and PRUword in new code. +** +** A PRWord is an integer that is the same size as a void*. +** It implements the notion of a "word" in the Java Virtual +** Machine. (See Sec. 3.4 "Words", The Java Virtual Machine +** Specification, Addison-Wesley, September 1996. +** http://java.sun.com/docs/books/vmspec/index.html.) +*/ +#ifdef _WIN64 +typedef __int64 PRWord; +typedef unsigned __int64 PRUword; +#else +typedef long PRWord; +typedef unsigned long PRUword; +#endif + +#if defined(NO_NSPR_10_SUPPORT) +#else +/********* ???????????????? FIX ME ??????????????????????????? *****/ +/********************** Some old definitions until pr=>ds transition is done ***/ +/********************** Also, we are still using NSPR 1.0. GC ******************/ +/* +** Fundamental NSPR macros, used nearly everywhere. +*/ + +#define PR_PUBLIC_API PR_IMPLEMENT + +/* +** Macro body brackets so that macros with compound statement definitions +** behave syntactically more like functions when called. +*/ +#define NSPR_BEGIN_MACRO do { +#define NSPR_END_MACRO } while (0) + +/* +** Macro shorthands for conditional C++ extern block delimiters. +*/ +#ifdef NSPR_BEGIN_EXTERN_C +#undef NSPR_BEGIN_EXTERN_C +#endif +#ifdef NSPR_END_EXTERN_C +#undef NSPR_END_EXTERN_C +#endif + +#ifdef __cplusplus +#define NSPR_BEGIN_EXTERN_C extern "C" { +#define NSPR_END_EXTERN_C } +#else +#define NSPR_BEGIN_EXTERN_C +#define NSPR_END_EXTERN_C +#endif + +#ifdef XP_MAC +#include "protypes.h" +#else +#include "obsolete/protypes.h" +#endif + +/********* ????????????? End Fix me ?????????????????????????????? *****/ +#endif /* NO_NSPR_10_SUPPORT */ + +PR_END_EXTERN_C + +#endif /* prtypes_h___ */ + diff --git a/engine/qclib/hash.c b/engine/qclib/hash.c index e30a5773f..46607f2e1 100644 --- a/engine/qclib/hash.c +++ b/engine/qclib/hash.c @@ -15,7 +15,7 @@ void Hash_InitTable(hashtable_t *table, int numbucks, void *mem) table->bucket = (bucket_t **)mem; } -int Hash_Key(char *name, int modulus) +int Hash_Key(const char *name, int modulus) { //fixme: optimize. unsigned int key; for (key=0;*name; name++) @@ -23,7 +23,7 @@ int Hash_Key(char *name, int modulus) return (int)(key%modulus); } -int Hash_KeyInsensative(char *name, int modulus) +int Hash_KeyInsensative(const char *name, int modulus) { //fixme: optimize. unsigned int key; for (key=0;*name; name++) @@ -37,7 +37,7 @@ int Hash_KeyInsensative(char *name, int modulus) return (int)(key%modulus); } -void *Hash_Get(hashtable_t *table, char *name) +void *Hash_Get(hashtable_t *table, const char *name) { int bucknum = Hash_Key(name, table->numbuckets); bucket_t *buck; @@ -53,7 +53,7 @@ void *Hash_Get(hashtable_t *table, char *name) } return NULL; } -void *Hash_GetInsensative(hashtable_t *table, char *name) +void *Hash_GetInsensative(hashtable_t *table, const char *name) { int bucknum = Hash_KeyInsensative(name, table->numbuckets); bucket_t *buck; diff --git a/engine/qclib/hash.h b/engine/qclib/hash.h index a46e38011..778e67a57 100644 --- a/engine/qclib/hash.h +++ b/engine/qclib/hash.h @@ -2,13 +2,16 @@ //David's hash tables //string based. +#ifndef HASH_H__ +#define HASH_H__ + #define Hash_BytesForBuckets(b) (sizeof(bucket_t)*b) #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc typedef struct bucket_s { void *data; union { - char *string; + const char *string; int value; } key; struct bucket_s *next; @@ -19,9 +22,9 @@ typedef struct hashtable_s { } hashtable_t; void Hash_InitTable(hashtable_t *table, int numbucks, void *mem); //mem must be 0 filled. (memset(mem, 0, size)) -int Hash_Key(char *name, int modulus); -void *Hash_Get(hashtable_t *table, char *name); -void *Hash_GetInsensative(hashtable_t *table, char *name); +int Hash_Key(const char *name, int modulus); +void *Hash_Get(hashtable_t *table, const char *name); +void *Hash_GetInsensative(hashtable_t *table, const char *name); void *Hash_GetKey(hashtable_t *table, int key); void *Hash_GetNext(hashtable_t *table, char *name, void *old); void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old); @@ -31,3 +34,5 @@ void Hash_Remove(hashtable_t *table, char *name); void Hash_RemoveData(hashtable_t *table, char *name, void *data); void Hash_RemoveKey(hashtable_t *table, int key); void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck); + +#endif diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 7cf88d4dc..b12fdeede 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -172,6 +172,26 @@ struct entvars_s *PR_entvars (progfuncs_t *progfuncs, struct edict_s *ed) return (struct entvars_s *)edvars(ed); } +int PR_GetFuncArgCount(progfuncs_t *progfuncs, func_t func) +{ + unsigned int pnum; + unsigned int fnum; + dfunction_t *f; + + pnum = (func & 0xff000000)>>24; + fnum = (func & 0x00ffffff); + + if (pnum >= (unsigned)maxprogs || !pr_progstate[pnum].functions) + return -1; + else if (fnum >= pr_progstate[pnum].progs->numfunctions) + return -1; + else + { + f = pr_progstate[pnum].functions + fnum; + return f->numparms; + } +} + func_t PR_FindFunc(progfuncs_t *progfuncs, char *funcname, progsnum_t pnum) { dfunction_t *f=NULL; diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index de884875a..1c9d6bead 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -615,6 +615,10 @@ pbool QCC_WriteData (int crc) outputsize = 32; } + if (qcc_targetformat == QCF_DARKPLACES) + compressoutput = 0; + + //compression of blocks? if (compressoutput) progs.blockscompressed |=1; //statements if (compressoutput) progs.blockscompressed |=2; //defs @@ -1881,14 +1885,39 @@ unsigned short QCC_PR_WriteProgdefs (char *filename) printf("Recognised progs as QuakeWorld\n"); break; case 5927: - printf("Recognised progs as regular Quake\n"); + printf("Recognised progs as NetQuake server gamecode\n"); break; + + case 26940: + printf("Recognised progs as Quake pre-release...\n"); + break; + case 38488: printf("Recognised progs as original Hexen2\n"); break; case 26905: printf("Recognised progs as Hexen2 Mission Pack\n"); break; + case 14046: + printf("Recognised progs as Hexen2 (demo)\n"); + break; + + case 32199: + printf("Recognised progs as a CSQC module\n"); + break; + case 52195: + printf("Recognised progs as outdated CSQC module\n"); + break; + case 10020: + printf("Recognised progs as a DP/FTE Menu module\n"); + break; + + case 32401: + printf("Warning: please update your tenebrae system defs.\n"); + break; + default: + printf("Warning: progs CRC not recognised from quake nor clones\n"); + break; } diff --git a/engine/server/q2game.h b/engine/server/q2game.h index eee350b9b..16c293d9c 100644 --- a/engine/server/q2game.h +++ b/engine/server/q2game.h @@ -32,34 +32,13 @@ typedef enum multicast_e extern float pm_q2stepheight; -#ifdef Q2SERVER +#if defined(Q2SERVER) || defined(Q2CLIENT) struct trace_s; struct q2trace_s; struct q2pmove_s; - - -#define Q2GAME_API_VERSION 3 - -// edict->svflags - -#define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects -#define SVF_DEADMONSTER 0x00000002 // treat as CONTENTS_DEADMONSTER for collision -#define SVF_MONSTER 0x00000004 // treat as CONTENTS_MONSTER for collision - -// edict->solid values - -typedef enum -{ -Q2SOLID_NOT, // no interaction with other objects -Q2SOLID_TRIGGER, // only touch when inside, after moving -Q2SOLID_BBOX, // touch on edge -Q2SOLID_BSP // bsp clip, touch on edge -} q2solid_t; - - #define MAXTOUCH 32 typedef struct q2pmove_s { @@ -90,6 +69,28 @@ typedef struct q2pmove_s void VARGS Q2_Pmove (q2pmove_t *pmove); +#endif +#ifdef Q2SERVER + +#define Q2GAME_API_VERSION 3 + +// edict->svflags + +#define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects +#define SVF_DEADMONSTER 0x00000002 // treat as CONTENTS_DEADMONSTER for collision +#define SVF_MONSTER 0x00000004 // treat as CONTENTS_MONSTER for collision + +// edict->solid values + +typedef enum +{ +Q2SOLID_NOT, // no interaction with other objects +Q2SOLID_TRIGGER, // only touch when inside, after moving +Q2SOLID_BBOX, // touch on edge +Q2SOLID_BSP // bsp clip, touch on edge +} q2solid_t; + + //=============================================================== // link_t is only used for entity area links now diff --git a/engine/server/savegame.c b/engine/server/savegame.c index db8f2d94b..cb58433d5 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -548,6 +548,7 @@ qboolean SV_LoadLevelCache(char *level, char *startspot, qboolean ignoreplayers) #ifdef Q2SERVER if (gametype == GT_QUAKE2) { + char syspath[MAX_OSPATH]; SV_SpawnServer (level, startspot, false, false); SV_ClearWorld(); @@ -557,7 +558,10 @@ qboolean SV_LoadLevelCache(char *level, char *startspot, qboolean ignoreplayers) return false; } - ge->ReadLevel(va("%s/%s", com_gamedir, name)); + if (!FS_NativePath(name, FS_GAMEONLY, syspath, sizeof(syspath))) + return false; + + ge->ReadLevel(syspath); for (i=0 ; i<100 ; i++) //run for 10 secs to iron out a few bugs. ge->RunFrame (); @@ -745,7 +749,7 @@ void SV_SaveLevelCache(qboolean dontharmgame) int clnum; char name[256]; - FILE *f; + vfsfile_t *f; int i; char comment[SAVEGAME_COMMENT_LENGTH+1]; @@ -773,10 +777,10 @@ void SV_SaveLevelCache(qboolean dontharmgame) } - sprintf (name, "%s/saves/%s", com_gamedir, cache->mapname); + sprintf (name, "saves/%s", cache->mapname); COM_DefaultExtension (name, ".lvc", sizeof(name)); - COM_CreatePath(name); + FS_CreatePath(name, FS_GAMEONLY); if (!dontharmgame) //save game in progress Con_TPrintf (STL_SAVEGAMETO, name); @@ -784,11 +788,11 @@ void SV_SaveLevelCache(qboolean dontharmgame) #ifdef Q2SERVER if (ge) { - char path[256]; - strcpy(path, name); - path[COM_SkipPath(name)-name] = '\0'; - Sys_mkdir(path); - ge->WriteLevel(name); + char syspath[256]; + + if (!FS_NativePath(name, FS_GAMEONLY, syspath, sizeof(syspath))) + return; + ge->WriteLevel(syspath); return; } #endif @@ -801,16 +805,16 @@ void SV_SaveLevelCache(qboolean dontharmgame) } #endif - f = fopen (name, "wb"); + f = FS_OpenVFS (name, "wb", FS_GAME); if (!f) { Con_TPrintf (STL_ERRORCOULDNTOPEN); return; } - fprintf (f, "%i\n", CACHEGAME_VERSION); + VFS_PRINTF (f, "%i\n", CACHEGAME_VERSION); SV_SavegameComment (comment); - fprintf (f, "%s\n", comment); + VFS_PRINTF (f, "%s\n", comment); for (cl = svs.clients, clnum=0; clnum < MAX_CLIENTS; cl++,clnum++)//fake dropping { if ((cl->state < cs_spawned && !cl->istobeloaded) || dontharmgame) //don't drop if they are still connecting @@ -832,47 +836,47 @@ void SV_SaveLevelCache(qboolean dontharmgame) PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); } } - fprintf (f, "%d\n", progstype); - fprintf (f, "%f\n", skill.value); - fprintf (f, "%f\n", deathmatch.value); - fprintf (f, "%f\n", coop.value); - fprintf (f, "%f\n", teamplay.value); - fprintf (f, "%s\n", sv.name); - fprintf (f, "%f\n",sv.time); + VFS_PRINTF (f, "%d\n", progstype); + VFS_PRINTF (f, "%f\n", skill.value); + VFS_PRINTF (f, "%f\n", deathmatch.value); + VFS_PRINTF (f, "%f\n", coop.value); + VFS_PRINTF (f, "%f\n", teamplay.value); + VFS_PRINTF (f, "%s\n", sv.name); + VFS_PRINTF (f, "%f\n",sv.time); // write the light styles - fprintf (f, "%i\n",MAX_LIGHTSTYLES); + VFS_PRINTF (f, "%i\n",MAX_LIGHTSTYLES); for (i=0 ; iparms->memfree(s); - fclose (f); + VFS_CLOSE (f); } #ifdef NEWSAVEFORMAT @@ -901,11 +905,8 @@ void SV_Savegame_f (void) client_t *cl; int clnum; char comment[SAVEGAME_COMMENT_LENGTH+1]; - FILE *f, *f2; - char filename[MAX_OSPATH]; + vfsfile_t *f; int len; - char *buffer=NULL; - int buflen=0; char *savename; levelcache_t *cache; char str[MAX_LOCALINFO_STRING+1]; @@ -921,111 +922,81 @@ void SV_Savegame_f (void) if (!*savename || strstr(savename, "..")) savename = "quicksav"; - sprintf (filename, "%s/saves/%s/info.fsv", com_gamedir, savename); - COM_CreatePath(filename); - f = fopen(filename, "wt"); + f = FS_OpenVFS(va("saves/%s/info.fsv", savename), "wt", FS_GAMEONLY); if (!f) { - Con_Printf("Couldn't open file %s\n", filename); + Con_Printf("Couldn't open file saves/%s/info.fsv\n", savename); return; } SV_SavegameComment(comment); - fprintf (f, "%d\n", FTESAVEGAME_VERSION+svs.gametype); - fprintf (f, "%s\n", comment); + VFS_PRINTF (f, "%d\n", FTESAVEGAME_VERSION+svs.gametype); + VFS_PRINTF (f, "%s\n", comment); - fprintf(f, "%i\n", sv.allocated_client_slots); + VFS_PRINTF(f, "%i\n", sv.allocated_client_slots); for (cl = svs.clients, clnum=0; clnum < sv.allocated_client_slots; cl++,clnum++) { if (cl->state < cs_spawned && !cl->istobeloaded) //don't save if they are still connecting { - fprintf(f, "\n"); + VFS_PRINTF(f, "\n"); continue; } - fprintf(f, "%s\n", cl->name); + VFS_PRINTF(f, "%s\n", cl->name); if (*cl->name) for (len = 0; len < NUM_SPAWN_PARMS; len++) - fprintf(f, "%i (%f)\n", *(int*)&cl->spawn_parms[len], cl->spawn_parms[len]); //write ints as not everyone passes a float in the parms. + VFS_PRINTF(f, "%i (%f)\n", *(int*)&cl->spawn_parms[len], cl->spawn_parms[len]); //write ints as not everyone passes a float in the parms. //write floats too so you can use it to debug. } Q_strncpyz(str, svs.info, sizeof(str)); Info_RemovePrefixedKeys(str, '*'); - fprintf (f, "%s\"\n", str); + VFS_PRINTF (f, "%s\"\n", str); Q_strncpyz(str, localinfo, sizeof(str)); Info_RemovePrefixedKeys(str, '*'); - fprintf (f, "%s\n", str); + VFS_PRINTF (f, "%s\n", str); - fprintf (f, "{\n"); //all game vars. FIXME: Should save the ones that have been retrieved/set by progs. - fprintf (f, "skill \"%s\"\n", skill.string); - fprintf (f, "deathmatch \"%s\"\n", deathmatch.string); - fprintf (f, "coop \"%s\"\n", coop.string); - fprintf (f, "teamplay \"%s\"\n", teamplay.string); + VFS_PRINTF (f, "{\n"); //all game vars. FIXME: Should save the ones that have been retrieved/set by progs. + VFS_PRINTF (f, "skill \"%s\"\n", skill.string); + VFS_PRINTF (f, "deathmatch \"%s\"\n", deathmatch.string); + VFS_PRINTF (f, "coop \"%s\"\n", coop.string); + VFS_PRINTF (f, "teamplay \"%s\"\n", teamplay.string); - fprintf (f, "nomonsters \"%s\"\n", nomonsters.string); - fprintf (f, "gamecfg\t \"%s\"\n", gamecfg.string); - fprintf (f, "scratch1 \"%s\"\n", scratch1.string); - fprintf (f, "scratch2 \"%s\"\n", scratch2.string); - fprintf (f, "scratch3 \"%s\"\n", scratch3.string); - fprintf (f, "scratch4 \"%s\"\n", scratch4.string); - fprintf (f, "savedgamecfg\t \"%s\"\n", savedgamecfg.string); - fprintf (f, "saved1 \"%s\"\n", saved1.string); - fprintf (f, "saved2 \"%s\"\n", saved2.string); - fprintf (f, "saved3 \"%s\"\n", saved3.string); - fprintf (f, "saved4 \"%s\"\n", saved4.string); - fprintf (f, "temp1 \"%s\"\n", temp1.string); - fprintf (f, "noexit \"%s\"\n", noexit.string); - fprintf (f, "pr_maxedicts\t \"%s\"\n", pr_maxedicts.string); - fprintf (f, "progs \"%s\"\n", progs.string); - fprintf (f, "set nextserver \"%s\"\n", Cvar_Get("nextserver", "", 0, "")->string); - fprintf (f, "}\n"); + VFS_PRINTF (f, "nomonsters \"%s\"\n", nomonsters.string); + VFS_PRINTF (f, "gamecfg\t \"%s\"\n", gamecfg.string); + VFS_PRINTF (f, "scratch1 \"%s\"\n", scratch1.string); + VFS_PRINTF (f, "scratch2 \"%s\"\n", scratch2.string); + VFS_PRINTF (f, "scratch3 \"%s\"\n", scratch3.string); + VFS_PRINTF (f, "scratch4 \"%s\"\n", scratch4.string); + VFS_PRINTF (f, "savedgamecfg\t \"%s\"\n", savedgamecfg.string); + VFS_PRINTF (f, "saved1 \"%s\"\n", saved1.string); + VFS_PRINTF (f, "saved2 \"%s\"\n", saved2.string); + VFS_PRINTF (f, "saved3 \"%s\"\n", saved3.string); + VFS_PRINTF (f, "saved4 \"%s\"\n", saved4.string); + VFS_PRINTF (f, "temp1 \"%s\"\n", temp1.string); + VFS_PRINTF (f, "noexit \"%s\"\n", noexit.string); + VFS_PRINTF (f, "pr_maxedicts\t \"%s\"\n", pr_maxedicts.string); + VFS_PRINTF (f, "progs \"%s\"\n", progs.string); + VFS_PRINTF (f, "set nextserver \"%s\"\n", Cvar_Get("nextserver", "", 0, "")->string); + VFS_PRINTF (f, "}\n"); SV_SaveLevelCache(true); //add the current level. Note that this can cause reentry problems. cache = svs.levcache; //state from previous levels - just copy it all accross. - fprintf(f, "{\n"); + VFS_PRINTF(f, "{\n"); while(cache) { - fprintf(f, "%s\n", cache->mapname); + VFS_PRINTF(f, "%s\n", cache->mapname); - sprintf (filename, "%s/saves/%s.lvc", com_gamedir, cache->mapname); - f2 = fopen(filename, "rb"); - if (!f2) - break; - fseek(f2, 0, SEEK_END); - len = ftell(f2); - if (!len) - { - Con_Printf("WARNING: %s was empty\n"); - fclose(f2); - cache = cache->next; - continue; - } - fseek(f2, 0, SEEK_SET); - if (!buffer || buflen < len) - { - if (buffer) BZ_Free(buffer); - buffer = BZ_Malloc(len); - buflen = len; - } - fread(buffer, len, 1, f2); - fclose(f2); - - sprintf (filename, "%s/saves/%s/%s.lvc", com_gamedir, savename, cache->mapname); - f2 = fopen(filename, "wb"); - if (!f2) - break; - fwrite(buffer, len, 1, f2); - fclose(f2); + FS_Copy(va("saves/%s.lvc", cache->mapname), va("saves/%s/%s.lvc", savename, cache->mapname), FS_GAME); cache = cache->next; } - fprintf(f, "}\n"); + VFS_PRINTF(f, "}\n"); - fprintf (f, "%s\n", sv.name); + VFS_PRINTF (f, "%s\n", sv.name); - fclose(f); + VFS_CLOSE(f); } void SV_Loadgame_f (void) @@ -1033,7 +1004,7 @@ void SV_Loadgame_f (void) levelcache_t *cache; char str[MAX_LOCALINFO_STRING+1], *trim; char savename[MAX_QPATH]; - FILE *f, *fi, *fo; + vfsfile_t *f; char filename[MAX_OSPATH]; int version; int clnum; @@ -1041,32 +1012,31 @@ void SV_Loadgame_f (void) client_t *cl; gametype_e gametype; - int len, buflen=0; - char *buffer=NULL; + int len; Q_strncpyz(savename, Cmd_Argv(1), sizeof(savename)); if (!*savename || strstr(savename, "..")) strcpy(savename, "quicksav"); - sprintf (filename, "%s/saves/%s/info.fsv", com_gamedir, savename); - f = fopen (filename, "rt"); + sprintf (filename, "saves/%s/info.fsv", savename); + f = FS_OpenVFS (filename, "rt", FS_GAME); if (!f) { Con_TPrintf (STL_ERRORCOULDNTOPEN); return; } - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); version = atoi(str); if (version < FTESAVEGAME_VERSION || version >= FTESAVEGAME_VERSION+GT_MAX) { - fclose (f); + VFS_CLOSE (f); Con_TPrintf (STL_BADSAVEVERSION, version, FTESAVEGAME_VERSION); return; } gametype = version - FTESAVEGAME_VERSION; - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); #ifndef SERVERONLY if (!cls.state) #endif @@ -1089,14 +1059,14 @@ void SV_Loadgame_f (void) SV_SendMessagesToAll(); - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); slots = atoi(str); for (cl = svs.clients, clnum=0; clnum < slots; cl++,clnum++) { if (cl->state > cs_zombie) SV_DropClient(cl); - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); str[sizeof(cl->namebuf)-1] = '\0'; for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; @@ -1113,7 +1083,7 @@ void SV_Loadgame_f (void) for (len = 0; len < NUM_SPAWN_PARMS; len++) { - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; for (trim = str; *trim <= ' ' && *trim; trim++) @@ -1130,7 +1100,7 @@ void SV_Loadgame_f (void) } - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; for (trim = str; *trim <= ' ' && *trim; trim++) @@ -1140,7 +1110,7 @@ void SV_Loadgame_f (void) len = strlen(svs.info); Q_strncpyz(svs.info+len, str, sizeof(svs.info)-len); - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; for (trim = str; *trim <= ' ' && *trim; trim++) @@ -1150,7 +1120,7 @@ void SV_Loadgame_f (void) len = strlen(localinfo); Q_strncpyz(localinfo+len, str, sizeof(localinfo)-len); - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; for (trim = str; *trim <= ' ' && *trim; trim++) @@ -1159,7 +1129,7 @@ void SV_Loadgame_f (void) SV_Error("Corrupt saved game\n"); while(1) { - if (!fgets(str, sizeof(str)-1, f)) + if (!VFS_GETS(f, str, sizeof(str)-1)) SV_Error("Corrupt saved game\n"); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; @@ -1173,7 +1143,7 @@ void SV_Loadgame_f (void) SV_FlushLevelCache(); - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; for (trim = str; *trim <= ' ' && *trim; trim++) @@ -1182,7 +1152,7 @@ void SV_Loadgame_f (void) SV_Error("Corrupt saved game\n"); while(1) { - if (!fgets(str, sizeof(str)-1, f)) + if (!VFS_GETS(f, str, sizeof(str)-1)) SV_Error("Corrupt saved game\n"); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; @@ -1201,50 +1171,18 @@ void SV_Loadgame_f (void) cache->next = svs.levcache; - - - - sprintf (filename, "%s/saves/%s/%s.lvc", com_gamedir, savename, cache->mapname); - fi = fopen(filename, "rb"); - if (!fi) - { - Z_Free(cache); - continue; - } - fseek(fi, 0, SEEK_END); - len = ftell(fi); - fseek(fi, 0, SEEK_SET); - if (!buffer || buflen < len) - { - if (buffer) BZ_Free(buffer); - buffer = BZ_Malloc(len); - buflen = len; - } - fread(buffer, len, 1, fi); - fclose(fi); - - sprintf (filename, "%s/saves/%s.lvc", com_gamedir, cache->mapname); - fo = fopen(filename, "wb"); - if (!fo) - { - Z_Free(cache); - continue; - } - fwrite(buffer, len, 1, fo); - fclose(fo); + FS_Copy(va("saves/%s/%s.lvc", savename, cache->mapname), va("saves/%s.lvc", cache->mapname), FS_GAME, FS_GAMEONLY); svs.levcache = cache; } - if (buffer) - Z_Free(buffer); - fgets(str, sizeof(str)-1, f); + VFS_GETS(f, str, sizeof(str)-1); for (trim = str+strlen(str)-1; trim>=str && *trim <= ' '; trim--) *trim='\0'; for (trim = str; *trim <= ' ' && *trim; trim++) ; - fclose(f); + VFS_CLOSE(f); SV_LoadLevelCache(str, "", true); sv.allocated_client_slots = slots; diff --git a/engine/server/server.h b/engine/server/server.h index 2d90d7c0b..f69086692 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1240,7 +1240,7 @@ typedef struct mvddest_s { enum {DEST_NONE, DEST_FILE, DEST_BUFFEREDFILE, DEST_STREAM} desttype; int socket; - FILE *file; + vfsfile_t *file; char name[MAX_QPATH]; char path[MAX_QPATH]; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 0f9c1fef9..2eb1d5890 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -387,7 +387,7 @@ void SV_Give_f (void) } } -int ShowMapList (char *name, int flags, void *parm) +int ShowMapList (const char *name, int flags, void *parm) { if (name[5] == 'b' && name[6] == '_') //skip box models return true; @@ -451,14 +451,17 @@ void SV_Map_f (void) waschangelevel = !strcmp(Cmd_Argv(0), "changelevel"); wasspmap = !strcmp(Cmd_Argv(0), "spmap"); - snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level); // this function and the if statement below, is a quake bugfix which stopped a map called "dm6++.bsp" from loading because of the + sign, quake2 map syntax interprets + character as "intro.cin+base1.bsp", to play a cinematic then load a map after - if (!COM_FCheckExists (expanded)) + if (strcmp(level, ".")) //restart current { - nextserver = strchr(level, '+'); - if (nextserver) + snprintf (expanded, sizeof(expanded), "maps/%s.bsp", level); // this function and the if statement below, is a quake bugfix which stopped a map called "dm6++.bsp" from loading because of the + sign, quake2 map syntax interprets + character as "intro.cin+base1.bsp", to play a cinematic then load a map after + if (!COM_FCheckExists (expanded)) { - *nextserver = '\0'; - nextserver++; + nextserver = strchr(level, '+'); + if (nextserver) + { + *nextserver = '\0'; + nextserver++; + } } } @@ -478,9 +481,14 @@ void SV_Map_f (void) if (!strcmp(level, ".")) //restart current { + //grab the current map name COM_StripExtension(COM_SkipPath(sv.modelname), level, sizeof(level)); issamelevel = true; + if (!*level) + Q_strncpyz(level, "start", sizeof(level)); + + //override the startspot Q_strncpyz(spot, Info_ValueForKey(svs.info, "*startspot"), sizeof(spot)); startspot = spot; } @@ -1281,6 +1289,37 @@ void SV_StuffToClient_f(void) Z_Free(key); } +char *ShowTime(unsigned int seconds) +{ + char buf[1024]; + char *b = buf; + *b = 0; + + if (seconds > 60) + { + if (seconds > 60*60) + { + if (seconds > 24*60*60) + { + strcpy(b, va("%id ", seconds/(24*60*60))); + b += strlen(b); + seconds %= 24*60*60; + } + + strcpy(b, va("%ih ", seconds/(60*60))); + b += strlen(b); + seconds %= 60*60; + } + strcpy(b, va("%im ", seconds/60)); + b += strlen(b); + seconds %= 60; + } + strcpy(b, va("%is", seconds)); + b += strlen(b); + + return va("%s", buf); +} + /* ================ SV_Status_f @@ -1324,7 +1363,17 @@ void SV_Status_f (void) Con_Printf ("avg response time: %i ms\n",(int)avg); Con_Printf ("packets/frame : %5.2f\n", pak); //not relevent as a limit. - Con_Printf ("current map : %s\n", sv.mapname); + //show the current map+name (but hide name if its too long or would be ugly) + if (columns >= 80 && *sv.mapname && strlen(sv.mapname) < 45 && !strchr(sv.mapname, '\n')) + Con_Printf ("current map : %s (%s)\n", sv.name, sv.mapname); + else + Con_Printf ("current map : %s\n", sv.name); + + Con_Printf("map uptime : %s\n", ShowTime(sv.physicstime)); + Con_Printf("server uptime : %s\n", ShowTime(realtime)); + if (sv.csqcdebug) + Con_Printf("csqc debug : true\n"); + Con_Printf("public : %s\n", sv_public.value?"yes":"no"); // min fps lat drp if (columns < 80) @@ -1506,6 +1555,7 @@ SV_Heartbeat_f */ void SV_Heartbeat_f (void) { + Master_ReResolve(); svs.last_heartbeat = -9999; } @@ -1737,7 +1787,7 @@ void SV_Gamedir_f (void) if (Cmd_Argc() == 1) { - Con_TPrintf (STL_CURRENTGAMEDIR, com_gamedir); + Con_TPrintf (STL_CURRENTGAMEDIR, FS_GetGamedir()); return; } diff --git a/engine/server/sv_chat.c b/engine/server/sv_chat.c index 96fdfc119..fe1d478ab 100644 --- a/engine/server/sv_chat.c +++ b/engine/server/sv_chat.c @@ -65,7 +65,7 @@ the qc code: } */ -#ifdef SVCHAT +#if defined(SVCHAT) && !defined(CLIENTONLY) #define SENDDELAY 1 diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index a9f128fb9..a53e7ccd8 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -73,9 +73,15 @@ sv_masterlist_t sv_masterlist[] = { {MP_QUAKEWORLD, SCVARC("sv_master7", "", SV_Masterlist_Callback)}, {MP_QUAKEWORLD, SCVARC("sv_master8", "", SV_Masterlist_Callback)}, - {MP_DARKPLACES, SCVARC("sv_masterextra1", "ghdigital.com", SV_Masterlist_Callback)}, //69.59.212.88 (admin: LordHavoc) - {MP_DARKPLACES, SCVARC("sv_masterextra2", "dpmaster.deathmask.net", SV_Masterlist_Callback)}, //209.164.24.243 (admin: Willis) - {MP_DARKPLACES, SCVARC("sv_masterextra3", "dpmaster.tchr.no", SV_Masterlist_Callback)}, // (admin: tChr) + {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra1", "master.quakeservers.net:27000", SV_Masterlist_Callback)}, //european. admin: raz0? + {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra2", "asgaard.morphos-team.net:27000", SV_Masterlist_Callback)}, //admin bigfoot + {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra3", "qwmaster.ocrana.de:27000", SV_Masterlist_Callback)}, //german. admin unknown + {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra4", "masterserver.exhale.de:27000", SV_Masterlist_Callback)}, //german. admin unknown + {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra5", "kubus.rulez.pl:27000", SV_Masterlist_Callback)}, //poland. admin unknown + + {MP_DARKPLACES, SCVARC("sv_masterextra1", "ghdigital.com:27950", SV_Masterlist_Callback)}, //69.59.212.88 (admin: LordHavoc) + {MP_DARKPLACES, SCVARC("sv_masterextra2", "dpmaster.deathmask.net:27950", SV_Masterlist_Callback)}, //209.164.24.243 (admin: Willis) + {MP_DARKPLACES, SCVARC("sv_masterextra3", "dpmaster.tchr.no:27950", SV_Masterlist_Callback)}, // (admin: tChr) {MP_NONE, SCVAR(NULL, NULL)} }; @@ -1017,17 +1023,17 @@ void SVC_Status (void) } #ifdef NQPROT -void SVC_GetInfo (char *challenge) +void SVC_GetInfo (char *challenge, int fullstatus) { //dpmaster support + char response[MAX_UDP_PACKET]; client_t *cl; int numclients = 0; int i; char *resp; - - if (!*challenge) - challenge = NULL; + char *gamestatus; + eval_t *v; for (i=0 ; istring); + else + gamestatus = ""; + } + else + gamestatus = ""; - resp = va("\377\377\377\377infoResponse\x0A" - "\\gamename\\%s" - "\\protocol\\%i" - "\\clients\\%d" - "\\sv_maxclients\\%s\\mapname\\%s" - "%s" - "%s%s", - com_gamename.string, - NET_PROTOCOL_VERSION, - numclients, - maxclients.string, Info_ValueForKey(svs.info, "map"), - svs.info, - challenge ? "\\challenge\\" : "", challenge ? challenge : ""); - Info_RemoveKey(resp + 17, "maxclients"); - Info_RemoveKey(resp + 17, "map"); - NET_SendPacket (NS_SERVER, strlen(resp), resp, net_from); + resp = response; + + //response packet header + *resp++ = 0xff; + *resp++ = 0xff; + *resp++ = 0xff; + *resp++ = 0xff; + if (fullstatus) + Q_strncpyz(resp, "statusResponse", sizeof(response) - (resp-response) - 1); + else + Q_strncpyz(resp, "infoResponse", sizeof(response) - (resp-response) - 1); + resp += strlen(resp); + *resp++ = '\n'; + + //first line is the serverinfo + Q_strncpyz(resp, svs.info, sizeof(response) - (resp-response)); + //this is a DP protocol, so some QW fields are not needed + Info_RemoveKey(resp, "maxclients"); + Info_RemoveKey(resp, "map"); + Info_SetValueForKey(resp, "gamename", com_gamename.string, sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "modname", com_modname.string, sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "protocol", va("%d", NET_PROTOCOL_VERSION), sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "mapname", Info_ValueForKey(svs.info, "map"), sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "qcstatus", gamestatus, sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "challenge", challenge, sizeof(response) - (resp-response)); + resp += strlen(resp); + + *resp++ = 0; //there's already a null, but hey + + if (fullstatus) + { + client_t *cl; + char *start = resp; + + if (resp != response+sizeof(response)) + { + resp[-1] = '\n'; //replace the null terminator that we already wrote + + //on the following lines we have an entry for each client + for (i=0 ; istate == cs_connected || cl->state == cs_spawned || cl->name[0]) && !cl->spectator) + { + Q_strncpyz(resp, va( + "%d %d \"%s\" \"%s\"\n" + , + cl->old_frags, + SV_CalcPing(cl), + cl->team, + cl->name + ), sizeof(response) - (resp-response)); + resp += strlen(resp); + } + } + + *resp++ = 0; //this might not be a null + if (resp == response+sizeof(response)) + { + //we're at the end of the buffer, it's full. bummer + //replace 12 bytes with infoResponse + memcpy(response+4, "infoResponse", 12); + //move down by len(statusResponse)-len(infoResponse) bytes + memmove(response+4+12, response+4+14, resp-response-(4+14)); + start -= 14-12; //fix this pointer + + resp = start; + resp[-1] = 0; //reset the \n + } + } + } + + NET_SendPacket (NS_SERVER, resp-response, response, net_from); } #endif @@ -1994,12 +2069,14 @@ client_t *SVC_DirectConnect(void) //initialise the client's frames, based on that client's protocol switch(newcl->protocol) { +#ifdef Q3SERVER case CP_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 case CP_QUAKE2: // build a new connection @@ -2572,8 +2649,10 @@ qboolean SV_ConnectionlessPacket (void) SVC_GetChallenge (); } #ifdef NQPROT + else if (!strcmp(c, "getstatus")) + SVC_GetInfo(Cmd_Args(), true); else if (!strcmp(c, "getinfo")) - SVC_GetInfo(Cmd_Args()); + SVC_GetInfo(Cmd_Args(), false); #endif else if (!strcmp(c, "rcon")) SVC_RemoteCommand (); @@ -3775,6 +3854,15 @@ void Master_Add(char *stringadr) svs.last_heartbeat = -99999; } +void Master_ReResolve(void) +{ + int i; + for (i = 0; sv_masterlist[i].cv.name; i++) + { + sv_masterlist[i].needsresolve = true; + } +} + void Master_ClearAll(void) { int i; @@ -3797,6 +3885,10 @@ void Master_Shutdown (void) char adr[MAX_ADR_SIZE]; int i; + //note that if a master server actually blindly listens to this then its exploitable. + //we send it out anyway as for us its all good. + //master servers ought to try and check up on the status of the server first, if they listen to this. + sprintf (string, "%c\n", S2M_SHUTDOWN); // send to group master @@ -3808,7 +3900,7 @@ void Master_Shutdown (void) { case MP_QUAKEWORLD: if (sv_reportheartbeats.value) - Con_Printf ("Sending heartbeat to %s\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr)); + Con_Printf ("Sending shutdown to %s\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr)); NET_SendPacket (NS_SERVER, strlen(string), string, sv_masterlist[i].adr); break; @@ -4226,19 +4318,35 @@ void SV_Init (quakeparms_t *parms) Cmd_RemoveCommand("bind"); // if a map wasn't specified on the command line, spawn start.map - if (sv.state == ss_dead) - Cmd_ExecuteString ("map start", RESTRICT_LOCAL); - if (sv.state == ss_dead) + if (sv.state == ss_dead && Cmd_AliasExist("startmap_dm", RESTRICT_LOCAL)) { - cvar_t *ml; - ml = Cvar_Get("g_maplist", "dm1 dm2 dm3 dm4 dm5 dm6", 0, ""); - Cmd_TokenizeString(ml->string, false, false); - if (Cmd_Argc()) - Cmd_ExecuteString(va("map %s", Cmd_Argv(rand()%Cmd_Argc())), RESTRICT_LOCAL); + Cbuf_AddText("startmap_dm", RESTRICT_LOCAL); //DP extension + Cbuf_Execute(); } + if (sv.state == ss_dead && Cmd_AliasExist("startmap_sp", RESTRICT_LOCAL)) + { + Cbuf_AddText("startmap_sp", RESTRICT_LOCAL); //DP extension + Cbuf_Execute(); + } + if (sv.state == ss_dead && COM_FCheckExists("maps/start.bsp")) + Cmd_ExecuteString ("map start", RESTRICT_LOCAL); //regular q1 + if (sv.state == ss_dead && COM_FCheckExists("maps/demo1.bsp")) + Cmd_ExecuteString ("map demo1", RESTRICT_LOCAL); //regular h2 sp +#ifdef Q2SERVER + if (sv.state == ss_dead && COM_FCheckExists("maps/base1.bsp")) + Cmd_ExecuteString ("map base1", RESTRICT_LOCAL); //regular q2 sp +#endif +#ifdef Q3SERVER + if (sv.state == ss_dead && COM_FCheckExists("maps/q3dm1.bsp")) + Cmd_ExecuteString ("map q3dm1", RESTRICT_LOCAL); //regular q3 'sp' +#endif +#ifdef HLSERVER + if (sv.state == ss_dead && COM_FCheckExists("maps/c0a0.bsp")) + Cmd_ExecuteString ("map c0a0", RESTRICT_LOCAL); //regular hl sp +#endif + if (sv.state == ss_dead) SV_Error ("Couldn't spawn a server"); - } } diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 1d5fef0de..bc1335723 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -34,6 +34,7 @@ mvddest_t *singledest; mvddest_t *SV_InitStream(int socket); static qboolean SV_MVD_Record (mvddest_t *dest); +char *SV_MVDName2Txt(char *name); extern cvar_t qtv_password; void DestClose(mvddest_t *d, qboolean destroyfiles) @@ -43,17 +44,16 @@ void DestClose(mvddest_t *d, qboolean destroyfiles) if (d->cache) BZ_Free(d->cache); if (d->file) - fclose(d->file); + VFS_CLOSE(d->file); if (d->socket) UDP_CloseSocket(d->socket); if (destroyfiles) { - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, d->path, d->name); - Sys_remove(path); + snprintf(path, MAX_OSPATH, "%s/%s", d->path, d->name); + FS_Remove(path, FS_GAMEONLY); - Q_strncpyz(path + strlen(path) - 3, "txt", MAX_OSPATH - strlen(path) + 3); - Sys_remove(path); + FS_Remove(SV_MVDName2Txt(path), FS_GAMEONLY); } Z_Free(d); @@ -84,15 +84,15 @@ void DestFlush(qboolean compleate) switch(d->desttype) { case DEST_FILE: - fflush (d->file); + VFS_FLUSH (d->file); break; case DEST_BUFFEREDFILE: if (d->cacheused+demo_size_padding > d->maxcachesize || compleate) { - len = fwrite(d->cache, 1, d->cacheused, d->file); + len = VFS_WRITE(d->file, d->cache, d->cacheused); if (len < d->cacheused) d->error = true; - fflush(d->file); + VFS_FLUSH(d->file); d->cacheused = 0; } @@ -547,7 +547,7 @@ int DemoWriteDest(void *data, int len, mvddest_t *d) switch(d->desttype) { case DEST_FILE: - fwrite(data, len, 1, d->file); + VFS_WRITE(d->file, data, len); break; case DEST_BUFFEREDFILE: //these write to a cache, which is flushed later case DEST_STREAM: @@ -651,142 +651,46 @@ typedef struct #define SORT_NO 0 #define SORT_BY_DATE 1 -#ifdef _WIN32 +int Sys_listdirFound(const char *fname, int fsize, void *uptr) +{ + file_t *f; + dir_t *dir = uptr; + fname = COM_SkipPath(fname); + if (!*fname) + { + dir->numdirs++; + return true; + } + if (dir->numfiles == dir->maxfiles) + return true; + f = &dir->files[dir->numfiles++]; + Q_strncpyz(f->name, fname, sizeof(f->name)); + f->size = fsize; + dir->size += fsize; + + return true; +} + dir_t *Sys_listdir (char *path, char *ext, qboolean usesorting) { + char searchterm[MAX_QPATH]; + unsigned int maxfiles = MAX_DIRFILES; dir_t *dir = malloc(sizeof(*dir) + sizeof(*dir->files)*maxfiles); - HANDLE h; - WIN32_FIND_DATA fd; - int i, pos, size; - char name[MAX_MVD_NAME], *s; - memset(dir, 0, sizeof(*dir)); - dir->files = (file_t*)(dir+1); dir->maxfiles = maxfiles; - h = FindFirstFile (va("%s/*.*", path), &fd); - if (h == INVALID_HANDLE_VALUE) - { - return dir; - } - - do - { - if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - dir->numdirs++; - continue; - } - - size = fd.nFileSizeLow; - Q_strncpyz (name, fd.cFileName, MAX_MVD_NAME); - dir->size += size; - - for (s = fd.cFileName + strlen(fd.cFileName); s > fd.cFileName; s--) - { - if (*s == '.') - break; - } - - if (strcmp(s, ext)) - continue; - - // inclusion sort - #if 0 - for (i=0 ; inumfiles; - pos = i; - dir->numfiles++; - for (i=dir->numfiles-1 ; i>pos ; i--) - dir->files[i] = dir->files[i-1]; - - strcpy (dir->files[i].name, name); - dir->files[i].size = size; - if (dir->numfiles == dir->maxfiles) - break; - } while ( FindNextFile(h, &fd) ); - FindClose (h); + Q_strncpyz(searchterm, va("%s/*.%s", path, ext), sizeof(searchterm)); + COM_EnumerateFiles(searchterm, Sys_listdirFound, dir); return dir; } - void Sys_freedir(dir_t *dir) { free(dir); } -#else -#include -dir_t *Sys_listdir (char *path, char *ext, qboolean usesorting) -{ - unsigned int maxfiles = MAX_DIRFILES; - dir_t *d = malloc(sizeof(*d) + sizeof(*d->files)*maxfiles); - - int i, extsize; - DIR *dir; - struct dirent *oneentry; - char pathname[MAX_OSPATH]; - qboolean all; - - memset(d, 0, sizeof(*d)); - d->files = (file_t*)(d+1); - d->maxfiles = maxfiles; - extsize = strlen(ext); - all = !strcmp(ext, ".*"); - - dir=opendir(path); - if (!dir) - { - return d; - } - - for(;;) - { - oneentry=readdir(dir); - if(!oneentry) - break; - -#ifndef __CYGWIN__ - if (oneentry->d_type == DT_DIR || oneentry->d_type == DT_LNK) - { - d->numdirs++; - continue; - } -#endif - - sprintf(pathname, "%s/%s", path, oneentry->d_name); - d->files[d->numfiles].size = COM_FileSize(pathname); - d->size += d->files[d->numfiles].size; - - i = strlen(oneentry->d_name); - if (!all && (i < extsize || (Q_strcasecmp(oneentry->d_name+i-extsize, ext)))) - continue; - - Q_strncpyz(d->files[d->numfiles].name, oneentry->d_name, MAX_MVD_NAME); - d->numfiles++; - - if (d->numfiles == d->maxfiles) - break; - } - - closedir(dir); - - return d; -} -void Sys_freedir(dir_t *dir) -{ - free(dir); -} -#endif - @@ -1415,11 +1319,11 @@ mvddest_t *SV_InitRecordFile (char *name) { char *s; mvddest_t *dst; - FILE *file; + vfsfile_t *file; char path[MAX_OSPATH]; - file = fopen (name, "wb"); + file = FS_OpenVFS (name, "wb", FS_GAMEONLY); if (!file) { Con_Printf ("ERROR: couldn't open \"%s\"\n", name); @@ -1459,9 +1363,9 @@ mvddest_t *SV_InitRecordFile (char *name) if (sv_demotxt.value) { - FILE *f; + vfsfile_t *f; - f = fopen (path, "w+t"); + f = FS_OpenVFS (path, "wt", FS_GAMEONLY); if (f != NULL) { char buf[2000]; @@ -1470,13 +1374,13 @@ mvddest_t *SV_InitRecordFile (char *name) SV_TimeOfDay(&date); snprintf(buf, sizeof(buf), "date %s\nmap %s\nteamplay %d\ndeathmatch %d\ntimelimit %d\n%s",date.str, sv.name, (int)teamplay.value, (int)deathmatch.value, (int)timelimit.value, SV_PrintTeams()); - fwrite(buf, strlen(buf),1,f); - fflush(f); - fclose(f); + VFS_WRITE(f, buf, strlen(buf)); + VFS_FLUSH(f); + VFS_CLOSE(f); } } else - Sys_remove(path); + FS_Remove(path, FS_GAMEONLY); return dst; @@ -2038,7 +1942,7 @@ void SV_MVD_Record_f (void) return; } - dir = Sys_listdir(va("%s/%s", com_gamedir, sv_demoDir.string), ".*", SORT_NO); + dir = Sys_listdir(sv_demoDir.string, ".*", SORT_NO); if (sv_demoMaxDirSize.value && dir->size > sv_demoMaxDirSize.value*1024) { Con_Printf("insufficient directory space, increase sv_demoMaxDirSize\n"); @@ -2052,7 +1956,7 @@ void SV_MVD_Record_f (void) sizeof(newname) - strlen(sv_demoSuffix.string) - 5); Q_strncatz(newname, sv_demoSuffix.string, MAX_MVD_NAME); - snprintf (name, MAX_OSPATH+MAX_MVD_NAME, "%s/%s/%s", com_gamedir, sv_demoDir.string, newname); + snprintf (name, MAX_OSPATH+MAX_MVD_NAME, "%s/%s", sv_demoDir.string, newname); COM_StripExtension(name, name, sizeof(name)); @@ -2273,7 +2177,7 @@ void SV_MVDEasyRecord_f (void) char name2[MAX_OSPATH*7]; // scream //char name2[MAX_OSPATH*2]; int i; - FILE *f; + vfsfile_t *f; c = Cmd_Argc(); if (c > 2) @@ -2288,7 +2192,7 @@ void SV_MVDEasyRecord_f (void) return; } - dir = Sys_listdir(va("%s/%s", com_gamedir,sv_demoDir.string), ".*", SORT_NO); + dir = Sys_listdir(sv_demoDir.string, ".*", SORT_NO); if (sv_demoMaxDirSize.value && dir->size > sv_demoMaxDirSize.value*1024) { Con_Printf("insufficient directory space, increase sv_demoMaxDirSize\n"); @@ -2334,25 +2238,25 @@ void SV_MVDEasyRecord_f (void) Q_strncpyz(name, va("%s%s", sv_demoPrefix.string, SV_CleanName(name)), MAX_MVD_NAME - strlen(sv_demoSuffix.string) - 7); Q_strncatz(name, sv_demoSuffix.string, sizeof(name)); - Q_strncpyz(name, va("%s/%s/%s", com_gamedir, sv_demoDir.string, name), sizeof(name)); + Q_strncpyz(name, va("%s/%s", sv_demoDir.string, name), sizeof(name)); // find a filename that doesn't exist yet Q_strncpyz(name2, name, sizeof(name2)); - Sys_mkdir(va("%s/%s", com_gamedir, sv_demoDir.string)); + FS_CreatePath (sv_demoDir.string, FS_GAMEONLY); // COM_StripExtension(name2, name2); strcat (name2, ".mvd"); - if ((f = fopen (name2, "rb")) == 0) - f = fopen(va("%s.gz", name2), "rb"); + if ((f = FS_OpenVFS(name2, "rb", FS_GAMEONLY)) == 0) + f = FS_OpenVFS(va("%s.gz", name2), "rb", FS_GAMEONLY); if (f) { i = 1; do { - fclose (f); + VFS_CLOSE (f); snprintf(name2, sizeof(name2), "%s_%02i", name, i); // COM_StripExtension(name2, name2); strcat (name2, ".mvd"); - if ((f = fopen (name2, "rb")) == 0) - f = fopen(va("%s.gz", name2), "rb"); + if ((f = FS_OpenVFS (name2, "rb", FS_GAMEONLY)) == 0) + f = FS_OpenVFS(va("%s.gz", name2), "rb", FS_GAMEONLY); i++; } while (f); } @@ -2490,8 +2394,8 @@ void SV_MVDList_f (void) float f; int i,j,show; - Con_Printf("content of %s/%s/*.mvd\n", com_gamedir,sv_demoDir.string); - dir = Sys_listdir(va("%s/%s", com_gamedir,sv_demoDir.string), ".mvd", SORT_BY_DATE); + Con_Printf("content of %s/*.mvd\n", sv_demoDir.string); + dir = Sys_listdir(sv_demoDir.string, ".mvd", SORT_BY_DATE); list = dir->files; if (!list->name[0]) { @@ -2541,7 +2445,7 @@ void SV_UserCmdMVDList_f (void) int i,j,show; Con_Printf("available demos\n"); - dir = Sys_listdir(va("%s/%s", com_gamedir,sv_demoDir.string), ".mvd", SORT_BY_DATE); + dir = Sys_listdir(sv_demoDir.string, ".mvd", SORT_BY_DATE); list = dir->files; if (!list->name[0]) { @@ -2587,7 +2491,7 @@ char *SV_MVDNum(char *buffer, int bufferlen, int num) file_t *list; dir_t *dir; - dir = Sys_listdir(va("%s/%s", com_gamedir, sv_demoDir.string), ".mvd", SORT_BY_DATE); + dir = Sys_listdir(sv_demoDir.string, ".mvd", SORT_BY_DATE); list = dir->files; if (num > dir->numfiles || num <= 0) @@ -2647,7 +2551,7 @@ void SV_MVDRemove_f (void) // remove all demos with specified token ptr++; - dir = Sys_listdir(va("%s/%s", com_gamedir, sv_demoDir.string), ".mvd", SORT_BY_DATE); + dir = Sys_listdir(sv_demoDir.string, ".mvd", SORT_BY_DATE); list = dir->files; for (i = 0;i < dir->numfiles; list++) { @@ -2657,14 +2561,14 @@ void SV_MVDRemove_f (void) SV_MVDStop_f(); // stop recording first; - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, sv_demoDir.string, list->name); - if (!Sys_remove(path)) + snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, list->name); + if (!FS_Remove(path, FS_GAMEONLY)) { Con_Printf("removing %s...\n", list->name); i++; } - Sys_remove(SV_MVDName2Txt(path)); + FS_Remove(SV_MVDName2Txt(path), FS_GAMEONLY); } } Sys_freedir(dir); @@ -2684,19 +2588,19 @@ void SV_MVDRemove_f (void) Q_strncpyz(name, Cmd_Argv(1), MAX_MVD_NAME); COM_DefaultExtension(name, ".mvd", sizeof(name)); - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); if (sv.mvdrecording && !strcmp(name, demo.name)) SV_MVDStop_f(); - if (!Sys_remove(path)) + if (!FS_Remove(path, FS_GAMEONLY)) { Con_Printf("demo %s successfully removed\n", name); } else Con_Printf("unable to remove demo %s\n", name); - Sys_remove(SV_MVDName2Txt(path)); + FS_Remove(SV_MVDName2Txt(path), FS_GAMEONLY); } void SV_MVDRemoveNum_f (void) @@ -2726,15 +2630,15 @@ void SV_MVDRemoveNum_f (void) if (sv.mvdrecording && !strcmp(name, demo.name)) SV_MVDStop_f(); - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); - if (!Sys_remove(path)) + snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); + if (!FS_Remove(path, FS_GAMEONLY)) { Con_Printf("demo %s succesfully removed\n", name); } else Con_Printf("unable to remove demo %s\n", name); - Sys_remove(SV_MVDName2Txt(path)); + FS_Remove(SV_MVDName2Txt(path), FS_GAMEONLY); } else Con_Printf("invalid demo num\n"); @@ -2744,7 +2648,7 @@ void SV_MVDInfoAdd_f (void) { char namebuf[MAX_QPATH]; char *name, *args, path[MAX_OSPATH]; - FILE *f; + vfsfile_t *f; if (Cmd_Argc() < 3) { Con_Printf("usage:MVDInfoAdd \n = * for currently recorded demo\n"); @@ -2759,7 +2663,7 @@ void SV_MVDInfoAdd_f (void) return; } - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, demo.path, SV_MVDName2Txt(demo.name)); + snprintf(path, MAX_OSPATH, "%s/%s", demo.path, SV_MVDName2Txt(demo.name)); } else { @@ -2771,10 +2675,10 @@ void SV_MVDInfoAdd_f (void) return; } - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); } - if ((f = fopen(path, "a+t")) == NULL) + if ((f = FS_OpenVFS(path, "a+t", FS_GAMEONLY)) == NULL) { Con_Printf("failed to open the file\n"); return; @@ -2785,10 +2689,10 @@ void SV_MVDInfoAdd_f (void) while (*args > 32) args++; while (*args && *args <= 32) args++; - fwrite(args, strlen(args), 1, f); - fwrite("\n", 1, 1, f); - fflush(f); - fclose(f); + VFS_WRITE(f, args, strlen(args)); + VFS_WRITE(f, "\n", 1); + VFS_FLUSH(f); + VFS_CLOSE(f); } void SV_MVDInfoRemove_f (void) @@ -2810,7 +2714,7 @@ void SV_MVDInfoRemove_f (void) return; } - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, demo.path, SV_MVDName2Txt(demo.name)); + snprintf(path, MAX_OSPATH, "%s/%s", demo.path, SV_MVDName2Txt(demo.name)); } else { @@ -2822,10 +2726,10 @@ void SV_MVDInfoRemove_f (void) return; } - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); } - if (Sys_remove(path)) + if (FS_Remove(path, FS_GAMEONLY)) Con_Printf("failed to remove the file\n"); else Con_Printf("file removed\n"); } @@ -2834,7 +2738,7 @@ void SV_MVDInfo_f (void) { int len; char buf[64]; - FILE *f = NULL; + vfsfile_t *f = NULL; char *name, path[MAX_OSPATH]; if (Cmd_Argc() < 2) @@ -2851,7 +2755,7 @@ void SV_MVDInfo_f (void) return; } - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, demo.path, SV_MVDName2Txt(demo.name)); + snprintf(path, MAX_OSPATH, "%s/%s", demo.path, SV_MVDName2Txt(demo.name)); } else { @@ -2863,10 +2767,10 @@ void SV_MVDInfo_f (void) return; } - snprintf(path, MAX_OSPATH, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name); } - if ((f = fopen(path, "rt")) == NULL) + if ((f = FS_OpenVFS(path, "rt", FS_GAMEONLY)) == NULL) { Con_Printf("(empty)\n"); return; @@ -2874,14 +2778,14 @@ void SV_MVDInfo_f (void) for(;;) { - len = fread (buf, 1, sizeof(buf)-1, f); + len = VFS_READ (f, buf, sizeof(buf)-1); if (len < 0) break; buf[len] = 0; Con_Printf("%s", buf); } - fclose(f); + VFS_CLOSE(f); } diff --git a/engine/server/sv_rankin.c b/engine/server/sv_rankin.c index 02c1e6f88..8eb7c4aa5 100644 --- a/engine/server/sv_rankin.c +++ b/engine/server/sv_rankin.c @@ -122,6 +122,7 @@ void inline WRITEHEADER(void) qboolean Rank_OpenRankings(void) { + char syspath[MAX_OSPATH]; qboolean created; if (!rankfile) { @@ -130,13 +131,13 @@ qboolean Rank_OpenRankings(void) return false; } - if (strstr(rank_filename.string, "..")) + if (!FS_NativePath(rank_filename.string, FS_GAMEONLY, syspath, sizeof(syspath))) return false; - rankfile = fopen(va("%s/%s", com_gamedir, rank_filename.string), "r+b"); + rankfile = fopen(syspath, "r+b"); if (!rankfile) //hmm... try creating { - rankfile = fopen(va("%s/%s", com_gamedir, rank_filename.string), "w+b"); + rankfile = fopen(syspath, "w+b"); created = true; } else diff --git a/engine/server/sv_sys_win.c b/engine/server/sv_sys_win.c index 0999a8d6e..bb9b53bb4 100644 --- a/engine/server/sv_sys_win.c +++ b/engine/server/sv_sys_win.c @@ -324,7 +324,7 @@ qboolean Sys_remove (char *path) return true; } -int Sys_EnumerateFiles (char *gpath, char *match, int (*func)(char *, int, void *), void *parm) +int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { HANDLE r; WIN32_FIND_DATA fd; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 02319f3e3..1eb7caa36 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1320,6 +1320,8 @@ void SV_Spawn_f (void) { split->entgravity = 1; split->maxspeed = 320; + + SVHL_PutClientInServer(split); } secret_total = 0; @@ -1421,6 +1423,9 @@ void SV_Begin_Core(client_t *split) #ifdef Q2SERVER if (ge) { + ge->ClientUserinfoChanged (split->q2edict, split->userinfo); //tell the gamecode + SV_ExtractFromUserinfo(split); //let the server routines know + ge->ClientBegin(split->q2edict); split->istobeloaded = false; } @@ -1469,13 +1474,6 @@ void SV_Begin_Core(client_t *split) } else { -#ifdef HLSERVER - if (svs.gametype == GT_HALFLIFE) - { - SVHL_PutClientInServer(split); - } - else -#endif if (svprogfuncs) { eval_t *eval, *eval2; @@ -2000,7 +1998,7 @@ void SV_NextUpload (void) //Use of this function is on name only. //Be aware that the maps directory should be restricted based on weather the file was from a pack file //this is to preserve copyright - please do not breach due to a bug. -qboolean SV_AllowDownload (char *name) +qboolean SV_AllowDownload (const char *name) { extern cvar_t allow_download; extern cvar_t allow_download_skins; @@ -3347,6 +3345,14 @@ void Cmd_Give_f (void) char *t; int v; +#ifdef HLSERVER + if (svs.gametype == GT_HALFLIFE) + { + HLSV_ClientCommand(host_client); + return; + } +#endif + if (!sv_allow_cheats) { Con_Printf ("Cheats are not allowed on this server\n"); diff --git a/engine/server/svhl_game.c b/engine/server/svhl_game.c new file mode 100644 index 000000000..b3e3ddecf --- /dev/null +++ b/engine/server/svhl_game.c @@ -0,0 +1,1724 @@ +#include "qwsvdef.h" + +/* +I think globals.maxentities is the hard cap, rather than current max like in q1. +*/ + +#ifdef HLSERVER + +#include "svhl_gcapi.h" + +#include "crc.h" +#include "model_hl.h" + +#define GAMECODEMODULE Cvar_Get("hl_svgame", "valve/dlls/mp.dll", 0, "halflife cvars")->string + +#define ignore(s) Con_Printf("Fixme: " s "\n") +#define notimp(l) Con_Printf("halflife sv builtin not implemented on line %i\n", l) + + +dllhandle_t *hlgamecode; +SVHL_Globals_t SVHL_Globals; +SVHL_GameFuncs_t SVHL_GameFuncs; + +#define MAX_HL_EDICTS 2048 +hledict_t *SVHL_Edict; +int SVHL_NumActiveEnts; + +int lastusermessage; + + + + +string_t GHL_AllocString(char *string) +{ + char *news; + news = Hunk_Alloc(strlen(string)+1); + memcpy(news, string, strlen(string)+1); + return news - SVHL_Globals.stringbase; +} +int GHL_PrecacheModel(char *name) +{ + int i; + + if (name[0] <= ' ') + { + Con_Printf ("precache_model: empty string\n"); + return 0; + } + + for (i=1 ; i=MAX_QPATH-1) //probably safest to keep this. + { + SV_Error ("Precache name too long"); + return 0; + } + name = sv.strings.model_precache[i] = SVHL_Globals.stringbase+GHL_AllocString(name); + + if (!strcmp(name + strlen(name) - 4, ".bsp")) + sv.models[i] = Mod_FindName(name); + + if (sv.state != ss_loading) + { + MSG_WriteByte(&sv.reliable_datagram, svcfte_precache); + MSG_WriteShort(&sv.reliable_datagram, i); + MSG_WriteString(&sv.reliable_datagram, name); +#ifdef NQPROT + MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache); + MSG_WriteShort(&sv.nqreliable_datagram, i); + MSG_WriteString(&sv.nqreliable_datagram, name); +#endif + } + + return i; + } + if (!strcmp(sv.strings.model_precache[i], name)) + { + return i; + } + } + SV_Error ("GHL_precache_model: overflow"); + return 0; +} +int GHL_PrecacheSound(char *name) +{ + int i; + + if (name[0] <= ' ') + { + Con_Printf ("precache_sound: empty string\n"); + return 0; + } + + for (i=1 ; i=MAX_QPATH-1) //probably safest to keep this. + { + SV_Error ("Precache name too long"); + return 0; + } + strcpy(sv.strings.sound_precache[i], name); + name = sv.strings.sound_precache[i]; + + if (sv.state != ss_loading) + { + MSG_WriteByte(&sv.reliable_datagram, svcfte_precache); + MSG_WriteShort(&sv.reliable_datagram, -i); + MSG_WriteString(&sv.reliable_datagram, name); +#ifdef NQPROT + MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache); + MSG_WriteShort(&sv.nqreliable_datagram, -i); + MSG_WriteString(&sv.nqreliable_datagram, name); +#endif + } + + return i; + } + if (!strcmp(sv.strings.sound_precache[i], name)) + { + return i; + } + } + SV_Error ("GHL_precache_sound: overflow"); + return 0; +} +void GHL_SetModel(hledict_t *ed, char *modelname) +{ + model_t *mod; + int mdlidx = GHL_PrecacheModel(modelname); + ed->v.modelindex = mdlidx; + ed->v.model = sv.strings.model_precache[mdlidx] - SVHL_Globals.stringbase; + + mod = sv.models[mdlidx]; + if (mod) + { + VectorCopy(mod->mins, ed->v.mins); + VectorCopy(mod->maxs, ed->v.maxs); + VectorSubtract(mod->maxs, mod->mins, ed->v.size); + } + SVHL_LinkEdict(ed, false); +} +unk GHL_ModelIndex(unk){notimp(__LINE__);} +int GHL_ModelFrames(int midx) +{ + //returns the number of frames(sequences I assume) this model has + ignore("ModelFrames"); + return 1; +} +void GHL_SetSize(hledict_t *ed, float *mins, float *maxs) +{ + VectorCopy(mins, ed->v.mins); + VectorCopy(maxs, ed->v.maxs); + SVHL_LinkEdict(ed, false); +} +void GHL_ChangeLevel(char *nextmap, char *startspot) +{ + Cbuf_AddText(va("changelevel %s %s@%f@%f@%f\n", nextmap, startspot, SVHL_Globals.landmark[0], SVHL_Globals.landmark[1], SVHL_Globals.landmark[2]), RESTRICT_PROGS); +} +unk GHL_GetSpawnParms(unk){notimp(__LINE__);} +unk GHL_SaveSpawnParms(unk){notimp(__LINE__);} +float GHL_VecToYaw(float *inv) +{ + vec3_t outa; + + VectorAngles(inv, NULL, outa); + return outa[1]; +} +void GHL_VecToAngles(float *inv, float *outa) +{ + VectorAngles(inv, NULL, outa); +} +unk GHL_MoveToOrigin(unk){notimp(__LINE__);} +unk GHL_ChangeYaw(unk){notimp(__LINE__);} +unk GHL_ChangePitch(unk){notimp(__LINE__);} +hledict_t *GHL_FindEntityByString(hledict_t *last, char *field, char *value) +{ + hledict_t *ent; + int i; + int ofs; + string_t str; + if (!strcmp(field, "targetname")) + ofs = (char*)&((hledict_t *)NULL)->v.targetname - (char*)NULL; + else if (!strcmp(field, "classname")) + ofs = (char*)&((hledict_t *)NULL)->v.classname - (char*)NULL; + else + { + Con_Printf("Fixme: Look for %s=%s\n", field, value); + return NULL; + } + + if (last) + i=last-SVHL_Edict+1; + else + i = 0; + for (; iisfree) + continue; + str = *(string_t*)((char*)ent+ofs); + if (str && !strcmp(SVHL_Globals.stringbase+str, value)) + return ent; + } + return SVHL_Edict; +} +unk GHL_GetEntityIllum(unk){notimp(__LINE__);} +hledict_t *GHL_FindEntityInSphere(hledict_t *last, float *org, float radius) +{ + int i, j; + vec3_t eorg; + hledict_t *ent; + + radius = radius*radius; + + if (last) + i=last-SVHL_Edict+1; + else + i = 0; + for (; iisfree) + continue; + if (!ent->v.solid) + continue; + for (j=0; j<3; j++) + eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5); + if (DotProduct(eorg,eorg) > radius) + continue; + + //its close enough + return ent; + } + return NULL; +} +hledict_t *GHL_FindClientInPVS(hledict_t *ed) +{ + qbyte *viewerpvs; + int best = 0, i; + float bestdist = 99999999; //HL maps are limited in size anyway + float d; + int leafnum; + vec3_t ofs; + hledict_t *other; + + //fixme: we need to track some state + //a different client should be returned each call _per ent_ (so it can be used once per frame) + + viewerpvs = sv.worldmodel->funcs.LeafPVS(sv.worldmodel, sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, ed->v.origin), NULL); + + for (i = 0; i < MAX_CLIENTS; i++) + { + if (svs.clients[i].state == cs_spawned) + { + other = &SVHL_Edict[i+1]; + if (ed == other) + continue; //ignore yourself. + if (svs.clients[i].spectator) + continue; //ignore spectators + + leafnum = sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, other->v.origin)-1;/*pvs is 1 based, leafs are 0 based*/ + if (viewerpvs[leafnum>>3] & (1<<(leafnum&7))) + { + VectorSubtract(ed->v.origin, other->v.origin, ofs); + d = DotProduct(ofs, ofs); + + if (d < bestdist) + { + bestdist = d; + best = i+1; + } + } + } + } + + if (best) + return &SVHL_Edict[best]; + return NULL; +} +unk GHL_EntitiesInPVS(unk){notimp(__LINE__);} +void GHL_MakeVectors(float *angles) +{ + AngleVectors(angles, SVHL_Globals.v_forward, SVHL_Globals.v_right, SVHL_Globals.v_up); +} +void GHL_AngleVectors(float *angles, float *forward, float *right, float *up) +{ + AngleVectors(angles, forward, right, up); +} + +/////////////////////////////////////////////////////////// + +hledict_t *GHL_CreateEntity(void) +{ + int i; + static int spawnnumber; + spawnnumber++; + + for (i = sv.allocated_client_slots; i < SVHL_NumActiveEnts; i++) + { + if (SVHL_Edict[i].isfree) + { + if (SVHL_Edict[i].freetime > sv.time) + continue; + + memset(&SVHL_Edict[i], 0, sizeof(SVHL_Edict[i])); + SVHL_Edict[i].spawnnumber = spawnnumber; + SVHL_Edict[i].v.edict = &SVHL_Edict[i]; + return &SVHL_Edict[i]; + } + } + if (i < MAX_HL_EDICTS) + { + SVHL_NumActiveEnts++; + memset(&SVHL_Edict[i], 0, sizeof(SVHL_Edict[i])); + SVHL_Edict[i].spawnnumber = spawnnumber; + SVHL_Edict[i].v.edict = &SVHL_Edict[i]; + return &SVHL_Edict[i]; + } + SV_Error("Ran out of free edicts"); + return NULL; +} +void GHL_RemoveEntity(hledict_t *ed) +{ + SVHL_UnlinkEdict(ed); + ed->isfree = true; + ed->freetime = sv.time+2; +} +hledict_t *GHL_CreateNamedEntity(string_t name) +{ + void (*spawnfunc)(hlentvars_t *evars); + hledict_t *ed; + ed = GHL_CreateEntity(); + if (!ed) + return NULL; + ed->v.classname = name; + + spawnfunc = (void(*)(hlentvars_t*))GetProcAddress((HINSTANCE)hlgamecode, name+SVHL_Globals.stringbase); + if (spawnfunc) + spawnfunc(&ed->v); + return ed; +} +void *GHL_PvAllocEntPrivateData(hledict_t *ed, long quant) +{ + ed->moddata = Z_Malloc(quant); + return ed->moddata; +} +unk GHL_PvEntPrivateData(unk) +{ + notimp(__LINE__); +} +unk GHL_FreeEntPrivateData(unk) +{ + notimp(__LINE__); +} +unk GHL_GetVarsOfEnt(unk) +{ + notimp(__LINE__); +} +hledict_t *GHL_PEntityOfEntOffset(int ednum) +{ + return (hledict_t *)(ednum + (char*)SVHL_Edict); +} +int GHL_EntOffsetOfPEntity(hledict_t *ed) +{ + return (char*)ed - (char*)SVHL_Edict; +} +int GHL_IndexOfEdict(hledict_t *ed) +{ + return ed - SVHL_Edict; +} +hledict_t *GHL_PEntityOfEntIndex(int idx) +{ + return &SVHL_Edict[idx]; +} +unk GHL_FindEntityByVars(unk) +{ + notimp(__LINE__); +} + +/////////////////////////////////////////////////////// + +unk GHL_MakeStatic(unk){notimp(__LINE__);} +unk GHL_EntIsOnFloor(unk){notimp(__LINE__);} +int GHL_DropToFloor(hledict_t *ed) +{ + vec3_t top; + vec3_t bottom; + trace_t tr; + VectorCopy(ed->v.origin, top); + VectorCopy(ed->v.origin, bottom); + top[2] += 1; + bottom[2] -= 256; + tr = SVHL_Move(top, ed->v.mins, ed->v.maxs, bottom, 0, 0, ed); + VectorCopy(tr.endpos, ed->v.origin); + return tr.fraction != 0 && tr.fraction != 1; +} +int GHL_WalkMove(hledict_t *ed, float yaw, float dist, int mode) +{ + ignore("walkmove"); + return 1; +} +void GHL_SetOrigin(hledict_t *ed, float *neworg) +{ + VectorCopy(neworg, ed->v.origin); + SVHL_LinkEdict(ed, false); +} +void GHL_EmitSound(hledict_t *ed, int chan, char *soundname, float vol, float atten, int flags, int pitch) +{ + SV_StartSound(ed-SVHL_Edict, ed->v.origin, ~0, chan, soundname, vol*255, atten); +} +void GHL_EmitAmbientSound(hledict_t *ed, float *org, char *soundname, float vol, float atten, unsigned int flags, int pitch) +{ + SV_StartSound(0, org, ~0, 0, soundname, vol*255, atten); +} +void GHL_TraceLine(float *start, float *end, int flags, hledict_t *ignore, hltraceresult_t *result) +{ + trace_t t; + + t = SVHL_Move(start, vec3_origin, vec3_origin, end, flags, 0, ignore); + + result->allsolid = t.allsolid; + result->startsolid = t.startsolid; + result->inopen = t.inopen; + result->inwater = t.inwater; + result->fraction = t.fraction; + VectorCopy(t.endpos, result->endpos); + result->planedist = t.plane.dist; + VectorCopy(t.plane.normal, result->planenormal); + result->touched = t.ent; + if (!result->touched) + result->touched = &SVHL_Edict[0]; + result->hitgroup = 0; +} +unk GHL_TraceToss(unk){notimp(__LINE__);} +unk GHL_TraceMonsterHull(unk){notimp(__LINE__);} +void GHL_TraceHull(float *start, float *end, int flags, int hullnum, hledict_t *ignore, hltraceresult_t *result) +{ + trace_t t; + + t = SVHL_Move(start, sv.worldmodel->hulls[hullnum].clip_mins, sv.worldmodel->hulls[hullnum].clip_maxs, end, flags, 0, ignore); + + result->allsolid = t.allsolid; + result->startsolid = t.startsolid; + result->inopen = t.inopen; + result->inwater = t.inwater; + result->fraction = t.fraction; + VectorCopy(t.endpos, result->endpos); + result->planedist = t.plane.dist; + VectorCopy(t.plane.normal, result->planenormal); + result->touched = t.ent; + result->hitgroup = 0; +} +unk GHL_TraceModel(unk){notimp(__LINE__);} +char *GHL_TraceTexture(hledict_t *againstent, vec3_t start, vec3_t end) +{ + trace_t tr; + sv.worldmodel->funcs.Trace(sv.worldmodel, 0, 0, start, end, vec3_origin, vec3_origin, &tr); + return tr.surface->name; +} +unk GHL_TraceSphere(unk){notimp(__LINE__);} +unk GHL_GetAimVector(unk){notimp(__LINE__);} +void GHL_ServerCommand(char *cmd) +{ + Cbuf_AddText(cmd, RESTRICT_PROGS); +} +void GHL_ServerExecute(void) +{ + Cbuf_ExecuteLevel(RESTRICT_PROGS); +} +unk GHL_ClientCommand(unk){notimp(__LINE__);} +unk GHL_ParticleEffect(unk){notimp(__LINE__);} +void GHL_LightStyle(int stylenum, char *stylestr) +{ + PF_applylightstyle(stylenum, stylestr, 7); +} +int GHL_DecalIndex(char *decalname) +{ + Con_Printf("Fixme: precache decal %s\n", decalname); + return 0; +} +int GHL_PointContents(float *org) +{ + return Q1CONTENTS_EMPTY; +} + +int svhl_messagedest; +vec3_t svhl_messageorigin; +hledict_t *svhl_messageent; +void GHL_MessageBegin(int dest, int type, float *org, hledict_t *ent) +{ + svhl_messagedest = dest; + if (org) + VectorCopy(org, svhl_messageorigin); + else + VectorClear(svhl_messageorigin); + svhl_messageent = ent; + + if (sv.multicast.cursize) + { + Con_Printf("MessageBegin called without MessageEnd\n"); + SZ_Clear (&sv.multicast); + } + MSG_WriteByte(&sv.multicast, svcfte_cgamepacket); + MSG_WriteShort(&sv.multicast, 0); + MSG_WriteByte(&sv.multicast, type); +} +void GHL_MessageEnd(unk) +{ + unsigned short len; + client_t *cl; + + if (!sv.multicast.cursize) + { + Con_Printf("MessageEnd called without MessageBegin\n"); + return; + } + + //update the length + len = sv.multicast.cursize - 3; + sv.multicast.data[1] = len&0xff; + sv.multicast.data[2] = len>>8; + + switch(svhl_messagedest) + { + case MSG_BROADCAST: + SZ_Write(&sv.datagram, sv.multicast.data, sv.multicast.cursize); + break; + case MSG_ONE: + cl = &svs.clients[svhl_messageent - SVHL_Edict - 1]; + if (cl->state >= cs_spawned) + { + ClientReliableCheckBlock(cl, sv.multicast.cursize); + ClientReliableWrite_SZ(cl, sv.multicast.data, sv.multicast.cursize); + ClientReliable_FinishWrite(cl); + } + break; + case MSG_ALL: + SZ_Write(&sv.reliable_datagram, sv.multicast.data, sv.multicast.cursize); + break; + case MSG_MULTICAST: + SV_Multicast(svhl_messageorigin, MULTICAST_PVS); + break; + case MSG_MULTICAST+1: + SV_Multicast(svhl_messageorigin, MULTICAST_PHS); + break; + default: + Con_Printf("GHL_MessageEnd: dest type %i not supported\n", svhl_messagedest); + break; + } + + SZ_Clear (&sv.multicast); +} +void GHL_WriteByte(int value) +{ + MSG_WriteByte(&sv.multicast, value); +} +void GHL_WriteChar(int value) +{ + MSG_WriteChar(&sv.multicast, value); +} +void GHL_WriteShort(int value) +{ + MSG_WriteShort(&sv.multicast, value); +} +void GHL_WriteLong(int value) +{ + MSG_WriteLong(&sv.multicast, value); +} +void GHL_WriteAngle(float value) +{ + MSG_WriteAngle8(&sv.multicast, value); +} +void GHL_WriteCoord(float value) +{ + coorddata i = MSG_ToCoord(value, 2); + SZ_Write (&sv.multicast, (void*)&i, 2); +} +void GHL_WriteString(char *string) +{ + MSG_WriteString(&sv.multicast, string); +} +void GHL_WriteEntity(int entnum) +{ + MSG_WriteShort(&sv.multicast, entnum); +} + + +void GHL_AlertMessage(int level, char *fmt, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr, fmt); + vsnprintf (string,sizeof(string)-1, fmt,argptr); + va_end (argptr); + + Con_Printf("%s\n", string); +} +void GHL_EngineFprintf(FILE *f, char *fmt, ...) +{ + SV_Error("Halflife gamecode tried to use EngineFprintf\n"); +} +unk GHL_SzFromIndex(unk){notimp(__LINE__);} +void *GHL_GetModelPtr(hledict_t *ed) +{ +#ifdef SERVERONLY + return NULL; +#else + if (!ed->v.modelindex) + return NULL; + if (!sv.models[ed->v.modelindex]) + sv.models[ed->v.modelindex] = Mod_ForName(sv.strings.model_precache[ed->v.modelindex], false); + return Mod_GetHalfLifeModelData(sv.models[ed->v.modelindex]); +#endif +} +int GHL_RegUserMsg(char *msgname, int msgsize) +{ + //we use 1 as the code to choose others. + if (lastusermessage <= 1) + return -1; + + SV_FlushSignon (); + + //for new clients + MSG_WriteByte(&sv.signon, svcfte_cgamepacket); + MSG_WriteShort(&sv.signon, strlen(msgname)+3); + MSG_WriteByte(&sv.signon, 1); + MSG_WriteByte(&sv.signon, lastusermessage); + MSG_WriteString(&sv.signon, msgname); + + //and if the client is already spawned... + MSG_WriteByte(&sv.reliable_datagram, svcfte_cgamepacket); + MSG_WriteShort(&sv.reliable_datagram, strlen(msgname)+3); + MSG_WriteByte(&sv.reliable_datagram, 1); + MSG_WriteByte(&sv.reliable_datagram, lastusermessage); + MSG_WriteString(&sv.reliable_datagram, msgname); + + return lastusermessage--; +} +unk GHL_AnimationAutomove(unk){notimp(__LINE__);} +unk GHL_GetBonePosition(unk){notimp(__LINE__);} + +hlintptr_t GHL_FunctionFromName(char *name) +{ + return (hlintptr_t)Sys_GetAddressForName(hlgamecode, name); +} +char *GHL_NameForFunction(hlintptr_t function) +{ + return Sys_GetNameForAddress(hlgamecode, (void*)function); +} + +unk GHL_ClientPrintf(unk) +{ +// SV_ClientPrintf( + notimp(__LINE__); +} +void GHL_ServerPrint(char *msg) +{ + Con_Printf("%s", msg); +} +char *GHL_Cmd_Args(void) +{ + return Cmd_Args(); +} +char *GHL_Cmd_Argv(int arg) +{ + return Cmd_Argv(arg); +} +int GHL_Cmd_Argc(unk) +{ + return Cmd_Argc(); +} +unk GHL_GetAttachment(unk){notimp(__LINE__);} +void GHL_CRC32_Init(hlcrc_t *crc) +{ + unsigned short crc16 = *crc; + QCRC_Init(&crc16); + *crc = crc16; +} +void GHL_CRC32_ProcessBuffer(hlcrc_t *crc, qbyte *p, int len) +{ + unsigned short crc16 = *crc; + while(len-->0) + { + QCRC_ProcessByte(&crc16, *p++); + } + *crc = crc16; +} +void GHL_CRC32_ProcessByte(hlcrc_t *crc, qbyte b) +{ + unsigned short crc16 = *crc; + QCRC_ProcessByte(&crc16, b); + *crc = crc16; +} +hlcrc_t GHL_CRC32_Final(hlcrc_t crc) +{ + unsigned short crc16 = crc; + return QCRC_Value(crc16); +} +long GHL_RandomLong(long minv, long maxv) +{ + return minv + frandom()*(maxv-minv); +} +float GHL_RandomFloat(float minv, float maxv) +{ + return minv + frandom()*(maxv-minv); +} +unk GHL_SetView(unk){notimp(__LINE__);} +unk GHL_Time(unk){notimp(__LINE__);} +unk GHL_CrosshairAngle(unk){notimp(__LINE__);} +void *GHL_LoadFileForMe(char *name, int *size_out) +{ + int fsize; + void *fptr; + fsize = FS_LoadFile(name, &fptr); + if (size_out) + *size_out = fsize; + if (fsize == -1) + return NULL; + return fptr; +} +void GHL_FreeFile(void *fptr) +{ + FS_FreeFile(fptr); +} +unk GHL_EndSection(unk){notimp(__LINE__);} +#include +int GHL_CompareFileTime(char *fname1, char *fname2, int *result) +{ + flocation_t loc1, loc2; + struct stat stat1, stat2; + //results: + //1 = f1 is newer + //0 = equal age + //-1 = f2 is newer + //at least I think that's what it means. + *result = 0; + if (!FS_FLocateFile(fname1, FSLFRT_IFFOUND, &loc1) || !FS_FLocateFile(fname2, FSLFRT_IFFOUND, &loc2)) + return 0; + + if (stat(loc1.rawname, &stat1) || stat(loc2.rawname, &stat2)) + return 0; + + if (stat1.st_mtime > stat2.st_mtime) + *result = 1; + else if (stat1.st_mtime < stat2.st_mtime) + *result = -1; + else + *result = 0; + + return 1; +} +void GHL_GetGameDir(char *gamedir) +{ + extern char gamedirfile[]; + //warning: the output buffer size is not specified! + Q_strncpyz(gamedir, gamedirfile, MAX_QPATH); +} +unk GHL_Cvar_RegisterVariable(unk){notimp(__LINE__);} +unk GHL_FadeClientVolume(unk){notimp(__LINE__);} +unk GHL_SetClientMaxspeed(unk){notimp(__LINE__);} +unk GHL_CreateFakeClient(unk){notimp(__LINE__);} +unk GHL_RunPlayerMove(unk){notimp(__LINE__);} +int GHL_NumberOfEntities(void) +{ + return 0; +} +unk GHL_GetInfoKeyBuffer(unk){notimp(__LINE__);} +unk GHL_InfoKeyValue(unk){notimp(__LINE__);} +unk GHL_SetKeyValue(unk){notimp(__LINE__);} +unk GHL_SetClientKeyValue(unk){notimp(__LINE__);} +unk GHL_IsMapValid(unk){notimp(__LINE__);} +unk GHL_StaticDecal(unk){notimp(__LINE__);} +unk GHL_PrecacheGeneric(unk){notimp(__LINE__);} +int GHL_GetPlayerUserId(hledict_t *ed) +{ + unsigned int clnum = (ed - SVHL_Edict) - 1; + if (clnum >= sv.allocated_client_slots) + return -1; + return svs.clients[clnum].userid; +} +unk GHL_BuildSoundMsg(unk){notimp(__LINE__);} + +int GHL_IsDedicatedServer(void) +{ +#ifdef SERVERONLY + return 1; +#else + return qrenderer == QR_NONE; +#endif +} + +hlcvar_t *hlcvar_malloced; +hlcvar_t *hlcvar_stored; +void SVHL_UpdateCvar(cvar_t *var) +{ + if (!var->hlcvar) + return; //nothing to do + var->hlcvar->string = var->string; + var->hlcvar->value = var->value; +} + +void SVHL_FreeCvars(void) +{ + cvar_t *nc; + hlcvar_t *n; + //forget all + while (hlcvar_malloced) + { + n = hlcvar_malloced; + hlcvar_malloced = n->next; + + nc = Cvar_FindVar(n->name); + if (nc) + nc->hlcvar = NULL; + Z_Free(n); + } + + while (hlcvar_stored) + { + n = hlcvar_stored; + hlcvar_stored = n->next; + + nc = Cvar_FindVar(n->name); + if (nc) + nc->hlcvar = NULL; + } +} +void SVHL_FreeCvar(hlcvar_t *var) +{ + cvar_t *nc; + hlcvar_t **ref; + //unlink (free if it was malloced) + + ref = &hlcvar_malloced; + while (*ref) + { + if (*ref == var) + { + (*ref) = (*ref)->next; + + nc = Cvar_FindVar(var->name); + if (nc) + nc->hlcvar = NULL; + Z_Free(var); + return; + } + ref = &(*ref)->next; + } + + ref = &hlcvar_stored; + while (*ref) + { + if (*ref == var) + { + (*ref) = (*ref)->next; + + nc = Cvar_FindVar(var->name); + if (nc) + nc->hlcvar = NULL; + return; + } + ref = &(*ref)->next; + } +} + +hlcvar_t *GHL_CVarGetPointer(char *varname) +{ + cvar_t *var; + hlcvar_t *hlvar; + var = Cvar_Get(varname, "", 0, "HalfLife"); + if (!var) + { + Con_Printf("Not giving cvar \"%s\" to game\n", varname); + return NULL; + } + hlvar = var->hlcvar; + if (!hlvar) + { + hlvar = var->hlcvar = Z_Malloc(sizeof(hlcvar_t)); + hlvar->name = var->name; + hlvar->string = var->string; + hlvar->value = var->value; + + hlvar->next = hlcvar_malloced; + hlcvar_malloced = hlvar; + } + return hlvar; +} +void GHL_CVarRegister(hlcvar_t *hlvar) +{ + cvar_t *var; + var = Cvar_Get(hlvar->name, hlvar->string, 0, "HalfLife"); + if (!var) + { + Con_Printf("Not giving cvar \"%s\" to game\n", hlvar->name); + return; + } + if (var->hlcvar) + { + SVHL_FreeCvar(var->hlcvar); + + hlvar->next = hlcvar_stored; + hlcvar_stored = hlvar; + } + var->hlcvar = hlvar; +} +float GHL_CVarGetFloat(char *vname) +{ + cvar_t *var = Cvar_FindVar(vname); + if (var) + return var->value; + Con_Printf("cvar %s does not exist\n", vname); + return 0; +} +char *GHL_CVarGetString(char *vname) +{ + cvar_t *var = Cvar_FindVar(vname); + if (var) + return var->string; + Con_Printf("cvar %s does not exist\n", vname); + return ""; +} +void GHL_CVarSetFloat(char *vname, float value) +{ + cvar_t *var = Cvar_FindVar(vname); + if (var) + Cvar_SetValue(var, value); + else + Con_Printf("cvar %s does not exist\n", vname); +} +void GHL_CVarSetString(char *vname, char *value) +{ + cvar_t *var = Cvar_FindVar(vname); + if (var) + Cvar_Set(var, value); + else + Con_Printf("cvar %s does not exist\n", vname); +} + +unk GHL_GetPlayerWONId(unk){notimp(__LINE__);} +unk GHL_Info_RemoveKey(unk){notimp(__LINE__);} +unk GHL_GetPhysicsKeyValue(unk){notimp(__LINE__);} +unk GHL_SetPhysicsKeyValue(unk){notimp(__LINE__);} +unk GHL_GetPhysicsInfoString(unk){notimp(__LINE__);} +unsigned short GHL_PrecacheEvent(int eventtype, char *eventname) +{ + Con_Printf("Fixme: GHL_PrecacheEvent: %s\n", eventname); + return 0; +} +void GHL_PlaybackEvent(int flags, hledict_t *ent, unsigned short eventidx, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2) +{ + ignore("GHL_PlaybackEvent not implemented"); +} +unk GHL_SetFatPVS(unk){notimp(__LINE__);} +unk GHL_SetFatPAS(unk){notimp(__LINE__);} +unk GHL_CheckVisibility(unk){notimp(__LINE__);} +unk GHL_DeltaSetField(unk){notimp(__LINE__);} +unk GHL_DeltaUnsetField(unk){notimp(__LINE__);} +unk GHL_DeltaAddEncoder(unk){notimp(__LINE__);} +unk GHL_GetCurrentPlayer(unk){notimp(__LINE__);} +unk GHL_CanSkipPlayer(unk){notimp(__LINE__);} +unk GHL_DeltaFindField(unk){notimp(__LINE__);} +unk GHL_DeltaSetFieldByIndex(unk){notimp(__LINE__);} +unk GHL_DeltaUnsetFieldByIndex(unk){notimp(__LINE__);} +unk GHL_SetGroupMask(unk){notimp(__LINE__);} +unk GHL_CreateInstancedBaseline(unk){notimp(__LINE__);} +unk GHL_Cvar_DirectSet(unk){notimp(__LINE__);} +unk GHL_ForceUnmodified(unk){notimp(__LINE__);} +unk GHL_GetPlayerStats(unk){notimp(__LINE__);} +unk GHL_AddServerCommand(unk){notimp(__LINE__);} +unk GHL_Voice_GetClientListening(unk){notimp(__LINE__);} +qboolean GHL_Voice_SetClientListening(int listener, int sender, int shouldlisten) +{ + return false; +} +unk GHL_GetPlayerAuthId(unk){notimp(__LINE__);} +unk GHL_SequenceGet(unk){notimp(__LINE__);} +unk GHL_SequencePickSentence(unk){notimp(__LINE__);} +unk GHL_GetFileSize(unk){notimp(__LINE__);} +unk GHL_GetApproxWavePlayLen(unk){notimp(__LINE__);} +unk GHL_IsCareerMatch(unk){notimp(__LINE__);} +unk GHL_GetLocalizedStringLength(unk){notimp(__LINE__);} +unk GHL_RegisterTutorMessageShown(unk){notimp(__LINE__);} +unk GHL_GetTimesTutorMessageShown(unk){notimp(__LINE__);} +unk GHL_ProcessTutorMessageDecayBuffer(unk){notimp(__LINE__);} +unk GHL_ConstructTutorMessageDecayBuffer(unk){notimp(__LINE__);} +unk GHL_ResetTutorMessageDecayData(unk){notimp(__LINE__);} +unk GHL_QueryClientCvarValue(unk){notimp(__LINE__);} +unk GHL_QueryClientCvarValue2(unk){notimp(__LINE__);} + + + + +//==================================================================================================== + + + + + +SVHL_Builtins_t SVHL_Builtins = +{ + GHL_PrecacheModel, + GHL_PrecacheSound, + GHL_SetModel, + GHL_ModelIndex, + GHL_ModelFrames, + GHL_SetSize, + GHL_ChangeLevel, + GHL_GetSpawnParms, + GHL_SaveSpawnParms, + GHL_VecToYaw, + GHL_VecToAngles, + GHL_MoveToOrigin, + GHL_ChangeYaw, + GHL_ChangePitch, + GHL_FindEntityByString, + GHL_GetEntityIllum, + GHL_FindEntityInSphere, + GHL_FindClientInPVS, + GHL_EntitiesInPVS, + GHL_MakeVectors, + GHL_AngleVectors, + GHL_CreateEntity, + GHL_RemoveEntity, + GHL_CreateNamedEntity, + GHL_MakeStatic, + GHL_EntIsOnFloor, + GHL_DropToFloor, + GHL_WalkMove, + GHL_SetOrigin, + GHL_EmitSound, + GHL_EmitAmbientSound, + GHL_TraceLine, + GHL_TraceToss, + GHL_TraceMonsterHull, + GHL_TraceHull, + GHL_TraceModel, + GHL_TraceTexture, + GHL_TraceSphere, + GHL_GetAimVector, + GHL_ServerCommand, + GHL_ServerExecute, + GHL_ClientCommand, + GHL_ParticleEffect, + GHL_LightStyle, + GHL_DecalIndex, + GHL_PointContents, + GHL_MessageBegin, + GHL_MessageEnd, + GHL_WriteByte, + GHL_WriteChar, + GHL_WriteShort, + GHL_WriteLong, + GHL_WriteAngle, + GHL_WriteCoord, + GHL_WriteString, + GHL_WriteEntity, + GHL_CVarRegister, + GHL_CVarGetFloat, + GHL_CVarGetString, + GHL_CVarSetFloat, + GHL_CVarSetString, + GHL_AlertMessage, + GHL_EngineFprintf, + GHL_PvAllocEntPrivateData, + GHL_PvEntPrivateData, + GHL_FreeEntPrivateData, + GHL_SzFromIndex, + GHL_AllocString, + GHL_GetVarsOfEnt, + GHL_PEntityOfEntOffset, + GHL_EntOffsetOfPEntity, + GHL_IndexOfEdict, + GHL_PEntityOfEntIndex, + GHL_FindEntityByVars, + GHL_GetModelPtr, + GHL_RegUserMsg, + GHL_AnimationAutomove, + GHL_GetBonePosition, + GHL_FunctionFromName, + GHL_NameForFunction, + GHL_ClientPrintf, + GHL_ServerPrint, + GHL_Cmd_Args, + GHL_Cmd_Argv, + GHL_Cmd_Argc, + GHL_GetAttachment, + GHL_CRC32_Init, + GHL_CRC32_ProcessBuffer, + GHL_CRC32_ProcessByte, + GHL_CRC32_Final, + GHL_RandomLong, + GHL_RandomFloat, + GHL_SetView, + GHL_Time, + GHL_CrosshairAngle, + GHL_LoadFileForMe, + GHL_FreeFile, + GHL_EndSection, + GHL_CompareFileTime, + GHL_GetGameDir, + GHL_Cvar_RegisterVariable, + GHL_FadeClientVolume, + GHL_SetClientMaxspeed, + GHL_CreateFakeClient, + GHL_RunPlayerMove, + GHL_NumberOfEntities, + GHL_GetInfoKeyBuffer, + GHL_InfoKeyValue, + GHL_SetKeyValue, + GHL_SetClientKeyValue, + GHL_IsMapValid, + GHL_StaticDecal, + GHL_PrecacheGeneric, + GHL_GetPlayerUserId, + GHL_BuildSoundMsg, + GHL_IsDedicatedServer, +#if HALFLIFE_API_VERSION > 138 + GHL_CVarGetPointer, + GHL_GetPlayerWONId, + GHL_Info_RemoveKey, + GHL_GetPhysicsKeyValue, + GHL_SetPhysicsKeyValue, + GHL_GetPhysicsInfoString, + GHL_PrecacheEvent, + GHL_PlaybackEvent, + GHL_SetFatPVS, + GHL_SetFatPAS, + GHL_CheckVisibility, + GHL_DeltaSetField, + GHL_DeltaUnsetField, + GHL_DeltaAddEncoder, + GHL_GetCurrentPlayer, + GHL_CanSkipPlayer, + GHL_DeltaFindField, + GHL_DeltaSetFieldByIndex, + GHL_DeltaUnsetFieldByIndex, + GHL_SetGroupMask, + GHL_CreateInstancedBaseline, + GHL_Cvar_DirectSet, + GHL_ForceUnmodified, + GHL_GetPlayerStats, + GHL_AddServerCommand, + GHL_Voice_GetClientListening, + GHL_Voice_SetClientListening, + GHL_GetPlayerAuthId, + GHL_SequenceGet, + GHL_SequencePickSentence, + GHL_GetFileSize, + GHL_GetApproxWavePlayLen, + GHL_IsCareerMatch, + GHL_GetLocalizedStringLength, + GHL_RegisterTutorMessageShown, + GHL_GetTimesTutorMessageShown, + GHL_ProcessTutorMessageDecayBuffer, + GHL_ConstructTutorMessageDecayBuffer, + GHL_ResetTutorMessageDecayData, + GHL_QueryClientCvarValue, + GHL_QueryClientCvarValue2, +#endif + + 0xdeadbeef +}; + +void SV_ReadLibListDotGam(void) +{ + char key[1024]; + char value[1024]; + char *file; + char *s; + + Info_SetValueForStarKey(svs.info, "*gamedll", "", sizeof(svs.info)); + Info_SetValueForStarKey(svs.info, "*cldll", "", sizeof(svs.info)); + + file = COM_LoadTempFile("liblist.gam"); + if (!file) + return; + + Info_SetValueForStarKey(svs.info, "*cldll", "1", sizeof(svs.info)); + + while ((file = COM_ParseOut(file, key, sizeof(key)))) + { + file = COM_ParseOut(file, value, sizeof(value)); + + while((s = strchr(value, '\\'))) + *s = '/'; + + if (!strcmp(key, "gamedll" +#ifdef __linux__ + "_linux" +#endif + )) + Info_SetValueForStarKey(svs.info, "*gamedll", value, sizeof(svs.info)); + if (!strcmp(key, "cldll")) + Info_SetValueForStarKey(svs.info, "*cldll", atoi(value)?"1":"", sizeof(svs.info)); + } +} + +int SVHL_InitGame(void) +{ + char *gamedll; + char *path; + char fullname[MAX_OSPATH]; + void (*GiveFnptrsToDll) (funcs, globals); + int (*GetEntityAPI)(SVHL_GameFuncs_t *pFunctionTable, int apivers); + + dllfunction_t hlgamefuncs[] = + { + {(void**)&GiveFnptrsToDll, "GiveFnptrsToDll"}, + {(void**)&GetEntityAPI, "GetEntityAPI"}, + {NULL, NULL} + }; + + if (sizeof(long) != sizeof(void*)) + { + Con_Printf("sizeof(long)!=sizeof(ptr): Cannot run halflife gamecode on this platform\n"); + return 0; + } + + SV_ReadLibListDotGam(); + + if (hlgamecode) + { + SVHL_Edict = Hunk_Alloc(sizeof(*SVHL_Edict) * MAX_HL_EDICTS); + SVHL_Globals.maxentities = MAX_HL_EDICTS; //I think this is correct + return 1; + } + + gamedll = Info_ValueForKey(svs.info, "*gamedll"); + path = NULL; + while((path = COM_NextPath (path))) + { + if (!path) + return 0; // couldn't find one anywhere + snprintf (fullname, sizeof(fullname), "%s/%s", path, gamedll); + hlgamecode = Sys_LoadLibrary(fullname, hlgamefuncs); + if (hlgamecode) + break; + } + + if (!hlgamecode) + return 0; + + SVHL_Edict = Hunk_Alloc(sizeof(*SVHL_Edict) * MAX_HL_EDICTS); + SVHL_Globals.maxentities = MAX_HL_EDICTS; //I think this is correct + GiveFnptrsToDll(&SVHL_Builtins, &SVHL_Globals); + + if (!GetEntityAPI(&SVHL_GameFuncs, HALFLIFE_API_VERSION)) + { + Con_Printf(CON_ERROR "Error: %s is incompatible\n", fullname); + Sys_CloseLibrary(hlgamecode); + return 0; + } + + SVHL_GameFuncs.GameDLLInit(); + return 1; +} + +void SVHL_SaveLevelCache(void) +{ + +} + +void SVHL_SetupGame(void) +{ + lastusermessage = 255; + //called on new map +} + +void SVHL_SpawnEntities(char *entstring) +{ + char key[256]; + char value[1024]; + char classname[1024]; + hlfielddef_t fdef; + hledict_t *ed, *world; + extern cvar_t coop; //who'd have thought it, eh? + char *ts; + int i; + + //initialise globals + SVHL_Globals.stringbase = ""; + SVHL_Globals.maxclients = MAX_CLIENTS; + SVHL_Globals.deathmatch = deathmatch.value; + SVHL_Globals.coop = coop.value; + SVHL_Globals.serverflags = 0; + SVHL_Globals.mapname = GHL_AllocString(sv.name); + + SVHL_NumActiveEnts = 0; + + + //touch world. + world = GHL_CreateNamedEntity(GHL_AllocString("worldspawn")); + world->v.solid = SOLID_BSP; + GHL_SetModel(world, sv.modelname); + + //spawn player ents + sv.allocated_client_slots = 0; + for (i = 0; i < SVHL_Globals.maxclients; i++) + { + sv.allocated_client_slots++; + ed = GHL_CreateNamedEntity(GHL_AllocString("player")); + } + for (i = 0; i < sv.allocated_client_slots; i++) + { + SVHL_Edict[i].isfree = true; + } + sv.allocated_client_slots = i; + + //precache the inline models (and touch them). + sv.strings.model_precache[0] = ""; + sv.strings.model_precache[1] = sv.modelname; //the qvm doesn't have access to this array + for (i=1 ; inumsubmodels ; i++) + { + sv.strings.model_precache[1+i] = localmodels[i]; + sv.models[i+1] = Mod_ForName (localmodels[i], false); + } + + while (entstring) + { + entstring = COM_ParseOut(entstring, key, sizeof(key)); + if (strcmp(key, "{")) + break; + + *classname = 0; + + ts = entstring; + while (ts) + { + ts = COM_ParseOut(ts, key, sizeof(key)); + if (!strcmp(key, "}")) + break; + ts = COM_ParseOut(ts, value, sizeof(value)); + + if (!strcmp(key, "classname")) + { + memcpy(classname, value, strlen(value)+1); + break; + } + } + + if (world) + { + if (strcmp(classname, "worldspawn")) + SV_Error("first entity is not worldspawn"); + ed = world; + world = NULL; + } + else + ed = GHL_CreateNamedEntity(GHL_AllocString(classname)); + + while (entstring) + { + entstring = COM_ParseOut(entstring, key, sizeof(key)); + if (!strcmp(key, "}")) + break; + entstring = COM_ParseOut(entstring, value, sizeof(value)); + + if (*key == '_') + continue; + + if (!strcmp(key, "classname")) + memcpy(classname, value, strlen(value)+1); + + fdef.handled = false; + if (!*classname) + fdef.classname = NULL; + else + fdef.classname = classname; + fdef.key = key; + fdef.value = value; + SVHL_GameFuncs.DispatchKeyValue(ed, &fdef); + if (!fdef.handled) + { + if (!strcmp(key, "angle")) + { + float a = atof(value); + sprintf(value, "%f %f %f", 0.0f, a, 0.0f); + strcpy(key, "angles"); + SVHL_GameFuncs.DispatchKeyValue(ed, &fdef); + } + if (!fdef.handled) + Con_Printf("Bad field on %s, %s\n", classname, key); + } + } + SVHL_GameFuncs.DispatchSpawn(ed); + } + + SVHL_GameFuncs.ServerActivate(SVHL_Edict, SVHL_NumActiveEnts, sv.allocated_client_slots); +} + +void SVHL_ShutdownGame(void) +{ + SVHL_FreeCvars(); + + //gametype changed, or server shutdown + Sys_CloseLibrary(hlgamecode); + hlgamecode = NULL; + + SVHL_Edict = NULL; + memset(&SVHL_Globals, 0, sizeof(SVHL_Globals)); + memset(&SVHL_GameFuncs, 0, sizeof(SVHL_GameFuncs)); + memset(&SVHL_GameFuncsEx, 0, sizeof(SVHL_GameFuncsEx)); +} + +qboolean HLSV_ClientCommand(client_t *client) +{ + hledict_t *ed = &SVHL_Edict[client - svs.clients + 1]; + if (!hlgamecode) + return false; + SVHL_GameFuncs.ClientCommand(ed); + return true; +} + +qboolean SVHL_ClientConnect(client_t *client, netadr_t adr, char rejectmessage[128]) +{ + char ipadr[256]; + NET_AdrToString(ipadr, sizeof(ipadr), adr); + strcpy(rejectmessage, "Rejected by gamecode"); + + if (!SVHL_GameFuncs.ClientConnect(&SVHL_Edict[client-svs.clients+1], client->name, ipadr, rejectmessage)) + return false; + + return true; +} + +void SVHL_BuildStats(client_t *client, int *si, float *sf, char **ss) +{ + hledict_t *ed = &SVHL_Edict[client - svs.clients + 1]; + + si[STAT_HEALTH] = ed->v.health; + si[STAT_VIEWHEIGHT] = ed->v.view_ofs[2]; + si[STAT_WEAPON] = SV_ModelIndex(SVHL_Globals.stringbase+ed->v.vmodelindex); + si[STAT_ITEMS] = ed->v.weapons; +} + +void SVHL_PutClientInServer(client_t *client) +{ + hledict_t *ed = &SVHL_Edict[client - svs.clients + 1]; + ed->isfree = false; + SVHL_GameFuncs.ClientPutInServer(&SVHL_Edict[client-svs.clients+1]); +} + +void SVHL_DropClient(client_t *drop) +{ + hledict_t *ed = &SVHL_Edict[drop - svs.clients + 1]; + SVHL_GameFuncs.ClientDisconnect(&SVHL_Edict[drop-svs.clients+1]); + ed->isfree = true; +} + +void SVHL_RunCmdR(hledict_t *ed, usercmd_t *ucmd) +{ + int i; + hledict_t *other; +extern cvar_t temp1; +extern vec3_t player_mins; +extern vec3_t player_maxs; + + // chop up very long commands + if (ucmd->msec > 50) + { + usercmd_t cmd = *ucmd; + + cmd.msec = ucmd->msec/2; + SVHL_RunCmdR (ed, &cmd); + cmd.msec = ucmd->msec/2 + (ucmd->msec&1); //give them back their msec. + cmd.impulse = 0; + SVHL_RunCmdR (ed, &cmd); + return; + } + + host_frametime = ucmd->msec * 0.001; + host_frametime *= sv.gamespeed; + if (host_frametime > 0.1) + host_frametime = 0.1; + + pmove.cmd = *ucmd; + pmove.pm_type = temp1.value;//PM_NORMAL;//FLY; + pmove.numphysent = 1; + pmove.physents[0].model = sv.worldmodel; + pmove.physents[0].info = 0; + + if (ed->v.flags & (1<<24)) + { + pmove.cmd.forwardmove = 0; + pmove.cmd.sidemove = 0; + pmove.cmd.upmove = 0; + } + + { + hledict_t *list[256]; + int count; + physent_t *pe; + vec3_t pmove_mins, pmove_maxs; + + for (i = 0; i < 3; i++) + { + pmove_mins[i] = pmove.origin[i] - 256; + pmove_maxs[i] = pmove.origin[i] + 256; + } + + count = SVHL_AreaEdicts(pmove_mins, pmove_maxs, list, sizeof(list)/sizeof(list[0])); + for (i = 0; i < count; i++) + { + other = list[i]; + if (other == ed) + continue; + if (other->v.owner == ed) + continue; + if (other->v.flags & (1<<23)) //has monsterclip flag set, so ignore it + continue; + + pe = &pmove.physents[pmove.numphysent]; + if (other->v.modelindex) + { + pe->model = sv.models[other->v.modelindex]; + if (pe->model && pe->model->type != mod_brush) + pe->model = NULL; + } + else + pe->model = NULL; + pmove.numphysent++; + pe->info = other - SVHL_Edict; + VectorCopy(other->v.origin, pe->origin); + VectorCopy(other->v.mins, pe->mins); + VectorCopy(other->v.maxs, pe->maxs); + VectorCopy(other->v.angles, pe->angles); + + if (other->v.solid == SOLID_NOT || other->v.solid == SOLID_TRIGGER) + pe->nonsolid = true; + else + pe->nonsolid = false; + + switch(other->v.skin) + { + case Q1CONTENTS_EMPTY: + pe->forcecontentsmask = FTECONTENTS_EMPTY; + break; + case Q1CONTENTS_SOLID: + pe->forcecontentsmask = FTECONTENTS_SOLID; + break; + case Q1CONTENTS_WATER: + pe->forcecontentsmask = FTECONTENTS_WATER; + break; + case Q1CONTENTS_SLIME: + pe->forcecontentsmask = FTECONTENTS_SLIME; + break; + case Q1CONTENTS_LAVA: + pe->forcecontentsmask = FTECONTENTS_LAVA; + break; + case Q1CONTENTS_SKY: + pe->forcecontentsmask = FTECONTENTS_SKY; + break; + case -16: + pe->forcecontentsmask = FTECONTENTS_LADDER; + break; + default: + pe->forcecontentsmask = 0; + break; + } + } + } + + VectorCopy(ed->v.mins, player_mins); + VectorCopy(ed->v.maxs, player_maxs); + + VectorCopy(ed->v.origin, pmove.origin); + VectorCopy(ed->v.velocity, pmove.velocity); + if (ed->v.flags & (1<<22)) + { + VectorCopy(ed->v.basevelocity, pmove.basevelocity); + } + else + VectorClear(pmove.basevelocity); + + PM_PlayerMove(sv.gamespeed); + + VectorCopy(pmove.origin, ed->v.origin); + VectorCopy(pmove.velocity, ed->v.velocity); + + if (pmove.onground) + { + ed->v.flags |= FL_ONGROUND; + ed->v.groundentity = &SVHL_Edict[pmove.physents[pmove.groundent].info]; + } + else + ed->v.flags &= ~FL_ONGROUND; + + for (i = 0; i < pmove.numtouch; i++) + { + other = &SVHL_Edict[pmove.physents[pmove.touchindex[i]].info]; + SVHL_GameFuncs.DispatchTouch(other, ed); + } + + SVHL_LinkEdict(ed, true); +} + +void SVHL_RunCmd(client_t *cl, usercmd_t *ucmd) +{ + hledict_t *ed = &SVHL_Edict[cl - svs.clients + 1]; + +#if HALFLIFE_API_VERSION >= 140 + ed->v.buttons = ucmd->buttons; +#else + //assume they're not running halflife cgame + ed->v.buttons = 0; + + if (ucmd->buttons & 1) + ed->v.buttons |= (1<<0); //shoot + if (ucmd->buttons & 2) + ed->v.buttons |= (1<<1); //jump + if (ucmd->buttons & 8) + ed->v.buttons |= (1<<2); //duck + if (ucmd->forwardmove > 0) + ed->v.buttons |= (1<<3); //forward + if (ucmd->forwardmove < 0) + ed->v.buttons |= (1<<4); //back + if (ucmd->buttons & 4) + ed->v.buttons |= (1<<5); //use + //ed->v.buttons |= (1<<6); //cancel + //ed->v.buttons |= (1<<7); //turn left + //ed->v.buttons |= (1<<8); //turn right + if (ucmd->sidemove > 0) + ed->v.buttons |= (1<<9); //move left + if (ucmd->sidemove < 0) + ed->v.buttons |= (1<<10); //move right + //ed->v.buttons |= (1<<11); //shoot2 + //ed->v.buttons |= (1<<12); //run + if (ucmd->buttons & 16) + ed->v.buttons |= (1<<13); //reload + //ed->v.buttons |= (1<<14); //alt1 + //ed->v.buttons |= (1<<15); //alt2 +#endif + + if (ucmd->impulse) + ed->v.impulse = ucmd->impulse; + ed->v.v_angle[0] = SHORT2ANGLE(ucmd->angles[0]); + ed->v.v_angle[1] = SHORT2ANGLE(ucmd->angles[1]); + ed->v.v_angle[2] = SHORT2ANGLE(ucmd->angles[2]); + + ed->v.angles[0] = 0; + ed->v.angles[1] = SHORT2ANGLE(ucmd->angles[1]); + ed->v.angles[2] = SHORT2ANGLE(ucmd->angles[2]); + + SVHL_GameFuncs.PlayerPreThink(ed); + SVHL_RunCmdR(ed, ucmd); + + if (ed->v.nextthink && ed->v.nextthink < sv.time) + { + ed->v.nextthink = 0; + SVHL_GameFuncs.DispatchThink(ed); + } + + SVHL_GameFuncs.PlayerPostThink(ed); +} + + +void SVHL_RunPlayerCommand(client_t *cl, usercmd_t *oldest, usercmd_t *oldcmd, usercmd_t *newcmd) +{ + hledict_t *e = &SVHL_Edict[cl - svs.clients + 1]; + + SVHL_Globals.time = sv.time; + if (net_drop < 20) + { + while (net_drop > 2) + { + SVHL_RunCmd (cl, &cl->lastcmd); + net_drop--; + } + if (net_drop > 1) + SVHL_RunCmd (cl, oldest); + if (net_drop > 0) + SVHL_RunCmd (cl, oldcmd); + } + SVHL_RunCmd (cl, newcmd); +} + +void SVHL_Snapshot_Build(client_t *client, packet_entities_t *pack, qbyte *pvs, edict_t *clent, qboolean ignorepvs) +{ + hledict_t *e; + entity_state_t *s; + int i; + + pack->servertime = sv.time; + pack->num_entities = 0; + + for (i = 1; i < MAX_HL_EDICTS; i++) + { + e = &SVHL_Edict[i]; + if (!e) + break; + if (e->isfree) + continue; + + if (!e->v.modelindex || !e->v.model) + continue; + if (e->v.effects & 128) + continue; + + if (pack->num_entities == pack->max_entities) + break; + + s = &pack->entities[pack->num_entities++]; + + s->number = i; + s->modelindex = e->v.modelindex; + s->frame = e->v.sequence1; + s->effects = e->v.effects; + s->skinnum = e->v.skin; + VectorCopy(e->v.angles, s->angles); + VectorCopy(e->v.origin, s->origin); + } +} + +void SVHL_Snapshot_SetupPVS(client_t *client) +{ +} + +#endif diff --git a/engine/server/svhl_gcapi.h b/engine/server/svhl_gcapi.h new file mode 100644 index 000000000..7bc7561b0 --- /dev/null +++ b/engine/server/svhl_gcapi.h @@ -0,0 +1,572 @@ +//#define HALFLIFE_API_VERSION 138 +#define HALFLIFE_API_VERSION 140 + +typedef long hllong; //long is 64bit on amd64+linux, not sure that's what valve meant, but lets keep it for compatibility. +typedef struct hledict_s hledict_t; +typedef unsigned long hlintptr_t; //this may be problematic. CRestore::ReadField needs a fix. Or 20. +typedef unsigned long hlcrc_t; //supposed to be 32bit... *sigh* + +typedef struct +{ + int allsolid; + int startsolid; + int inopen; + int inwater; + float fraction; + vec3_t endpos; + float planedist; + vec3_t planenormal; + hledict_t *touched; + int hitgroup; +} hltraceresult_t; + +#if HALFLIFE_API_VERSION <= 138 +typedef struct +{ + int etype; + int number; + int flags; + vec3_t origin; + vec3_t angles; + int modelindex; + int sequence1; + float frame; + int colourmap; + short skin; + short solid; + int effects; + float scale; + int rendermode; + int renderamt; + int rendercolour; + int renderfx; + int movetype; + float frametime; + float framerate; + int body; + qbyte controller[4]; + qbyte blending[2]; + short padding; + vec3_t velocity; + vec3_t mins; + vec3_t maxs; + int aiment; +} hlbaseline_t; +#endif + +typedef struct +{ + string_t classname; + string_t globalname; + + vec3_t origin; + vec3_t oldorigin; + vec3_t velocity; +vec3_t basevelocity; +vec3_t clbasevelocity; + + vec3_t movedir; + + vec3_t angles; + vec3_t avelocity; + vec3_t punchangles; + vec3_t v_angle; + +#if HALFLIFE_API_VERSION > 138 +vec3_t endpos; +vec3_t startpos; +float impacttime; +float starttime; +#endif + + int fixangle; + + float ideal_pitch; + float pitch_speed; + float ideal_yaw; + float yaw_speed; + + + int modelindex; + string_t model; +int vmodelindex; +int vwmodelindex; + + vec3_t absmin; + vec3_t absmax; + vec3_t mins; + vec3_t maxs; + vec3_t size; + + float ltime; + float nextthink; + int movetype; + int solid; + + int skin; +int body; + int effects; + +float gravity; +float friction; + +int light_level; + +int sequence1; +int sequence2; + float frame; +float framestarttime; +float framerate; +qbyte controller[4]; +qbyte blending[2]; +float scale; + +int rendermode; +float renderamt; +vec3_t rendercolour; +int renderfx; + + float health; + float frags; +int weapons; + float takedamage; + int deadflag; + vec3_t view_ofs; + +int buttons; + int impulse; + + hledict_t *chain; + hledict_t *dmg_inflictor; + hledict_t *enemy; + hledict_t *aiment; + hledict_t *owner; + hledict_t *groundentity; + + + int spawnflags; + int flags; + + int colormap; + int team; + + float max_health; + float teleport_time; + float armortype; + float armorvalue; + int waterlevel; + int watertype; + + string_t target; + string_t targetname; + string_t netname; + string_t message; //WARNING: hexen2 uses a float and not a string + + float dmg_take; + float dmg_save; + float dmg; + float dmg_time; + + string_t noise; + string_t noise1; + string_t noise2; + string_t noise3; + +float speed; +float air_finished; +float pain_finished; +float radsuit_finished; + +hledict_t *edict; +#if HALFLIFE_API_VERSION > 138 +int playerclass; +float maxspeed; +float fov; +int weaponanim; +int msec; +int ducking; +int timestepsound; +int swimtime; +int ducktime; +int stepleft; +float fallvelocity; +int gamestate; +int oldbuttons; +int groupinfo; + +int customi0; +int customi1; +int customi2; +int customi3; +float customf0; +float customf1; +float customf2; +float customf3; +vec3_t customv0; +vec3_t customv1; +vec3_t customv2; +vec3_t customv3; +hledict_t *custome0; +hledict_t *custome1; +hledict_t *custome2; +hledict_t *custome3; +#endif +} hlentvars_t; + +struct hledict_s +{ + qboolean isfree; + int spawnnumber; + link_t area; // linked to a division node or leaf + +#if HALFLIFE_API_VERSION > 138 + int headnode; + int num_leafs; +#define HLMAX_ENT_LEAFS 48 + short leafnums[HLMAX_ENT_LEAFS]; +#else + int num_leafs; +#define HLMAX_ENT_LEAFS 24 + short leafnums[HLMAX_ENT_LEAFS]; + + hlbaseline_t baseline; +#endif + + float freetime; // sv.time when the object was freed + + void *moddata; + hlentvars_t v; +}; + +#define unk void +/* +#define FCVAR_ARCHIVE 1 // set to cause it to be saved to vars.rc +#define FCVAR_USERINFO 2 // changes the client's info string +#define FCVAR_SERVERINFO 4 // notifies players when changed +#define FCVAR_SERVERDLL 8 // defined by external DLL +#define FCVAR_CLIENTDLL 16 // defined by the client dll +#define HLCVAR_PROTECTED 32 // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value +#define HLCVAR_SPONLY 64 // This cvar cannot be changed by clients connected to a multiplayer server. +*/ +typedef struct hlcvar_s +{ + char *name; + char *string; + int flags; + float value; + struct hlcvar_s *next; +} hlcvar_t; + +typedef struct +{ + char *classname; + char *key; + char *value; + hllong handled; +} hlfielddef_t; + + + +typedef struct +{ +// int self; +// int other; +// int world; + float time; + float frametime; + float force_retouch; + string_t mapname; +string_t startspot; + float deathmatch; + float coop; + float teamplay; + float serverflags; +// float total_secrets; +// float total_monsters; + float found_secrets; +// float killed_monsters; +// float parms1, parm2, parm3, parm4, parm; + vec3_t v_forward; + vec3_t v_up; + vec3_t v_right; + float trace_allsolid; + float trace_startsolid; + float trace_fraction; + vec3_t trace_endpos; + vec3_t trace_plane_normal; + float trace_plane_dist; + int trace_ent; + float trace_inopen; + float trace_inwater; +int trace_hitgroup; +int trace_flags; + int msg_entity; +int audiotrack; +int maxclients; +int maxentities; + +char *stringbase; +void *savedata; +vec3_t landmark; +//43... +} SVHL_Globals_t; + + + + +//http://metamod.org/dllapi_notes.html +typedef struct +{ + void (*GameDLLInit)(void); + int (*DispatchSpawn)(hledict_t *ed); + void (*DispatchThink)(hledict_t *ed); + unk (*DispatchUse)(unk); + void (*DispatchTouch)(hledict_t *e1, hledict_t *e2); + void (*DispatchBlocked)(hledict_t *self, hledict_t *other); + void (*DispatchKeyValue)(hledict_t *ed, hlfielddef_t *fdef); + unk (*DispatchSave)(unk); + unk (*DispatchRestore)(unk); + unk (*DispatchObjectCollsionBox)(unk); + unk (*SaveWriteFields)(unk); + unk (*SaveReadFields)(unk); + unk (*SaveGlobalState)(unk); + unk (*RestoreGlobalState)(unk); + unk (*ResetGlobalState)(unk); + qboolean (*ClientConnect)(hledict_t *ed, char *name, char *ip, char reject[128]); + void (*ClientDisconnect)(hledict_t *ed); + void (*ClientKill)(hledict_t *ed); + void (*ClientPutInServer)(hledict_t *ed); + void (*ClientCommand)(hledict_t *ed); + unk (*ClientUserInfoChanged)(unk); + void (*ServerActivate)(hledict_t *edictlist, int numedicts, int numplayers); +#if HALFLIFE_API_VERSION > 138 + unk (*ServerDeactivate)(unk); +#endif + void (*PlayerPreThink)(hledict_t *ed); + void (*PlayerPostThink)(hledict_t *ed); + unk (*StartFrame)(unk); + unk (*ParmsNewLevel)(unk); + unk (*ParmsChangeLevel)(unk); + unk (*GetGameDescription)(unk); + unk (*PlayerCustomization)(unk); + unk (*SpectatorConnect)(unk); + unk (*SpectatorDisconnect)(unk); + unk (*SpectatorThink)(unk); + //138 +#if HALFLIFE_API_VERSION > 138 + unk (*Sys_Error)(unk); + unk (*PM_Move)(unk); + unk (*PM_Init)(unk); + unk (*PM_FindTextureType)(unk); + unk (*SetupVisibility)(unk); + unk (*UpdateClientData)(unk); + unk (*AddToFullPack)(unk); + unk (*CreateBaseline)(unk); + unk (*RegisterEncoders)(unk); + unk (*GetWeaponData)(unk); + unk (*CmdStart)(unk); + unk (*CmdEnd)(unk); + unk (*ConnectionlessPacket)(unk); + unk (*GetHullBounds)(unk); + unk (*CreateInstancedBaselines)(unk); + unk (*InconsistentFile)(unk); + unk (*AllowLagCompensation)(unk); +#endif +} SVHL_GameFuncs_t; + +//http://metamod.org/newapi_notes.html +struct +{ + unk (*OnFreeEntPrivateData)(unk); + unk (*GameShutdown)(unk); + unk (*ShouldCollide)(unk); + unk (*CvarValue)(unk); + unk (*CvarValue2 )(unk); +} *SVHL_GameFuncsEx; + +// http://metamod.org/engine_notes.html +typedef struct +{ + int (*PrecacheModel)(char *name); + int (*PrecacheSound)(char *name); + void (*SetModel)(hledict_t *ed, char *modelname); + unk (*ModelIndex)(unk); + int (*ModelFrames)(int midx); + void (*SetSize)(hledict_t *ed, float *mins, float *maxs); + void (*ChangeLevel)(char *nextmap, char *startspot); + unk (*GetSpawnParms)(unk); + unk (*SaveSpawnParms)(unk); + float (*VecToYaw)(float *inv); + void (*VecToAngles)(float *inv, float *outa); + unk (*MoveToOrigin)(unk); + unk (*ChangeYaw)(unk); + unk (*ChangePitch)(unk); + hledict_t *(*FindEntityByString)(hledict_t *last, char *field, char *value); + unk (*GetEntityIllum)(unk); + hledict_t *(*FindEntityInSphere)(hledict_t *last, float *org, float radius); + hledict_t *(*FindClientInPVS)(hledict_t *ed); + unk (*EntitiesInPVS)(unk); + void (*MakeVectors)(float *angles); + void (*AngleVectors)(float *angles, float *forward, float *right, float *up); + hledict_t *(*CreateEntity)(void); + void (*RemoveEntity)(hledict_t *ed); + hledict_t *(*CreateNamedEntity)(string_t name); + unk (*MakeStatic)(unk); + unk (*EntIsOnFloor)(unk); + int (*DropToFloor)(hledict_t *ed); + int (*WalkMove)(hledict_t *ed, float yaw, float dist, int mode); + void (*SetOrigin)(hledict_t *ed, float *neworg); + void (*EmitSound)(hledict_t *ed, int chan, char *soundname, float vol, float atten, int flags, int pitch); + void (*EmitAmbientSound)(hledict_t *ed, float *org, char *samp, float vol, float attenuation, unsigned int flags, int pitch); + void (*TraceLine)(float *start, float *end, int flags, hledict_t *ignore, hltraceresult_t *result); + unk (*TraceToss)(unk); + unk (*TraceMonsterHull)(unk); + void (*TraceHull)(float *start, float *end, int flags, int hullnum, hledict_t *ignore, hltraceresult_t *result); + unk (*TraceModel)(unk); + char *(*TraceTexture)(hledict_t *againstent, vec3_t start, vec3_t end); + unk (*TraceSphere)(unk); + unk (*GetAimVector)(unk); + void (*ServerCommand)(char *cmd); + void (*ServerExecute)(void); + unk (*ClientCommand)(unk); + unk (*ParticleEffect)(unk); + void (*LightStyle)(int stylenum, char *stylestr); + int (*DecalIndex)(char *decalname); + int (*PointContents)(float *org); + void (*MessageBegin)(int dest, int svc, float *org, hledict_t *ent); + void (*MessageEnd)(void); + void (*WriteByte)(int value); + void (*WriteChar)(int value); + void (*WriteShort)(int value); + void (*WriteLong)(int value); + void (*WriteAngle)(float value); + void (*WriteCoord)(float value); + void (*WriteString)(char *string); + void (*WriteEntity)(int entnum); + void (*CVarRegister)(hlcvar_t *hlvar); + float (*CVarGetFloat)(char *vname); + char *(*CVarGetString)(char *vname); + void (*CVarSetFloat)(char *vname, float v); + void (*CVarSetString)(char *vname, char *v); + void (*AlertMessage)(int level, char *fmt, ...); + void (*EngineFprintf)(FILE *f, char *fmt, ...); + void *(*PvAllocEntPrivateData)(hledict_t *ed, long quant); + unk (*PvEntPrivateData)(unk); + unk (*FreeEntPrivateData)(unk); + unk (*SzFromIndex)(unk); + string_t (*AllocString)(char *string); + unk (*GetVarsOfEnt)(unk); + hledict_t * (*PEntityOfEntOffset)(int ednum); + int (*EntOffsetOfPEntity)(hledict_t *ed); + int (*IndexOfEdict)(hledict_t *ed); + hledict_t *(*PEntityOfEntIndex)(int idx); + unk (*FindEntityByVars)(unk); + void *(*GetModelPtr)(hledict_t *ed); + int (*RegUserMsg)(char *msgname, int msgsize); + unk (*AnimationAutomove)(unk); + unk (*GetBonePosition)(unk); + hlintptr_t (*FunctionFromName)(char *name); + char *(*NameForFunction)(hlintptr_t); + unk (*ClientPrintf)(unk); + void (*ServerPrint)(char *msg); + char *(*Cmd_Args)(void); + char *(*Cmd_Argv)(int argno); + int (*Cmd_Argc)(void); + unk (*GetAttachment)(unk); + void (*CRC32_Init)(hlcrc_t *crc); + void (*CRC32_ProcessBuffer)(hlcrc_t *crc, qbyte *p, int len); + void (*CRC32_ProcessByte)(hlcrc_t *crc, qbyte b); + hlcrc_t (*CRC32_Final)(hlcrc_t crc); + long (*RandomLong)(long minv, long maxv); + float (*RandomFloat)(float minv, float maxv); + unk (*SetView)(unk); + unk (*Time)(unk); + unk (*CrosshairAngle)(unk); + void *(*LoadFileForMe)(char *name, int *size_out); + void (*FreeFile)(void *fptr); + unk (*EndSection)(unk); + int (*CompareFileTime)(char *fname1, char *fname2, int *result); + void (*GetGameDir)(char *gamedir); + unk (*Cvar_RegisterVariable)(unk); + unk (*FadeClientVolume)(unk); + unk (*SetClientMaxspeed)(unk); + unk (*CreateFakeClient)(unk); + unk (*RunPlayerMove)(unk); + unk (*NumberOfEntities)(unk); + unk (*GetInfoKeyBuffer)(unk); + unk (*InfoKeyValue)(unk); + unk (*SetKeyValue)(unk); + unk (*SetClientKeyValue)(unk); + unk (*IsMapValid)(unk); + unk (*StaticDecal)(unk); + unk (*PrecacheGeneric)(unk); + int (*GetPlayerUserId)(hledict_t *ed); + unk (*BuildSoundMsg)(unk); + unk (*IsDedicatedServer)(unk); + //138 +#if HALFLIFE_API_VERSION > 138 + hlcvar_t *(*CVarGetPointer)(char *varname); + unk (*GetPlayerWONId)(unk); + unk (*Info_RemoveKey)(unk); + unk (*GetPhysicsKeyValue)(unk); + unk (*SetPhysicsKeyValue)(unk); + unk (*GetPhysicsInfoString)(unk); + unsigned short (*PrecacheEvent)(int eventtype, char *eventname); + void (*PlaybackEvent)(int flags, hledict_t *ent, unsigned short eventidx, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2); + unk (*SetFatPVS)(unk); + unk (*SetFatPAS)(unk); + unk (*CheckVisibility)(unk); + unk (*DeltaSetField)(unk); + unk (*DeltaUnsetField)(unk); + unk (*DeltaAddEncoder)(unk); + unk (*GetCurrentPlayer)(unk); + unk (*CanSkipPlayer)(unk); + unk (*DeltaFindField)(unk); + unk (*DeltaSetFieldByIndex)(unk); + unk (*DeltaUnsetFieldByIndex)(unk); + unk (*SetGroupMask)(unk); + unk (*CreateInstancedBaseline)(unk); + unk (*Cvar_DirectSet)(unk); + unk (*ForceUnmodified)(unk); + unk (*GetPlayerStats)(unk); + unk (*AddServerCommand)(unk); + // + unk (*Voice_GetClientListening)(unk); + qboolean (*Voice_SetClientListening)(int listener, int sender, int shouldlisten); + //140 + unk (*GetPlayerAuthId)(unk); + unk (*SequenceGet)(unk); + unk (*SequencePickSentence)(unk); + unk (*GetFileSize)(unk); + unk (*GetApproxWavePlayLen)(unk); + unk (*IsCareerMatch)(unk); + unk (*GetLocalizedStringLength)(unk); + unk (*RegisterTutorMessageShown)(unk); + unk (*GetTimesTutorMessageShown)(unk); + unk (*ProcessTutorMessageDecayBuffer)(unk); + unk (*ConstructTutorMessageDecayBuffer)(unk); + unk (*ResetTutorMessageDecayData)(unk); + unk (*QueryClientCvarValue)(unk); + unk (*QueryClientCvarValue2)(unk); +#endif + + int check; //added so I can be sure parameters match this list, etc +} SVHL_Builtins_t; + +extern SVHL_Globals_t SVHL_Globals; +extern SVHL_GameFuncs_t SVHL_GameFuncs; + +extern hledict_t *SVHL_Edict; +extern int SVHL_NumActiveEnts; + + + + + +void SVHL_LinkEdict (hledict_t *ent, qboolean touch_triggers); +void SVHL_UnlinkEdict (hledict_t *ent); +hledict_t *SVHL_TestEntityPosition (hledict_t *ent); +void SVHL_TouchLinks ( hledict_t *ent, areanode_t *node ); +trace_t SVHL_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, int forcehull, hledict_t *passedict); +int SVHL_PointContents (vec3_t p); +int SVHL_AreaEdicts (vec3_t mins, vec3_t maxs, hledict_t **list, int maxcount); diff --git a/engine/server/svhl_phys.c b/engine/server/svhl_phys.c new file mode 100644 index 000000000..4f4a324c4 --- /dev/null +++ b/engine/server/svhl_phys.c @@ -0,0 +1,1854 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sv_phys.c + +#include "qwsvdef.h" + +#ifdef HLSERVER + +#include "svhl_gcapi.h" + +/* + + +pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move. + +onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects + +doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH +bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS +corpses are SOLID_NOT and MOVETYPE_TOSS +crates are SOLID_BBOX and MOVETYPE_TOSS +walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP +flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY + +solid_edge items only clip against bsp models. + +*/ + +extern cvar_t sv_maxvelocity; + +extern cvar_t sv_gravity; +extern cvar_t sv_stopspeed; +extern cvar_t sv_maxspeed; +extern cvar_t sv_spectatormaxspeed; +extern cvar_t sv_accelerate; +extern cvar_t sv_airaccelerate; +extern cvar_t sv_wateraccelerate; +extern cvar_t sv_friction; +extern cvar_t sv_waterfriction; +extern cvar_t sv_gameplayfix_noairborncorpse; + + +#define MOVE_EPSILON 0.01 + +void SVHL_Physics_Toss (hledict_t *ent); + +void SVHL_StartSound (hledict_t *entity, int channel, char *sample, int volume, float attenuation) +{ +} + +/* +================ +SV_CheckAllEnts +================ +*/ +void SVHL_CheckAllEnts (void) +{ + int e; + hledict_t *check; + +// see if any solid entities are inside the final position + for (e=1 ; eisfree) + continue; + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_FOLLOW + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + + if (SVHL_TestEntityPosition (check)) + Con_Printf ("entity in invalid position\n"); + } +} + +/* +================ +SV_CheckVelocity +================ +*/ +void SVHL_CheckVelocity (hledict_t *ent) +{ + int i; + +// +// bound velocity +// + for (i=0 ; i<3 ; i++) + { + if (IS_NAN(ent->v.velocity[i])) + { + Con_Printf ("Got a NaN velocity on %s\n", SVHL_Globals.stringbase+ent->v.classname); + ent->v.velocity[i] = 0; + } + if (IS_NAN(ent->v.origin[i])) + { + Con_Printf ("Got a NaN origin on %s\n", SVHL_Globals.stringbase+ent->v.classname); + ent->v.origin[i] = 0; + } + } + + if (Length(ent->v.velocity) > sv_maxvelocity.value) + { +// Con_DPrintf("Slowing %s\n", SVHL_Globals.stringbase+ent->v.classname); + VectorScale (ent->v.velocity, sv_maxvelocity.value/Length(ent->v.velocity), ent->v.velocity); + } +} + +/* +============= +SV_RunThink + +Runs thinking code if time. There is some play in the exact time the think +function will be called, because it is called before any movement is done +in a frame. Not used for pushmove objects, because they must be exact. +Returns false if the entity removed itself. +============= +*/ +qboolean SVHL_RunThink (hledict_t *ent) +{ + float thinktime; + + if (1) //try and imitate nq as closeley as possible + { + thinktime = ent->v.nextthink; + if (thinktime <= 0 || thinktime > sv.physicstime + host_frametime) + return true; + + if (thinktime < sv.physicstime) + thinktime = sv.physicstime; // don't let things stay in the past. + // it is possible to start that way + // by a trigger with a local time. + ent->v.nextthink = 0; + SVHL_Globals.time = thinktime; + SVHL_GameFuncs.DispatchThink(ent); + + return !ent->isfree; + } + + do + { + thinktime = ent->v.nextthink; + if (thinktime <= 0) + return true; + if (thinktime > sv.physicstime + host_frametime) + return true; + + if (thinktime < sv.physicstime) + thinktime = sv.physicstime; // don't let things stay in the past. + // it is possible to start that way + // by a trigger with a local time. + ent->v.nextthink = 0; + + SVHL_Globals.time = thinktime; + SVHL_GameFuncs.DispatchThink(ent); + + if (ent->isfree) + return false; + + if (ent->v.nextthink <= thinktime) //hmm... infinate loop was possible here.. Quite a few non-QW mods do this. + return true; + } while (1); + + return true; +} + +/* +================== +SV_Impact + +Two entities have touched, so run their touch functions +================== +*/ +void SVHL_Impact (hledict_t *e1, hledict_t *e2) +{ + SVHL_Globals.time = sv.physicstime; + if (e1->v.solid != SOLID_NOT) + { + SVHL_GameFuncs.DispatchTouch(e1, e2); + } + + if (e2->v.solid != SOLID_NOT) + { + SVHL_GameFuncs.DispatchTouch(e2, e1); + } +} + + +/* +================== +ClipVelocity + +Slide off of the impacting object +================== +*/ +void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce); + + +/* +============ +SV_FlyMove + +The basic solid body movement clip that slides along multiple planes +Returns the clipflags if the velocity was modified (hit something solid) +1 = floor +2 = wall / step +4 = dead stop +If steptrace is not NULL, the trace of any vertical wall hit will be stored +============ +*/ +#define MAX_CLIP_PLANES 5 +int SVHL_FlyMove (hledict_t *ent, float time, trace_t *steptrace) +{ + int bumpcount, numbumps; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[MAX_CLIP_PLANES]; + vec3_t primal_velocity, original_velocity, new_velocity; + int i, j; + trace_t trace; + vec3_t end; + float time_left; + int blocked; + vec3_t diff; + + vec3_t startorg; + + numbumps = 4; + + blocked = 0; + VectorCopy (ent->v.velocity, original_velocity); + VectorCopy (ent->v.velocity, primal_velocity); + numplanes = 0; + + time_left = time; + + VectorCopy (ent->v.origin, startorg); + + for (bumpcount=0 ; bumpcountv.origin[i] + time_left * ent->v.velocity[i]; + + trace = SVHL_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, 0, ent); + + if (trace.startsolid) + { // entity is trapped in another solid + VectorClear (ent->v.velocity); + return 3; + } + + if (trace.fraction > 0) + { // actually covered some distance + VectorCopy (trace.endpos, ent->v.origin); + VectorCopy (ent->v.velocity, original_velocity); + numplanes = 0; + } + + if (trace.fraction == 1) + break; // moved the entire distance + + if (!trace.ent) + SV_Error ("SV_FlyMove: !trace.ent"); + + if (trace.plane.normal[2] > 0.7) + { + blocked |= 1; // floor + if (((hledict_t *)trace.ent)->v.solid == SOLID_BSP) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = trace.ent; + } + } + if (!trace.plane.normal[2]) + { + blocked |= 2; // step + if (steptrace) + *steptrace = trace; // save for player extrafriction + } + +// +// run the impact function +// + SVHL_Impact (ent, trace.ent); + if (ent->isfree) + break; // removed by the impact function + + + time_left -= time_left * trace.fraction; + + // cliped to another plane + if (numplanes >= MAX_CLIP_PLANES) + { // this shouldn't really happen + VectorClear (ent->v.velocity); + if (steptrace) + *steptrace = trace; // save for player extrafriction + return 3; + } + + if (0) + { + ClipVelocity(ent->v.velocity, trace.plane.normal, ent->v.velocity, 1); + break; + } + else + { + if (numplanes) + { + VectorSubtract(planes[0], trace.plane.normal, diff); + if (Length(diff) < 0.01) + continue; //hit this plane already + } + + VectorCopy (trace.plane.normal, planes[numplanes]); + numplanes++; + + // + // modify original_velocity so it parallels all of the clip planes + // + for (i=0 ; iv.velocity[0], ent->v.velocity[1], ent->v.velocity[2]); + VectorCopy (new_velocity, ent->v.velocity); +// Con_Printf ("%5.1f %5.1f %5.1f\n",ent->v.velocity[0], ent->v.velocity[1], ent->v.velocity[2]); + } + else + { // go along the crease + if (numplanes != 2) + { +// Con_Printf ("clip velocity, numplanes == %i\n",numplanes); +// Con_Printf ("%5.1f %5.1f %5.1f ",ent->v.velocity[0], ent->v.velocity[1], ent->v.velocity[2]); + VectorClear (ent->v.velocity); +// Con_Printf ("%5.1f %5.1f %5.1f\n",ent->v.velocity[0], ent->v.velocity[1], ent->v.velocity[2]); + return 7; + } +// Con_Printf ("%5.1f %5.1f %5.1f ",ent->v.velocity[0], ent->v.velocity[1], ent->v.velocity[2]); + CrossProduct (planes[0], planes[1], dir); + VectorNormalize(dir); //fixes slow falling in corners + d = DotProduct (dir, ent->v.velocity); + VectorScale (dir, d, ent->v.velocity); +// Con_Printf ("%5.1f %5.1f %5.1f\n",ent->v.velocity[0], ent->v.velocity[1], ent->v.velocity[2]); + } + } + +// +// if original velocity is against the original velocity, stop dead +// to avoid tiny occilations in sloping corners +// + if (DotProduct (ent->v.velocity, primal_velocity) <= 0) + { + VectorClear (ent->v.velocity); + return blocked; + } + } + + return blocked; +} + + +/* +============ +SV_AddGravity + +============ +*/ +void SVHL_AddGravity (hledict_t *ent, float scale) +{ + if (!scale && progstype != PROG_QW) + scale = 1; + ent->v.velocity[2] -= scale * sv_gravity.value/*movevars.gravity*/ * host_frametime; +} + +/* +=============================================================================== + +PUSHMOVE + +=============================================================================== +*/ + +/* +============ +SV_PushEntity + +Does not change the entities velocity at all +============ +*/ +trace_t SVHL_PushEntity (hledict_t *ent, vec3_t push) +{ + trace_t trace; + vec3_t end; + + VectorAdd (ent->v.origin, push, end); + + if (ent->v.movetype == MOVETYPE_FLYMISSILE) + trace = SVHL_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, 0, ent); + else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT) + // only clip against bmodels + trace = SVHL_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, 0, ent); + else + trace = SVHL_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, 0, ent); + +// if (trace.ent) +// VectorMA(trace.endpos, sv_impactpush.value, trace.plane.normal, ent->v.origin); +// else + VectorCopy (trace.endpos, ent->v.origin); + SVHL_LinkEdict (ent, true); + + if (trace.ent) + SVHL_Impact (ent, trace.ent); + + return trace; +} + + + + +typedef struct +{ + hledict_t *ent; + vec3_t origin; + vec3_t angles; +// float deltayaw; +} hlpushed_t; +hlpushed_t pushed[MAX_EDICTS], *pushed_p; + +/* +============ +SV_Push + +Objects need to be moved back on a failed push, +otherwise riders would continue to slide. +============ +*/ +qboolean SVHL_PushAngles (hledict_t *pusher, vec3_t move, vec3_t amove) +{ + int i, e; + hledict_t *check, *block; + vec3_t mins, maxs; + float oldsolid; + hlpushed_t *p; + vec3_t org, org2, move2, forward, right, up; + + pushed_p = pushed; + + // find the bounding box + for (i=0 ; i<3 ; i++) + { + mins[i] = pusher->v.absmin[i] + move[i]; + maxs[i] = pusher->v.absmax[i] + move[i]; + } + +// we need this for pushing things later + VectorNegate (amove, org); + AngleVectors (org, forward, right, up); + +// save the pusher's original position + pushed_p->ent = pusher; + VectorCopy (pusher->v.origin, pushed_p->origin); + VectorCopy (pusher->v.angles, pushed_p->angles); +// if (pusher->client) +// pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW]; + pushed_p++; + +// move the pusher to it's final position + VectorAdd (pusher->v.origin, move, pusher->v.origin); + VectorAdd (pusher->v.angles, amove, pusher->v.angles); + SVHL_LinkEdict (pusher, false); + +// see if any solid entities are inside the final position + for (e = 1; e < SVHL_NumActiveEnts; e++) + { + check = &SVHL_Edict[e]; + if (check->isfree) + continue; + + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + +#if 1 + oldsolid = pusher->v.solid; + pusher->v.solid = SOLID_NOT; + block = SVHL_TestEntityPosition (check); + pusher->v.solid = oldsolid; + if (block) + continue; +#else + if (!check->area.prev) + continue; // not linked in anywhere +#endif + + // if the entity is standing on the pusher, it will definitely be moved + if ( ! ( ((int)check->v.flags & FL_ONGROUND) + && check->v.groundentity == pusher) ) + { + // see if the ent needs to be tested + if ( check->v.absmin[0] >= maxs[0] + || check->v.absmin[1] >= maxs[1] + || check->v.absmin[2] >= maxs[2] + || check->v.absmax[0] <= mins[0] + || check->v.absmax[1] <= mins[1] + || check->v.absmax[2] <= mins[2] ) + continue; + + + // see if the ent's bbox is inside the pusher's final position + // if (!SVHL_TestEntityPosition (check)) + // continue; + } + + if ((pusher->v.movetype == MOVETYPE_PUSH) || (check->v.groundentity == pusher)) + { + // move this entity + pushed_p->ent = check; + VectorCopy (check->v.origin, pushed_p->origin); + VectorCopy (check->v.angles, pushed_p->angles); + pushed_p++; + + // try moving the contacted entity + VectorAdd (check->v.origin, move, check->v.origin); +// if (check->client) +// { // FIXME: doesn't rotate monsters? +// check->client->ps.pmove.delta_angles[YAW] += amove[YAW]; +// } + VectorAdd (check->v.angles, amove, check->v.angles); + + // figure movement due to the pusher's amove + VectorSubtract (check->v.origin, pusher->v.origin, org); + org2[0] = DotProduct (org, forward); + org2[1] = -DotProduct (org, right); + org2[2] = DotProduct (org, up); + VectorSubtract (org2, org, move2); + VectorAdd (check->v.origin, move2, check->v.origin); + + check->v.flags = (int)check->v.flags & ~FL_ONGROUND; + + // may have pushed them off an edge + if (check->v.groundentity != pusher) + check->v.groundentity = 0; + + block = SVHL_TestEntityPosition (check); + if (!block) + { // pushed ok + SVHL_LinkEdict (check, false); + // impact? + continue; + } + + + + // if it is ok to leave in the old position, do it + // this is only relevent for riding entities, not pushed + // FIXME: this doesn't acount for rotation + VectorSubtract (check->v.origin, move, check->v.origin); + block = SVHL_TestEntityPosition (check); + if (!block) + { + pushed_p--; + continue; + } + } + + // if it is sitting on top. Do not block. + if (check->v.mins[0] == check->v.maxs[0]) + { + SVHL_LinkEdict (check, false); + continue; + } + +// Con_Printf("Pusher hit %s\n", PR_GetString(svprogfuncs, check->v.classname)); + SVHL_GameFuncs.DispatchBlocked(pusher, check); + + // move back any entities we already moved + // go backwards, so if the same entity was pushed + // twice, it goes back to the original position + for (p=pushed_p-1 ; p>=pushed ; p--) + { + VectorCopy (p->origin, p->ent->v.origin); + VectorCopy (p->angles, p->ent->v.angles); +// if (p->ent->client) +// { +// p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw; +// } + SVHL_LinkEdict (p->ent, false); + } + return false; + } + +//FIXME: is there a better way to handle this? + // see if anything we moved has touched a trigger + for (p=pushed_p-1 ; p>=pushed ; p--) + SVHL_TouchLinks ( p->ent, sv_areanodes ); + + return true; +} + +/* +============ +SV_Push + +============ +*/ +qboolean SVHL_Push (hledict_t *pusher, vec3_t move, vec3_t amove) +{ + int i, e; + hledict_t *check, *block; + vec3_t mins, maxs; + vec3_t pushorig; + int num_moved; + hledict_t *moved_edict[MAX_EDICTS]; + vec3_t moved_from[MAX_EDICTS]; + float oldsolid; + + if (amove[0] || amove[1] || amove[2]) + { + return SVHL_PushAngles(pusher, move, amove); + } + + for (i=0 ; i<3 ; i++) + { + mins[i] = pusher->v.absmin[i] + move[i]; + maxs[i] = pusher->v.absmax[i] + move[i]; + } + + VectorCopy (pusher->v.origin, pushorig); + +// move the pusher to it's final position + + VectorAdd (pusher->v.origin, move, pusher->v.origin); + SVHL_LinkEdict (pusher, false); + +// see if any solid entities are inside the final position + num_moved = 0; + for (e=1 ; eisfree) + continue; + if (check->v.movetype == MOVETYPE_PUSH + || check->v.movetype == MOVETYPE_NONE + || check->v.movetype == MOVETYPE_FOLLOW + || check->v.movetype == MOVETYPE_NOCLIP) + continue; + + oldsolid = pusher->v.solid; + pusher->v.solid = SOLID_NOT; + block = SVHL_TestEntityPosition (check); + pusher->v.solid = oldsolid; + if (block) + continue; + + // if the entity is standing on the pusher, it will definately be moved + if ( ! ( ((int)check->v.flags & FL_ONGROUND) + && + check->v.groundentity == pusher) ) + { + if ( check->v.absmin[0] >= maxs[0] + || check->v.absmin[1] >= maxs[1] + || check->v.absmin[2] >= maxs[2] + || check->v.absmax[0] <= mins[0] + || check->v.absmax[1] <= mins[1] + || check->v.absmax[2] <= mins[2] ) + continue; + + // see if the ent's bbox is inside the pusher's final position + if (!SVHL_TestEntityPosition (check)) + continue; + } + + VectorCopy (check->v.origin, moved_from[num_moved]); + moved_edict[num_moved] = check; + num_moved++; + +// check->v.flags = (int)check->v.flags & ~FL_ONGROUND; + + // try moving the contacted entity + VectorAdd (check->v.origin, move, check->v.origin); + block = SVHL_TestEntityPosition (check); + if (!block) + { // pushed ok + SVHL_LinkEdict (check, false); + continue; + } + + // if it is ok to leave in the old position, do it + VectorSubtract (check->v.origin, move, check->v.origin); + block = SVHL_TestEntityPosition (check); + if (!block) + { + //if leaving it where it was, allow it to drop to the floor again (useful for plats that move downward) + check->v.flags = (int)check->v.flags & ~FL_ONGROUND; + + num_moved--; + continue; + } + + // if it is still inside the pusher, block + if (check->v.mins[0] == check->v.maxs[0]) + { + SVHL_LinkEdict (check, false); + continue; + } + if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) + { // corpse + check->v.mins[0] = check->v.mins[1] = 0; + VectorCopy (check->v.mins, check->v.maxs); + SVHL_LinkEdict (check, false); + continue; + } + + VectorCopy (pushorig, pusher->v.origin); + SVHL_LinkEdict (pusher, false); + + // if the pusher has a "blocked" function, call it + // otherwise, just stay in place until the obstacle is gone + SVHL_GameFuncs.DispatchBlocked(pusher, check); + + // move back any entities we already moved + for (i=0 ; iv.origin); + SVHL_LinkEdict (moved_edict[i], false); + } + return false; + } + + return true; +} + + +/* +============ +SV_PushMove + +============ +*/ +void SVHL_PushMove (hledict_t *pusher, float movetime) +{ + int i; + vec3_t move; + vec3_t amove; + + if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2] + && !pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2]) + { + pusher->v.ltime += movetime; + return; + } + + for (i=0 ; i<3 ; i++) + { + move[i] = pusher->v.velocity[i] * movetime; + amove[i] = pusher->v.avelocity[i] * movetime; + } + + if (SVHL_Push (pusher, move, amove)) + pusher->v.ltime += movetime; +} + + +/* +================ +SV_Physics_Pusher + +================ +*/ +void SVHL_Physics_Pusher (hledict_t *ent) +{ + float thinktime; + float oldltime; + float movetime; +vec3_t oldorg, move; +vec3_t oldang, amove; +float l; + + oldltime = ent->v.ltime; + + thinktime = ent->v.nextthink; + if (thinktime < ent->v.ltime + host_frametime) + { + movetime = thinktime - ent->v.ltime; + if (movetime < 0) + movetime = 0; + } + else + movetime = host_frametime; + + if (movetime) + { + SVHL_PushMove (ent, movetime); // advances ent->v.ltime if not blocked + } + + if (thinktime > oldltime && thinktime <= ent->v.ltime) + { + VectorCopy (ent->v.origin, oldorg); + VectorCopy (ent->v.angles, oldang); + + ent->v.nextthink = 0; + SVHL_Globals.time = sv.physicstime; + SVHL_GameFuncs.DispatchThink(ent); + if (ent->isfree) + return; + + VectorSubtract (ent->v.origin, oldorg, move); + VectorSubtract (ent->v.angles, oldang, amove); + + l = Length(move)+Length(amove); + if (l > 1.0/64) + { + // Con_Printf ("**** snap: %f\n", Length (l)); + VectorCopy (oldorg, ent->v.origin); + SVHL_Push (ent, move, amove); + } + + } + else if (ent->v.flags & (1<<21)) + { + ent->v.nextthink = 0; + SVHL_Globals.time = sv.physicstime; + SVHL_GameFuncs.DispatchThink(ent); + if (ent->isfree) + return; + } + +} + + +/* +============= +SV_Physics_Follow + +Entities that are "stuck" to another entity +============= +*/ +void SVHL_Physics_Follow (hledict_t *ent) +{ + vec3_t vf, vr, vu, angles, v; + hledict_t *e; + + // regular thinking + if (!SVHL_RunThink (ent)) + return; + + // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects + e = ent->v.aiment; +// if (e->v.angles[0] == ent->xv->punchangle[0] && e->v.angles[1] == ent->xv->punchangle[1] && e->v.angles[2] == ent->xv->punchangle[2]) + { + // quick case for no rotation + VectorAdd(e->v.origin, ent->v.view_ofs, ent->v.origin); + } +/* else + { + angles[0] = -ent->xv->punchangle[0]; + angles[1] = ent->xv->punchangle[1]; + angles[2] = ent->xv->punchangle[2]; + AngleVectors (angles, vf, vr, vu); + v[0] = ent->v.view_ofs[0] * vf[0] + ent->v.view_ofs[1] * vr[0] + ent->v.view_ofs[2] * vu[0]; + v[1] = ent->v.view_ofs[0] * vf[1] + ent->v.view_ofs[1] * vr[1] + ent->v.view_ofs[2] * vu[1]; + v[2] = ent->v.view_ofs[0] * vf[2] + ent->v.view_ofs[1] * vr[2] + ent->v.view_ofs[2] * vu[2]; + angles[0] = -e->v.angles[0]; + angles[1] = e->v.angles[1]; + angles[2] = e->v.angles[2]; + AngleVectors (angles, vf, vr, vu); + ent->v.origin[0] = v[0] * vf[0] + v[1] * vf[1] + v[2] * vf[2] + e->v.origin[0]; + ent->v.origin[1] = v[0] * vr[0] + v[1] * vr[1] + v[2] * vr[2] + e->v.origin[1]; + ent->v.origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v.origin[2]; + } +*/ VectorAdd (e->v.angles, ent->v.v_angle, ent->v.angles); + SVHL_LinkEdict (ent, true); +} + +/* +============= +SV_Physics_Noclip + +A moving object that doesn't obey physics +============= +*/ +void SVHL_Physics_Noclip (hledict_t *ent) +{ +// regular thinking + if (!SVHL_RunThink (ent)) + return; + + VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); + VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); + + SVHL_LinkEdict (ent, false); +} + +/* +============================================================================== + +TOSS / BOUNCE + +============================================================================== +*/ + +/* +============= +SV_CheckWaterTransition + +============= +*/ +void SVHL_CheckWaterTransition (hledict_t *ent) +{ + int cont; + + cont = SVHL_PointContents (ent->v.origin); + + //needs to be q1 progs compatible + if (cont & FTECONTENTS_LAVA) + cont = Q1CONTENTS_LAVA; + else if (cont & FTECONTENTS_SLIME) + cont = Q1CONTENTS_SLIME; + else if (cont & FTECONTENTS_WATER) + cont = Q1CONTENTS_WATER; + else + cont = Q1CONTENTS_EMPTY; + + if (!ent->v.watertype) + { // just spawned here + ent->v.watertype = cont; + ent->v.waterlevel = 1; + return; + } + + if (cont <= Q1CONTENTS_WATER) + { + if (ent->v.watertype == Q1CONTENTS_EMPTY) + { // just crossed into water + SVHL_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + } + ent->v.watertype = cont; + ent->v.waterlevel = 1; + } + else + { + if (ent->v.watertype != Q1CONTENTS_EMPTY) + { // just crossed into open + SVHL_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + } + ent->v.watertype = Q1CONTENTS_EMPTY; + ent->v.waterlevel = cont; + } +} + +/* +============= +SV_Physics_Toss + +Toss, bounce, and fly movement. When onground, do nothing. +============= +*/ +void SVHL_Physics_Toss (hledict_t *ent) +{ + trace_t trace; + vec3_t move; + float backoff; + + vec3_t temporg; + + SVHL_CheckVelocity (ent); + +// regular thinking + if (!SVHL_RunThink (ent)) + return; + +// if onground, return without moving + if ( ((int)ent->v.flags & FL_ONGROUND) ) + { + if (ent->v.velocity[2] >= (1.0f/32.0f)) + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + else + { + if (sv_gameplayfix_noairborncorpse.value) + { + hledict_t *onent; + onent = ent->v.groundentity; + if (!onent->isfree) + return; //don't drop if our fround is still valid + } + else + return; //don't drop, even if the item we were on was removed (certain dm maps do this for q3 style stuff). + } + } + +// add gravity + if (ent->v.movetype != MOVETYPE_FLY + && ent->v.movetype != MOVETYPE_FLYMISSILE + && ent->v.movetype != MOVETYPE_BOUNCEMISSILE + && ent->v.movetype != MOVETYPE_SWIM) + SVHL_AddGravity (ent, 1.0); + +// move angles + VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); + +// move origin + VectorScale (ent->v.velocity, host_frametime, move); + VectorCopy(ent->v.origin, temporg); + VectorCopy(temporg, ent->v.origin); + trace = SVHL_PushEntity (ent, move); + + if (trace.allsolid) + trace.fraction = 0; + if (trace.fraction == 1) + return; + if (ent->isfree) + return; + + VectorCopy(trace.endpos, move); + + if (ent->v.movetype == MOVETYPE_BOUNCE) + backoff = 1.5; + else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE) + backoff = 2; + else + backoff = 1; + + ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); + + +// stop if on ground + if ((trace.plane.normal[2] > 0.7) && (ent->v.movetype != MOVETYPE_BOUNCEMISSILE)) + { + if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE ) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = trace.ent; + VectorClear (ent->v.velocity); + VectorClear (ent->v.avelocity); + } + } + +// check for in water + SVHL_CheckWaterTransition (ent); +} + +/* +=============================================================================== + +STEPPING MOVEMENT + +=============================================================================== +*/ + +/* +============= +SV_Physics_Step + +Monsters freefall when they don't have a ground entity, otherwise +all movement is done with discrete steps. + +This is also used for objects that have become still on the ground, but +will fall if the floor is pulled out from under them. +FIXME: is this true? +============= +*/ +void SVHL_Physics_Step (hledict_t *ent) +{ + qboolean hitsound; + + if (ent->v.velocity[2] >= (1.0 / 32.0) && ((int)ent->v.flags & FL_ONGROUND)) + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + +// frefall if not onground + if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) ) + { + hitsound = ent->v.velocity[2] < movevars.gravity*-0.1; + + SVHL_AddGravity (ent, 1.0); + SVHL_CheckVelocity (ent); + SVHL_FlyMove (ent, host_frametime, NULL); + SVHL_LinkEdict (ent, true); + + if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground + { + if (hitsound) + { + if (progstype == PROG_H2) + SVHL_StartSound (ent, 0, "fx/thngland.wav", 255, 1); + else + SVHL_StartSound (ent, 0, "demon/dland2.wav", 255, 1); + } + } + } + +// regular thinking + SVHL_RunThink (ent); + + SVHL_CheckWaterTransition (ent); +} + +//============================================================================ + + + + + + + + + + + + + +/* +============= +SV_CheckStuck + +This is a big hack to try and fix the rare case of getting stuck in the world +clipping hull. +============= +*/ +void SVHL_CheckStuck (hledict_t *ent) +{ + int i, j; + int z; + vec3_t org; +//return; + if (!SVHL_TestEntityPosition(ent)) + { + VectorCopy (ent->v.origin, ent->v.oldorigin); + return; + } + + VectorCopy (ent->v.origin, org); + VectorCopy (ent->v.oldorigin, ent->v.origin); + if (!SVHL_TestEntityPosition(ent)) + { + Con_DPrintf ("Unstuck.\n"); + SVHL_LinkEdict (ent, true); + return; + } + + for (z=0 ; z < movevars.stepheight ; z++) + for (i=-1 ; i <= 1 ; i++) + for (j=-1 ; j <= 1 ; j++) + { + ent->v.origin[0] = org[0] + i; + ent->v.origin[1] = org[1] + j; + ent->v.origin[2] = org[2] + z; + if (!SVHL_TestEntityPosition(ent)) + { + Con_DPrintf ("Unstuck.\n"); + SVHL_LinkEdict (ent, true); + return; + } + } + + VectorCopy (org, ent->v.origin); + Con_DPrintf ("player is stuck.\n"); +} + +/* +============= +SV_CheckWater +============= +*/ +qboolean SVHL_CheckWater (hledict_t *ent) +{ + vec3_t point; + int cont; + + point[0] = ent->v.origin[0]; + point[1] = ent->v.origin[1]; + point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; + + ent->v.waterlevel = 0; + ent->v.watertype = Q1CONTENTS_EMPTY; + cont = SVHL_PointContents (point); + if (cont & FTECONTENTS_FLUID) + { + if (cont & FTECONTENTS_LAVA) + ent->v.watertype = Q1CONTENTS_LAVA; + else if (cont & FTECONTENTS_SLIME) + ent->v.watertype = Q1CONTENTS_SLIME; + else if (cont & FTECONTENTS_WATER) + ent->v.watertype = Q1CONTENTS_WATER; + else + ent->v.watertype = Q1CONTENTS_SKY; + ent->v.waterlevel = 1; + point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5; + cont = SVHL_PointContents (point); + if (cont & FTECONTENTS_FLUID) + { + ent->v.waterlevel = 2; + point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; + cont = SVHL_PointContents (point); + if (cont & FTECONTENTS_FLUID) + ent->v.waterlevel = 3; + } + } + + return ent->v.waterlevel > 1; +} + + +/* +============ +SV_WallFriction + +============ +*/ +void SVHL_WallFriction (hledict_t *ent, trace_t *trace) +{ + vec3_t forward, right, up; + float d, i; + vec3_t into, side; + + AngleVectors (ent->v.v_angle, forward, right, up); + d = DotProduct (trace->plane.normal, forward); + + d += 0.5; + if (d >= 0 || IS_NAN(d)) + return; + +// cut the tangential velocity + i = DotProduct (trace->plane.normal, ent->v.velocity); + VectorScale (trace->plane.normal, i, into); + VectorSubtract (ent->v.velocity, into, side); + + ent->v.velocity[0] = side[0] * (1 + d); + ent->v.velocity[1] = side[1] * (1 + d); +} + +/* +===================== +SV_TryUnstick + +Player has come to a dead stop, possibly due to the problem with limited +float precision at some angle joins in the BSP hull. + +Try fixing by pushing one pixel in each direction. + +This is a hack, but in the interest of good gameplay... +====================== +*/ +int SVHL_TryUnstick (hledict_t *ent, vec3_t oldvel) +{ + int i; + vec3_t oldorg; + vec3_t dir; + int clip; + trace_t steptrace; + + VectorCopy (ent->v.origin, oldorg); + VectorClear (dir); + + for (i=0 ; i<8 ; i++) + { +// try pushing a little in an axial direction + switch (i) + { + case 0: dir[0] = 2; dir[1] = 0; break; + case 1: dir[0] = 0; dir[1] = 2; break; + case 2: dir[0] = -2; dir[1] = 0; break; + case 3: dir[0] = 0; dir[1] = -2; break; + case 4: dir[0] = 2; dir[1] = 2; break; + case 5: dir[0] = -2; dir[1] = 2; break; + case 6: dir[0] = 2; dir[1] = -2; break; + case 7: dir[0] = -2; dir[1] = -2; break; + } + + SVHL_PushEntity (ent, dir); + +// retry the original move + ent->v.velocity[0] = oldvel[0]; + ent->v. velocity[1] = oldvel[1]; + ent->v. velocity[2] = 0; + clip = SVHL_FlyMove (ent, 0.1, &steptrace); + + if ( fabs(oldorg[1] - ent->v.origin[1]) > 4 + || fabs(oldorg[0] - ent->v.origin[0]) > 4 ) + { +//Con_DPrintf ("unstuck!\n"); + return clip; + } + +// go back to the original pos and try again + VectorCopy (oldorg, ent->v.origin); + } + + VectorClear (ent->v.velocity); + return 7; // still not moving +} + +/* +===================== +SV_WalkMove + +Only used by players +====================== +*/ +#if 0 +#define SMSTEPSIZE 4 +void SVHL_WalkMove (hledict_t *ent) +{ + vec3_t upmove, downmove; + vec3_t oldorg, oldvel; + vec3_t nosteporg, nostepvel; + int clip; + int oldonground; + trace_t steptrace, downtrace; + +// +// do a regular slide move unless it looks like you ran into a step +// + oldonground = (int)ent->v.flags & FL_ONGROUND; + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + + VectorCopy (ent->v.origin, oldorg); + VectorCopy (ent->v.velocity, oldvel); + + clip = SVHL_FlyMove (ent, host_frametime, &steptrace); + + if ( !(clip & 2) ) + return; // move didn't block on a step + + if (!oldonground && ent->v.waterlevel == 0) + return; // don't stair up while jumping + + if (ent->v.movetype != MOVETYPE_WALK) + return; // gibbed by a trigger + +// if (sv_nostep.value) +// return; + + if ( (int)ent->v.flags & FL_WATERJUMP ) + return; + + VectorCopy (ent->v.origin, nosteporg); + VectorCopy (ent->v.velocity, nostepvel); + +// +// try moving up and forward to go up a step +// + VectorCopy (oldorg, ent->v.origin); // back to start pos + + VectorCopy (vec3_origin, upmove); + VectorCopy (vec3_origin, downmove); + upmove[2] = movevars.stepheight; + downmove[2] = -movevars.stepheight + oldvel[2]*host_frametime; + +// move up + SVHL_PushEntity (ent, upmove); // FIXME: don't link? + +// move forward + ent->v.velocity[0] = oldvel[0]; + ent->v.velocity[1] = oldvel[1]; + ent->v.velocity[2] = 0; + clip = SVHL_FlyMove (ent, host_frametime, &steptrace); + +// check for stuckness, possibly due to the limited precision of floats +// in the clipping hulls + if (clip) + { + if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125 + && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 ) + { // stepping up didn't make any progress + clip = SVHL_TryUnstick (ent, oldvel); + +// Con_Printf("Try unstick fwd\n"); + } + } + +// extra friction based on view angle + if ( clip & 2 ) + { + vec3_t lastpos, lastvel, lastdown; + +// Con_Printf("couldn't do it\n"); + + //retry with a smaller step (allows entering smaller areas with a step of 4) + VectorCopy (downmove, lastdown); + VectorCopy (ent->v.origin, lastpos); + VectorCopy (ent->v.velocity, lastvel); + + // + // try moving up and forward to go up a step + // + VectorCopy (oldorg, ent->v.origin); // back to start pos + + VectorCopy (vec3_origin, upmove); + VectorCopy (vec3_origin, downmove); + upmove[2] = SMSTEPSIZE; + downmove[2] = -SMSTEPSIZE + oldvel[2]*host_frametime; + + // move up + SVHL_PushEntity (ent, upmove); // FIXME: don't link? + + // move forward + ent->v.velocity[0] = oldvel[0]; + ent->v.velocity[1] = oldvel[1]; + ent->v.velocity[2] = 0; + clip = SVHL_FlyMove (ent, host_frametime, &steptrace); + + // check for stuckness, possibly due to the limited precision of floats + // in the clipping hulls + if (clip) + { + if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125 + && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 ) + { // stepping up didn't make any progress + clip = SVHL_TryUnstick (ent, oldvel); + +// Con_Printf("Try unstick up\n"); + } + } + + if ( fabs(oldorg[1] - ent->v.origin[1])+fabs(oldorg[0] - ent->v.origin[0]) < fabs(oldorg[1] - lastpos[1])+fabs(oldorg[1] - lastpos[1])) + { // stepping up didn't make any progress + //go back + VectorCopy (lastdown, downmove); + VectorCopy (lastpos, ent->v.origin); + VectorCopy (lastvel, ent->v.velocity); + + SVHL_WallFriction (ent, &steptrace); + +// Con_Printf("wall friction\n"); + } + + else if (clip & 2) + { + SVHL_WallFriction (ent, &steptrace); +// Con_Printf("wall friction 2\n"); + } + } + +// move down + downtrace = SVHL_PushEntity (ent, downmove); // FIXME: don't link? + + if (downtrace.plane.normal[2] > 0.7) + { + if (ent->v.solid == SOLID_BSP) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = EDICT_TO_PROG(svprogfuncs, downtrace.ent); + } + } + else + { +// if the push down didn't end up on good ground, use the move without +// the step up. This happens near wall / slope combinations, and can +// cause the player to hop up higher on a slope too steep to climb + VectorCopy (nosteporg, ent->v.origin); + VectorCopy (nostepvel, ent->v.velocity); + +// Con_Printf("down not good\n"); + } +} +#else + +// 1/32 epsilon to keep floating point happy +#define DIST_EPSILON (0.03125) +int SVHL_SetOnGround (hledict_t *ent) +{ + vec3_t end; + trace_t trace; + if ((int)ent->v.flags & FL_ONGROUND) + return 1; + end[0] = ent->v.origin[0]; + end[1] = ent->v.origin[1]; + end[2] = ent->v.origin[2] - 1; + trace = SVHL_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, 0, ent); + if (trace.fraction <= DIST_EPSILON && trace.plane.normal[2] >= 0.7) + { + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = trace.ent; + return 1; + } + return 0; +} +void SVHL_WalkMove (hledict_t *ent) +{ + int clip, oldonground, originalmove_clip, originalmove_flags; + hledict_t *originalmove_groundentity; + vec3_t upmove, downmove, start_origin, start_velocity, originalmove_origin, originalmove_velocity; + trace_t downtrace, steptrace; + + SVHL_CheckVelocity(ent); + + // do a regular slide move unless it looks like you ran into a step + oldonground = (int)ent->v.flags & FL_ONGROUND; + ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; + + VectorCopy (ent->v.origin, start_origin); + VectorCopy (ent->v.velocity, start_velocity); + + clip = SVHL_FlyMove (ent, host_frametime, NULL); + + SVHL_SetOnGround (ent); + SVHL_CheckVelocity(ent); + + VectorCopy(ent->v.origin, originalmove_origin); + VectorCopy(ent->v.velocity, originalmove_velocity); + originalmove_clip = clip; + originalmove_flags = (int)ent->v.flags; + originalmove_groundentity = ent->v.groundentity; + + if ((int)ent->v.flags & FL_WATERJUMP) + return; + +// if (sv_nostep.value) +// return; + + // if move didn't block on a step, return + if (clip & 2) + { + // if move was not trying to move into the step, return + if (fabs(start_velocity[0]) < 0.03125 && fabs(start_velocity[1]) < 0.03125) + return; + + if (ent->v.movetype != MOVETYPE_FLY) + { + // return if gibbed by a trigger + if (ent->v.movetype != MOVETYPE_WALK) + return; + + // only step up while jumping if that is enabled +// if (!(sv_jumpstep.value && sv_gameplayfix_stepwhilejumping.value)) + if (!oldonground && ent->v.waterlevel == 0) + return; + } + + // try moving up and forward to go up a step + // back to start pos + VectorCopy (start_origin, ent->v.origin); + VectorCopy (start_velocity, ent->v.velocity); + + // move up + VectorClear (upmove); + upmove[2] = movevars.stepheight; + // FIXME: don't link? + SVHL_PushEntity(ent, upmove); + + // move forward + ent->v.velocity[2] = 0; + clip = SVHL_FlyMove (ent, host_frametime, &steptrace); + ent->v.velocity[2] += start_velocity[2]; + + SVHL_CheckVelocity(ent); + + // check for stuckness, possibly due to the limited precision of floats + // in the clipping hulls + if (clip + && fabs(originalmove_origin[1] - ent->v.origin[1]) < 0.03125 + && fabs(originalmove_origin[0] - ent->v.origin[0]) < 0.03125) + { +// Con_Printf("wall\n"); + // stepping up didn't make any progress, revert to original move + VectorCopy(originalmove_origin, ent->v.origin); + VectorCopy(originalmove_velocity, ent->v.velocity); + //clip = originalmove_clip; + ent->v.flags = originalmove_flags; + ent->v.groundentity = originalmove_groundentity; + // now try to unstick if needed + //clip = SVHL_TryUnstick (ent, oldvel); + return; + } + + //Con_Printf("step - "); + + // extra friction based on view angle + if (clip & 2)// && sv_wallfriction.value) + { +// Con_Printf("wall\n"); + SVHL_WallFriction (ent, &steptrace); + } + } + else if (/*!sv_gameplayfix_stepdown.integer || */!oldonground || start_velocity[2] > 0 || ((int)ent->v.flags & FL_ONGROUND) || ent->v.waterlevel >= 2) + return; + + // move down + VectorClear (downmove); + downmove[2] = -movevars.stepheight + start_velocity[2]*host_frametime; + // FIXME: don't link? + downtrace = SVHL_PushEntity (ent, downmove); + + if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7) + { + // LordHavoc: disabled this check so you can walk on monsters/players + //if (ent->v.solid == SOLID_BSP) + { + //Con_Printf("onground\n"); + ent->v.flags = (int)ent->v.flags | FL_ONGROUND; + ent->v.groundentity = downtrace.ent; + } + } + else + { + //Con_Printf("slope\n"); + // if the push down didn't end up on good ground, use the move without + // the step up. This happens near wall / slope combinations, and can + // cause the player to hop up higher on a slope too steep to climb + VectorCopy(originalmove_origin, ent->v.origin); + VectorCopy(originalmove_velocity, ent->v.velocity); + //clip = originalmove_clip; + ent->v.flags = originalmove_flags; + ent->v.groundentity = originalmove_groundentity; + } + + SVHL_SetOnGround (ent); + SVHL_CheckVelocity(ent); +} +#endif + +/* +================ +SV_RunEntity + +================ +*/ +void SVHL_RunEntity (hledict_t *ent) +{ + if (ent-SVHL_Edict > 0 && ent-SVHL_Edict <= sv.allocated_client_slots) + { //a client woo. + /* if ( svs.clients[ent->entnum-1].state < cs_spawned ) + return; // unconnected slot + + + if (svs.clients[ent->entnum-1].protocol == SCP_BAD) + svs.clients[ent->entnum-1].edict->v.fixangle = 0; //bots never get fixangle cleared otherwise + + host_client = &svs.clients[ent->entnum-1]; + SVHL_ClientThink(); + + // + // call standard client pre-think + // + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); +#ifdef VM_Q1 + if (svs.gametype == GT_Q1QVM) + Q1QVM_PlayerPreThink(); + else +#endif + if (pr_global_struct->PlayerPreThink) + PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink); + + */ + } + + if (ent->v.flags & (1<<30)) + { + GHL_RemoveEntity(ent); + return; + } + + switch ( (int)ent->v.movetype) + { + case MOVETYPE_PUSH: + SVHL_Physics_Pusher (ent); + break; + case MOVETYPE_NONE: + if (!SVHL_RunThink (ent)) + return; + break; + case MOVETYPE_NOCLIP: + SVHL_Physics_Noclip (ent); + break; + case MOVETYPE_STEP: + case MOVETYPE_PUSHPULL: + SVHL_Physics_Step (ent); + break; + case MOVETYPE_FOLLOW: + SVHL_Physics_Follow (ent); + break; + case MOVETYPE_TOSS: + case MOVETYPE_BOUNCE: + case MOVETYPE_BOUNCEMISSILE: + case MOVETYPE_FLY: + case MOVETYPE_FLYMISSILE: + case MOVETYPE_SWIM: + SVHL_Physics_Toss (ent); + break; + case MOVETYPE_WALK: + if (!SVHL_RunThink (ent)) + return; + if (!SVHL_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) + SVHL_AddGravity (ent, ent->v.gravity); + SVHL_CheckStuck (ent); + + SVHL_WalkMove (ent); + +// if (!(ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots)) + SVHL_LinkEdict (ent, true); + + break; + default: + SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v.movetype, SVHL_Globals.stringbase+ent->v.classname); + } + + /* + if (ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots) + { + SVhL_LinkEdict (ent, true); + + pr_global_struct->time = sv.physicstime; + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); +#ifdef VM_Q1 + if (svs.gametype == GT_Q1QVM) + Q1QVM_PostThink(); + else +#endif + { + if (pr_global_struct->PlayerPostThink) + PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPostThink); + } + } + */ +} + +trace_t SVHL_Trace_Toss (hledict_t *tossent, hledict_t *ignore) +{ + int i; + float gravity; + vec3_t move, end; + trace_t trace; + + vec3_t origin, velocity; + + // this has to fetch the field from the original edict, since our copy is truncated + gravity = tossent->v.gravity; + if (!gravity) + gravity = 1.0; + gravity *= sv_gravity.value * 0.05; + + VectorCopy (tossent->v.origin, origin); + VectorCopy (tossent->v.velocity, velocity); + + SVHL_CheckVelocity (tossent); + + for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds + { + velocity[2] -= gravity; + VectorScale (velocity, 0.05, move); + VectorAdd (origin, move, end); + trace = SVHL_Move (origin, tossent->v.mins, tossent->v.maxs, end, MOVE_NORMAL, 0, tossent); + VectorCopy (trace.endpos, origin); + + if (trace.fraction < 1 && trace.ent && trace.ent != ignore) + break; + + if (Length(velocity) > sv_maxvelocity.value) + { +// Con_DPrintf("Slowing %s\n", PR_GetString(svprogfuncs, tossent->v.classname)); + VectorScale (velocity, sv_maxvelocity.value/Length(velocity), velocity); + } + } + + trace.fraction = 0; // not relevant + return trace; +} + +/* +================ +SV_Physics + +================ +*/ +void SVHL_RunFrame (void) +{ + qboolean retouch; + int i; + hledict_t *ent; + + //only run physics tics if there's a client on the server. + //this fixes the bug where the train moves out before the player spawns, so the player doesn't fall to his death + for (i = 0; i < sv.allocated_client_slots; i++) + { + if (svs.clients[i].state == cs_spawned) + break; + } + if (i == sv.allocated_client_slots) + return; + + + SVHL_Globals.frametime = host_frametime; + SVHL_Globals.time = sv.physicstime; + + SVHL_GameFuncs.StartFrame (); + + + retouch = SVHL_Globals.force_retouch; + +// +// treat each object in turn +// even the world gets a chance to think +// + for (i=0 ; iisfree) + continue; + + if (retouch) + SVHL_LinkEdict (ent, true); // force retouch even for stationary + + if (i > 0 && i <= sv.allocated_client_slots) + { + if (!svs.clients[i-1].isindependant) + { + // SVHL_RunEntity(ent); + } + else + SVHL_LinkEdict(ent, true); + continue; // clients are run directly from packets + } + + SVHL_RunEntity (ent); + } + + if (retouch) + SVHL_Globals.force_retouch-=1; +} + +#endif diff --git a/engine/server/svhl_world.c b/engine/server/svhl_world.c new file mode 100644 index 000000000..f341a43da --- /dev/null +++ b/engine/server/svhl_world.c @@ -0,0 +1,747 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// world.c -- world query functions + +#include "qwsvdef.h" + +#ifdef HLSERVER +#include "svhl_gcapi.h" + +qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace, vec3_t origin, vec3_t angles); +/* + +entities never clip against themselves, or their owner + +line of sight checks trace->crosscontent, but bullets don't + +*/ + +extern cvar_t sv_compatiblehulls; + +typedef struct +{ + vec3_t boxmins, boxmaxs;// enclose the test object along entire move + float *mins, *maxs; // size of the moving object + vec3_t mins2, maxs2; // size when clipping against mosnters + float *start, *end; + trace_t trace; + int type; + hledict_t *passedict; + int hullnum; +} hlmoveclip_t; + +/* +=============================================================================== + +HULL BOXES + +=============================================================================== +*/ + + +/* +=============================================================================== + +ENTITY AREA CHECKING + +=============================================================================== +*/ + +/* +=============== +SV_UnlinkEdict + +=============== +*/ +void SVHL_UnlinkEdict (hledict_t *ent) +{ + if (!ent->area.prev) + return; // not linked in anywhere + RemoveLink (&ent->area); + ent->area.prev = ent->area.next = NULL; +} + + +/* +==================== +SV_TouchLinks +==================== +*/ +#define MAX_NODELINKS 256 //all this means is that any more than this will not touch. +hledict_t *nodelinks[MAX_NODELINKS]; +void SVHL_TouchLinks ( hledict_t *ent, areanode_t *node ) +{ //Spike: rewritten this function to cope with killtargets used on a few maps. + link_t *l, *next; + hledict_t *touch; + + int linkcount = 0, ln; + + //work out who they are first. + for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) + { + if (linkcount == MAX_NODELINKS) + break; + next = l->next; + touch = HLEDICT_FROM_AREA(l); + if (touch == ent) + continue; + + if (touch->v.solid != SOLID_TRIGGER) + continue; + + if (ent->v.absmin[0] > touch->v.absmax[0] + || ent->v.absmin[1] > touch->v.absmax[1] + || ent->v.absmin[2] > touch->v.absmax[2] + || ent->v.absmax[0] < touch->v.absmin[0] + || ent->v.absmax[1] < touch->v.absmin[1] + || ent->v.absmax[2] < touch->v.absmin[2] ) + continue; + +// if (!((int)ent->xv.dimension_solid & (int)touch->xv.dimension_hit)) +// continue; + + nodelinks[linkcount++] = touch; + } + + for (ln = 0; ln < linkcount; ln++) + { + touch = nodelinks[ln]; + + //make sure nothing moved it away + if (touch->isfree) + continue; + if (touch->v.solid != SOLID_TRIGGER) + continue; + if (ent->v.absmin[0] > touch->v.absmax[0] + || ent->v.absmin[1] > touch->v.absmax[1] + || ent->v.absmin[2] > touch->v.absmax[2] + || ent->v.absmax[0] < touch->v.absmin[0] + || ent->v.absmax[1] < touch->v.absmin[1] + || ent->v.absmax[2] < touch->v.absmin[2] ) + continue; + +// if (!((int)ent->xv->dimension_solid & (int)touch->xv->dimension_hit)) //didn't change did it?... +// continue; + + SVHL_GameFuncs.DispatchTouch(touch, ent); + + if (ent->isfree) + break; + } + + +// recurse down both sides + if (node->axis == -1 || ent->isfree) + return; + + if ( ent->v.absmax[node->axis] > node->dist ) + SVHL_TouchLinks ( ent, node->children[0] ); + if ( ent->v.absmin[node->axis] < node->dist ) + SVHL_TouchLinks ( ent, node->children[1] ); +} + +/* +=============== +SV_LinkEdict + +=============== +*/ +void SVHL_LinkEdict (hledict_t *ent, qboolean touch_triggers) +{ + areanode_t *node; + + if (ent->area.prev) + SVHL_UnlinkEdict (ent); // unlink from old position + + if (ent == &SVHL_Edict[0]) + return; // don't add the world + + if (ent->isfree) + return; + +// set the abs box + if (ent->v.solid == SOLID_BSP && + (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) ) + { // expand for rotation + +#if 1 + int i; + float v; + float max; + //q2 method + max = 0; + for (i=0 ; i<3 ; i++) + { + v =fabs( ent->v.mins[i]); + if (v > max) + max = v; + v =fabs( ent->v.maxs[i]); + if (v > max) + max = v; + } + for (i=0 ; i<3 ; i++) + { + ent->v.absmin[i] = ent->v.origin[i] - max; + ent->v.absmax[i] = ent->v.origin[i] + max; + } +#else + + int i; + + vec3_t f, r, u; + vec3_t mn, mx; + + //we need to link to the correct leaves + + AngleVectors(ent->v.angles, f,r,u); + + mn[0] = DotProduct(ent->v.mins, f); + mn[1] = -DotProduct(ent->v.mins, r); + mn[2] = DotProduct(ent->v.mins, u); + + mx[0] = DotProduct(ent->v.maxs, f); + mx[1] = -DotProduct(ent->v.maxs, r); + mx[2] = DotProduct(ent->v.maxs, u); + for (i = 0; i < 3; i++) + { + if (mn[i] < mx[i]) + { + ent->v.absmin[i] = ent->v.origin[i]+mn[i]-0.1; + ent->v.absmax[i] = ent->v.origin[i]+mx[i]+0.1; + } + else + { //box went inside out + ent->v.absmin[i] = ent->v.origin[i]+mx[i]-0.1; + ent->v.absmax[i] = ent->v.origin[i]+mn[i]+0.1; + } + } +#endif + } + else + { + VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin); + VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax); + } + +// +// to make items easier to pick up and allow them to be grabbed off +// of shelves, the abs sizes are expanded +// + if ((int)ent->v.flags & FL_ITEM) + { + ent->v.absmin[0] -= 15; + ent->v.absmin[1] -= 15; + ent->v.absmin[2] -= 1; + ent->v.absmax[0] += 15; + ent->v.absmax[1] += 15; + ent->v.absmax[2] += 1; + } + else + { // because movement is clipped an epsilon away from an actual edge, + // we must fully check even when bounding boxes don't quite touch + ent->v.absmin[0] -= 1; + ent->v.absmin[1] -= 1; + ent->v.absmin[2] -= 1; + ent->v.absmax[0] += 1; + ent->v.absmax[1] += 1; + ent->v.absmax[2] += 1; + } + +// link to PVS leafs +// sv.worldmodel->funcs.FindTouchedLeafs_Q1(sv.worldmodel, ent, ent->v.absmin, ent->v.absmax); + +// find the first node that the ent's box crosses + node = sv_areanodes; + while (1) + { + if (node->axis == -1) + break; + if (ent->v.absmin[node->axis] > node->dist) + node = node->children[0]; + else if (ent->v.absmax[node->axis] < node->dist) + node = node->children[1]; + else + break; // crosses the node + } + +// link it in + + InsertLinkBefore (&ent->area, &node->solid_edicts); + +// if touch_triggers, touch all entities at this node and decend for more + if (touch_triggers) + SVHL_TouchLinks ( ent, sv_areanodes ); +} + + +/* +=============================================================================== + +POINT TESTING IN HULLS + +=============================================================================== +*/ + +/* +================== +SV_PointContents + +================== +*/ +int SVHL_PointContents (vec3_t p) +{ + return sv.worldmodel->funcs.PointContents(sv.worldmodel, p); +} + +//=========================================================================== + +/* +============ +SV_TestEntityPosition + +A small wrapper around SV_BoxInSolidEntity that never clips against the +supplied entity. +============ +*/ +hledict_t *SVHL_TestEntityPosition (hledict_t *ent) +{ + trace_t trace; + + trace = SVHL_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, 0, ent); + + if (trace.startsolid) + return &SVHL_Edict[0]; + + return NULL; +} + +/* +================== +SV_ClipMoveToEntity + +Handles selection or creation of a clipping hull, and offseting (and +eventually rotation) of the end points +================== +*/ +trace_t SVHL_ClipMoveToEntity (hledict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel) //hullnum overrides min/max for q1 style bsps +{ + trace_t trace; + model_t *model; + +/* +#ifdef Q2BSPS + if (ent->v->solid == SOLID_BSP) + if (sv.models[(int)ent->v->modelindex] && (sv.models[(int)ent->v->modelindex]->fromgame == fg_quake2 || sv.models[(int)ent->v->modelindex]->fromgame == fg_quake3)) + { + trace = CM_TransformedBoxTrace (start, end, mins, maxs, sv.models[(int)ent->v->modelindex]->hulls[0].firstclipnode, MASK_PLAYERSOLID, ent->v->origin, ent->v->angles); + if (trace.fraction < 1 || trace.startsolid) + trace.ent = ent; + return trace; + } +#endif +*/ + +// get the clipping hull + if (ent->v.solid == SOLID_BSP) + { + model = sv.models[(int)ent->v.modelindex]; + if (!model || (model->type != mod_brush && model->type != mod_heightmap)) + SV_Error("SOLID_BSP with non bsp model (classname: %s)", SVHL_Globals.stringbase+ent->v.classname); + } + else + { + vec3_t boxmins, boxmaxs; + VectorSubtract (ent->v.mins, maxs, boxmins); + VectorSubtract (ent->v.maxs, mins, boxmaxs); + SV_HullForBox(boxmins, boxmaxs); + model = NULL; + } + +// trace a line through the apropriate clipping hull + if (ent->v.solid != SOLID_BSP) + { + ent->v.angles[0]*=-1; //carmack made bsp models rotate wrongly. + TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles); + ent->v.angles[0]*=-1; + } + else + { + TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles); + } + +// fix trace up by the offset + if (trace.fraction != 1) + { + if (!model && hitmodel && ent->v.solid != SOLID_BSP && ent->v.modelindex > 0) + { + //okay, we hit the bbox + + model_t *model; + if (ent->v.modelindex < 1 || ent->v.modelindex >= MAX_MODELS) + SV_Error("SV_ClipMoveToEntity: modelindex out of range\n"); + model = sv.models[ (int)ent->v.modelindex ]; + if (!model) + { //if the model isn't loaded, load it. + //this saves on memory requirements with mods that don't ever use this. + model = sv.models[(int)ent->v.modelindex] = Mod_ForName(sv.strings.model_precache[(int)ent->v.modelindex], false); + } + + if (model && model->funcs.Trace) + { + //do the second trace + TransformedTrace(model, hullnum, ent->v.frame, start, end, mins, maxs, &trace, ent->v.origin, ent->v.angles); + } + } + + if (trace.startsolid) + { + if (ent != &SVHL_Edict[0]) + Con_Printf("Trace started solid\n"); + } + } + +// did we clip the move? + if (trace.fraction < 1 || trace.startsolid ) + trace.ent = ent; + + return trace; +} + +#ifdef Q2BSPS +float *area_mins, *area_maxs; +hledict_t **area_list; +int area_count, area_maxcount; +void SVHL_AreaEdicts_r (areanode_t *node) +{ + link_t *l, *next, *start; + hledict_t *check; + int count; + + count = 0; + + // touch linked edicts + start = &node->solid_edicts; + + for (l=start->next ; l != start ; l = next) + { + next = l->next; + check = HLEDICT_FROM_AREA(l); + +// if (check->v.solid == SOLID_NOT) +// continue; // deactivated + if (check->v.absmin[0] > area_maxs[0] + || check->v.absmin[1] > area_maxs[1] + || check->v.absmin[2] > area_maxs[2] + || check->v.absmax[0] < area_mins[0] + || check->v.absmax[1] < area_mins[1] + || check->v.absmax[2] < area_mins[2]) + continue; // not touching + + if (area_count == area_maxcount) + { + Con_Printf ("SV_AreaEdicts: MAXCOUNT\n"); + return; + } + + area_list[area_count] = check; + area_count++; + } + + if (node->axis == -1) + return; // terminal node + + // recurse down both sides + if ( area_maxs[node->axis] > node->dist ) + SVHL_AreaEdicts_r ( node->children[0] ); + if ( area_mins[node->axis] < node->dist ) + SVHL_AreaEdicts_r ( node->children[1] ); +} + +/* +================ +SV_AreaEdicts +================ +*/ +int SVHL_AreaEdicts (vec3_t mins, vec3_t maxs, hledict_t **list, int maxcount) +{ + area_mins = mins; + area_maxs = maxs; + area_list = list; + area_count = 0; + area_maxcount = maxcount; + + SVHL_AreaEdicts_r (sv_areanodes); + + return area_count; +} + +#endif +//=========================================================================== + + +/* +==================== +SV_ClipToEverything + +like SV_ClipToLinks, but doesn't use the links part. This can be used for checking triggers, solid entities, not-solid entities. +Sounds pointless, I know. +==================== +*/ +void SVHL_ClipToEverything (hlmoveclip_t *clip) +{ + int e; + trace_t trace; + hledict_t *touch; + for (e=1 ; eisfree) + continue; + if (touch->v.solid == SOLID_NOT && !((int)touch->v.flags & FL_FINDABLE_NONSOLID)) + continue; + if (touch->v.solid == SOLID_TRIGGER && !((int)touch->v.flags & FL_FINDABLE_NONSOLID)) + continue; + + if (touch == clip->passedict) + continue; + + if (clip->type & MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP) + continue; + + if (clip->passedict) + { + // don't clip corpse against character + if (clip->passedict->v.solid == SOLID_CORPSE && (touch->v.solid == SOLID_SLIDEBOX || touch->v.solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip->passedict->v.solid == SOLID_SLIDEBOX && touch->v.solid == SOLID_CORPSE) + continue; + +// if (!((int)clip->passedict->v.dimension_hit & (int)touch->v.dimension_solid)) +// continue; + } + + if (clip->boxmins[0] > touch->v.absmax[0] + || clip->boxmins[1] > touch->v.absmax[1] + || clip->boxmins[2] > touch->v.absmax[2] + || clip->boxmaxs[0] < touch->v.absmin[0] + || clip->boxmaxs[1] < touch->v.absmin[1] + || clip->boxmaxs[2] < touch->v.absmin[2] ) + continue; + + if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0]) + continue; // points never interact + + // might intersect, so do an exact clip + if (clip->trace.allsolid) + return; + if (clip->passedict) + { + if (touch->v.owner == clip->passedict) + continue; // don't clip against own missiles + if (clip->passedict->v.owner == touch) + continue; // don't clip against owner + } + + if ((int)touch->v.flags & FL_MONSTER) + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + else + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + if (trace.allsolid || trace.startsolid || + trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + clip->trace = trace; + } + } +} + +/* +==================== +SV_ClipToLinks + +Mins and maxs enclose the entire area swept by the move +==================== +*/ +void SVHL_ClipToLinks ( areanode_t *node, hlmoveclip_t *clip ) +{ + link_t *l, *next; + hledict_t *touch; + trace_t trace; + +// touch linked edicts + for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) + { + next = l->next; + touch = HLEDICT_FROM_AREA(l); + if (touch->v.solid == SOLID_NOT) + continue; + if (touch == clip->passedict) + continue; + if (touch->v.solid == SOLID_TRIGGER) + continue; + + if (clip->type & MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP) + continue; + + if (clip->passedict) + { + // don't clip corpse against character + if (clip->passedict->v.solid == SOLID_CORPSE && (touch->v.solid == SOLID_SLIDEBOX || touch->v.solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip->passedict->v.solid == SOLID_SLIDEBOX && touch->v.solid == SOLID_CORPSE) + continue; + +// if (!((int)clip->passedict->xv->dimension_hit & (int)touch->xv->dimension_solid)) +// continue; + } + + if (clip->boxmins[0] > touch->v.absmax[0] + || clip->boxmins[1] > touch->v.absmax[1] + || clip->boxmins[2] > touch->v.absmax[2] + || clip->boxmaxs[0] < touch->v.absmin[0] + || clip->boxmaxs[1] < touch->v.absmin[1] + || clip->boxmaxs[2] < touch->v.absmin[2] ) + continue; + + if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0]) + continue; // points never interact + + // might intersect, so do an exact clip + if (clip->trace.allsolid) + return; + if (clip->passedict) + { + if (touch->v.owner == clip->passedict) + continue; // don't clip against own missiles + if (clip->passedict->v.owner == touch) + continue; // don't clip against owner + } + + if ((int)touch->v.flags & FL_MONSTER) + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + else + trace = SVHL_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + if (trace.allsolid || trace.startsolid || + trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + clip->trace = trace; + } + } + +// recurse down both sides + if (node->axis == -1) + return; + + if ( clip->boxmaxs[node->axis] > node->dist ) + SVHL_ClipToLinks ( node->children[0], clip ); + if ( clip->boxmins[node->axis] < node->dist ) + SVHL_ClipToLinks ( node->children[1], clip ); +} + +/* +================== +SV_Move +================== +*/ +trace_t SVHL_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, int forcehull, hledict_t *passedict) +{ + hlmoveclip_t clip; + int i; + int hullnum; + + memset ( &clip, 0, sizeof ( clip ) ); + if (forcehull) + hullnum = forcehull; + else if (sv_compatiblehulls.value) + hullnum = 0; + else + { + int diff; + int best; + hullnum = 0; + best = 8192; + //x/y pos/neg are assumed to be the same magnitute. + //z pos/height are assumed to be different from all the others. + for (i = 0; i < MAX_MAP_HULLSM; i++) + { + if (!sv.worldmodel->hulls[i].available) + continue; +#define sq(x) ((x)*(x)) + diff = sq(sv.worldmodel->hulls[i].clip_maxs[2] - maxs[2]) + + sq(sv.worldmodel->hulls[i].clip_mins[2] - mins[2]) + + sq(sv.worldmodel->hulls[i].clip_maxs[1] - maxs[1]) + + sq(sv.worldmodel->hulls[i].clip_mins[0] - mins[0]); + if (diff < best) + { + best = diff; + hullnum=i; + } + } + hullnum++; + } + +// clip to world + clip.trace = SVHL_ClipMoveToEntity ( &SVHL_Edict[0], start, mins, maxs, end, hullnum, false); + + clip.start = start; + clip.end = end; + clip.mins = mins; + clip.maxs = maxs; + clip.type = type; + clip.passedict = passedict; + clip.hullnum = hullnum; + + if (type & MOVE_MISSILE) + { + for (i=0 ; i<3 ; i++) + { + clip.mins2[i] = -15; + clip.maxs2[i] = 15; + } + } + else + { + VectorCopy (mins, clip.mins2); + VectorCopy (maxs, clip.maxs2); + } + +// create the bounding box of the entire move + SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); + +// clip to entities + if (clip.type & MOVE_EVERYTHING) + SVHL_ClipToEverything (&clip); + else + SVHL_ClipToLinks ( sv_areanodes, &clip ); + + if (clip.trace.startsolid) + clip.trace.fraction = 0; + + if (!clip.trace.ent) + return clip.trace; + + return clip.trace; +} + +#endif diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 9d6f4fa6c..c386257ec 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -1,4 +1,4 @@ -#include "quakedef.h" +#include "qwsvdef.h" //An implementation of a Q3 server... //requires qvm implementation and existing q3 client stuff (or at least the overlapping stuff in q3common.c). diff --git a/engine/sw/d_sprite.c b/engine/sw/d_sprite.c index f6ef8d4ee..7b814672b 100644 --- a/engine/sw/d_sprite.c +++ b/engine/sw/d_sprite.c @@ -1048,9 +1048,9 @@ void D_DrawSprite (void) if (ymin >= ymax) return; // doesn't cross any scans at all - cachewidth = r_spritedesc.pspriteframe->width; - sprite_height = r_spritedesc.pspriteframe->height; - cacheblock = (qbyte *)&r_spritedesc.pspriteframe->pixels[0]; + cachewidth = r_spritedesc.pspriteframe->p.width; + sprite_height = r_spritedesc.pspriteframe->p.height; + cacheblock = (qbyte *)&r_spritedesc.pspriteframe->p.d.data[0]; // copy the first vertex to the last vertex, so we don't have to deal with // wrapping diff --git a/engine/sw/r_sprite.c b/engine/sw/r_sprite.c index d38b0ad8e..5b069dd71 100644 --- a/engine/sw/r_sprite.c +++ b/engine/sw/r_sprite.c @@ -297,8 +297,8 @@ void R_DrawSprite (void) r_spritedesc.pspriteframe = R_GetSpriteFrame (currententity); - sprite_width = r_spritedesc.pspriteframe->width; - sprite_height = r_spritedesc.pspriteframe->height; + sprite_width = r_spritedesc.pspriteframe->p.width; + sprite_height = r_spritedesc.pspriteframe->p.height; // TODO: make this caller-selectable if (psprite->type == SPR_FACING_UPRIGHT) diff --git a/engine/sw/sw_draw.c b/engine/sw/sw_draw.c index 2fc35c13d..7cbf9aa2f 100644 --- a/engine/sw/sw_draw.c +++ b/engine/sw/sw_draw.c @@ -130,10 +130,10 @@ mpic_t *SWDraw_SafeCachePic (char *extpath) if (image[i*4+3] < 64) // 25% threshhold { ((mpic_t*)dat)->flags |= MPIC_ALPHA; - dat->data[i] = 255; + dat->d.data[i] = 255; } else - dat->data[i] = GetPaletteNoFB(image[i*4], image[i*4+1], image[i*4+2]); + dat->d.data[i] = GetPaletteNoFB(image[i*4], image[i*4+1], image[i*4+2]); } BZ_Free(image); @@ -165,10 +165,10 @@ mpic_t *SWDraw_SafeCachePic (char *extpath) if (image[i*4+3] < 64) // 25% threshhold { ((mpic_t*)dat)->flags |= MPIC_ALPHA; - dat->data[i] = 255; + dat->d.data[i] = 255; } else - dat->data[i] = GetPaletteNoFB(image[i*4], image[i*4+1], image[i*4+2]); + dat->d.data[i] = GetPaletteNoFB(image[i*4], image[i*4+1], image[i*4+2]); } BZ_Free(image); @@ -200,10 +200,10 @@ mpic_t *SWDraw_SafeCachePic (char *extpath) if (image[i*4+3] < 64) // 25% threshhold { ((mpic_t*)dat)->flags |= MPIC_ALPHA; - dat->data[i] = 255; + dat->d.data[i] = 255; } else - dat->data[i] = GetPaletteNoFB(image[i*4], image[i*4+1], image[i*4+2]); + dat->d.data[i] = GetPaletteNoFB(image[i*4], image[i*4+1], image[i*4+2]); } BZ_Free(image); @@ -377,7 +377,7 @@ void SWDraw_Init (void) pic = (mpic_t *)SWDraw_MallocPic("pics/conchars.pcx"); //safe from host_hunkmarks... if (pic) { - draw_chars = pic->data; + draw_chars = pic->d.data; s = pic->width*pic->height; for (i = 0; i < s; i++) //convert 255s to 0, q1's transparent colour @@ -483,7 +483,7 @@ void SWDraw_Init (void) int j; for (j = 0; j < 128*128; j++) - dat->data[j] = (draw_chars[j] == 255 || !draw_chars[j]) ? draw_chars[j] ^ 255 : draw_chars[j]; + dat->d.data[j] = (draw_chars[j] == 255 || !draw_chars[j]) ? draw_chars[j] ^ 255 : draw_chars[j]; dat->width = dat->height = 128; dat->flags = 1; @@ -504,7 +504,7 @@ void SWDraw_Init (void) } r_rectdesc.width = draw_backtile->width; r_rectdesc.height = draw_backtile->height; - r_rectdesc.ptexbytes = draw_backtile->data; + r_rectdesc.ptexbytes = draw_backtile->d.data; r_rectdesc.rowbytes = draw_backtile->width; } @@ -1071,7 +1071,7 @@ void SWDraw_Pic (int x, int y, mpic_t *pic) return;//Sys_Error ("Draw_Pic: bad coordinates"); } - source = pic->data; + source = pic->d.data; if (r_pixbytes == 1) { @@ -1131,7 +1131,7 @@ void SWDraw_TransSubPic(int x, int y, mpic_t *pic, int srcx, int srcy, int width Sys_Error ("Draw_Pic: bad coordinates"); } - source = pic->data + srcy * pic->width + srcx; + source = pic->d.data + srcy * pic->width + srcx; if (r_pixbytes == 1) { @@ -1229,7 +1229,7 @@ void SWDraw_SubPic(int x, int y, mpic_t *pic, int srcx, int srcy, int width, int Sys_Error ("Draw_Pic: bad coordinates"); } - source = pic->data + srcy * pic->width + srcx; + source = pic->d.data + srcy * pic->width + srcx; if (r_pixbytes == 1) { @@ -1290,7 +1290,7 @@ void SWDraw_TransPic (int x, int y, mpic_t *pic) Sys_Error ("Draw_TransPic: bad coordinates"); } - source = pic->data; + source = pic->d.data; if (r_pixbytes == 1) { @@ -2000,15 +2000,15 @@ void SWDraw_Image (float xp, float yp, float wp, float hp, float s1, float t1, f // draw the pic if (r_pixbytes == 1) { - SWDraw_SubImage8(xp, yp, wp, hp, s1, t1, s2, t2, pic->width, pic->height, pic->data); + SWDraw_SubImage8(xp, yp, wp, hp, s1, t1, s2, t2, pic->width, pic->height, pic->d.data); } else if (r_pixbytes == 2) { - SWDraw_SubImage16(xp, yp, wp, hp, s1, t1, s2, t2, pic->width, pic->height, pic->data); + SWDraw_SubImage16(xp, yp, wp, hp, s1, t1, s2, t2, pic->width, pic->height, pic->d.data); } else { - SWDraw_SubImage32(xp, yp, wp, hp, s1, t1, s2, t2, pic->width, pic->height, pic->data); + SWDraw_SubImage32(xp, yp, wp, hp, s1, t1, s2, t2, pic->width, pic->height, pic->d.data); } } @@ -2062,7 +2062,7 @@ void SWDraw_ConsoleBackground (int lines) //sprintf (ver, "start commands with a \\ character %4.2f", VERSION); sprintf (ver, "%i", build_number()); - dest = conback->data + w + w*186 - 11 - 8*strlen(ver); + dest = conback->d.data + w + w*186 - 11 - 8*strlen(ver); // memcpy(saveback, conback->data + w*186, w*8); for (x=0 ; xdata + v*w; + src = conback->d.data + v*w; f = 0; fstep = w*0x10000/vid.conwidth; for (x=0 ; xdata + v*w; + src = conback->d.data + v*w; if (vid.conwidth == w) memcpy (dest, src, vid.conwidth); else @@ -2133,7 +2133,7 @@ void SWDraw_ConsoleBackground (int lines) { v = (vid.conheight - lines + y)*h/vid.conheight; - src = conback->data + v*w; + src = conback->d.data + v*w; // if (vid.conwidth == w) // memcpy (dest16, src, vid.conwidth); // else @@ -2175,9 +2175,9 @@ void SWDraw_ConsoleBackground (int lines) for (y=0 ; ydata + v*w; + src = conback->d.data + v*w; v = (vid.conheight - lines + y)*(h-1)/vid.conheight+1; - src2 = conback->data + v*w; + src2 = conback->d.data + v*w; v = (vid.conheight - lines + y)*(h-1)/vid.conheight; vf = (((vid.conheight - lines + y)*(h-1.0)/vid.conheight) - v) * 255; @@ -2217,7 +2217,7 @@ void SWDraw_ConsoleBackground (int lines) for (y=0 ; ydata + v*w; + src = conback->d.data + v*w; f = 0; fstep = w*0x10000/vid.conwidth; @@ -2236,7 +2236,7 @@ void SWDraw_ConsoleBackground (int lines) for (y=0 ; ydata + v*w; + src = conback->d.data + v*w; f = 0; fstep = w*0x10000/vid.conwidth; @@ -2674,7 +2674,7 @@ Call before beginning any disc IO. void SWDraw_BeginDisc (void) { if (draw_disc) - D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24); + D_BeginDirectRect (vid.width - 24, 0, draw_disc->d.data, 24, 24); } diff --git a/engine/sw/sw_model.c b/engine/sw/sw_model.c index 0625c903d..d0102fa28 100644 --- a/engine/sw/sw_model.c +++ b/engine/sw/sw_model.c @@ -3531,8 +3531,8 @@ void * SWMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int version) Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); *ppframe = pspriteframe; - pspriteframe->width = width; - pspriteframe->height = height; + pspriteframe->p.width = width; + pspriteframe->p.height = height; origin[0] = LittleLong (pinframe->origin[0]); origin[1] = LittleLong (pinframe->origin[1]); @@ -3549,7 +3549,7 @@ void * SWMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int version) { //downgrade quality ppixin = (unsigned char *)(pinframe + 1); - ppixout = (unsigned char *)&pspriteframe->pixels[0]; + ppixout = (unsigned char *)&pspriteframe->p.d.data[0]; for (i=0 ; ipixels[0], (qbyte *)(pinframe + 1), size); + Q_memcpy (&pspriteframe->p.d.data[0], (qbyte *)(pinframe + 1), size); } else if (r_pixbytes == 2) { @@ -3571,7 +3571,7 @@ void * SWMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int version) { //downgrade quality ppixin = (unsigned char *)(pinframe + 1); - p16out = (unsigned short *)&pspriteframe->pixels[0]; + p16out = (unsigned short *)&pspriteframe->p.d.data[0]; for (i=0 ; ipixels[0]; + p16out = (unsigned short *)&pspriteframe->p.d.data[0]; for (i=0 ; ipixels[0]; + p32out = (unsigned int *)&pspriteframe->p.d.data[0]; for (i=0 ; ipixels[0]; + p32out = (unsigned int *)&pspriteframe->p.d.data[0]; for (i=0 ; iframes[mod->numframes].frameptr = Hunk_AllocName(sizeof(mspriteframe_t)+width*r_pixbytes*height, loadname); - frame->width = width; - frame->height = height; + frame->p.width = width; + frame->p.height = height; origin[0] = LittleLong (pframetype->origin_x); origin[1] = LittleLong (pframetype->origin_y); frame->up = -origin[1]; - frame->down = frame->height - origin[1]; + frame->down = frame->p.height - origin[1]; frame->left = -origin[0]; - frame->right = frame->width - origin[0]; + frame->right = frame->p.width - origin[0]; if (r_pixbytes == 4) { for (j = 0; j < width*height; j++) { - frame->pixels[j*4+0] = framedata[j*4+2]; - frame->pixels[j*4+1] = framedata[j*4+1]; - frame->pixels[j*4+2] = framedata[j*4+0]; - frame->pixels[j*4+3] = framedata[j*4+3]; + frame->p.d.data[j*4+0] = framedata[j*4+2]; + frame->p.d.data[j*4+1] = framedata[j*4+1]; + frame->p.d.data[j*4+2] = framedata[j*4+0]; + frame->p.d.data[j*4+3] = framedata[j*4+3]; } } else @@ -3886,9 +3886,9 @@ qboolean SWMod_LoadSprite2Model (model_t *mod, void *buffer) for (j = 0; j < width*height; j++) { if (!framedata[j*4+3]) //make sure - frame->pixels[j] = 255; + frame->p.d.data[j] = 255; else - frame->pixels[j] = GetPaletteNoFB(framedata[j*4+0], framedata[j*4+1], framedata[j*4+2]); + frame->p.d.data[j] = GetPaletteNoFB(framedata[j*4+0], framedata[j*4+1], framedata[j*4+2]); } } BZ_Free(framedata); diff --git a/engine/sw/vid_win2.c b/engine/sw/vid_win2.c index 0f55c3fef..e2926e694 100644 --- a/engine/sw/vid_win2.c +++ b/engine/sw/vid_win2.c @@ -946,8 +946,7 @@ void SWVID_Shutdown (void) return; } #endif - IN_DeactivateMouse(); - IN_ShowMouse(); + IN_UpdateGrabs(false, false); SWimp_Shutdown(); } @@ -964,37 +963,7 @@ void SWVID_Update (vrect_t *rects) //end frame... #endif SWimp_EndFrame(); - // handle the mouse state when windowed if that's changed - if (!vid_isfullscreen) - { - mouse = false; - if (_windowed_mouse.value) - if (key_dest == key_game)// || key_dest == key_menu) - mouse = true; - } - else - { - if (key_dest == key_menu) - mouse = false; - else - mouse = true; - } - if (!ActiveApp) - mouse = false; //nope can't have it. - if (mouse != mouseactive) - { - if (mouse) - { - IN_ActivateMouse(); - IN_HideMouse(); - IN_UpdateClipCursor(); - } - else - { - IN_DeactivateMouse(); - IN_ShowMouse(); - } - } + IN_UpdateGrabs(vid_isfullscreen, ActiveApp); } void SWVID_SetCaption(char *text)