From ffc2a085893a1de8ee469f0d0085433e697615a1 Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 3 May 2013 04:28:08 +0000 Subject: [PATCH] pass network addresses around as a pointer rather than as a struct. They've grown quite a bit from vanilla code and can now be quite large. this should give more efficient network filtering+matching. Added version+time+date to segfault lots. try to use vbo+vao as needed. added a manifest file in order to disable uac emulation and its virtual store lies. particles now support a sort of namespace. eg: an effect called "cfg.effect" will load up the 'cfg' particle config and use its 'effect' effect (but not replace any explicit effects). You can still create particle effects called 'cfg.effect' with no issue. Added support for fsarchive plugins. Added a sys_register_file_associations command. .bsp not yet handled, but demo playback should work fine. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4324 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 18 +- engine/client/cl_cg.c | 4 +- engine/client/cl_demo.c | 4 +- engine/client/cl_main.c | 75 ++--- engine/client/cl_master.h | 2 +- engine/client/cl_parse.c | 4 +- engine/client/cl_plugin.inc | 22 +- engine/client/cl_ui.c | 16 +- engine/client/client.h | 10 +- engine/client/clq3_parse.c | 10 +- engine/client/console.c | 2 +- engine/client/keys.c | 15 +- engine/client/keys.h | 12 +- engine/client/m_download.c | 34 ++- engine/client/m_items.c | 11 +- engine/client/m_master.c | 14 +- engine/client/m_mp3.c | 160 ++++++++--- engine/client/m_multi.c | 12 +- engine/client/m_options.c | 18 +- engine/client/m_single.c | 3 +- engine/client/merged.h | 2 +- engine/client/net_master.c | 58 ++-- engine/client/p_classic.c | 7 - engine/client/p_null.c | 10 +- engine/client/p_script.c | 228 ++++++++++----- engine/client/pr_clcmd.c | 16 +- engine/client/pr_csqc.c | 93 ++++--- engine/client/pr_menu.c | 40 ++- engine/client/pr_skelobj.c | 164 ++++++++++- engine/client/quake.manifest | 9 + engine/client/snd_directx.c | 2 +- engine/client/snd_sdl.c | 3 +- engine/client/sys_win.c | 336 ++++++++++++++++++++-- engine/client/textedit.c | 1 + engine/client/valid.c | 4 +- engine/client/winquake.rc | 4 + engine/common/bothdefs.h | 18 +- engine/common/cmd.c | 17 +- engine/common/com_mesh.c | 29 +- engine/common/common.c | 205 +++++++++++--- engine/common/common.h | 32 ++- engine/common/console.h | 2 +- engine/common/fs.c | 75 +++-- engine/common/fs.h | 27 +- engine/common/fs_pak.c | 34 +-- engine/common/fs_stdio.c | 49 ++-- engine/common/fs_win32.c | 45 +-- engine/common/fs_zip.c | 32 +-- engine/common/gl_q2bsp.c | 2 + engine/common/log.c | 2 +- engine/common/net.h | 29 +- engine/common/net_chan.c | 31 ++- engine/common/net_ssl_winsspi.c | 12 +- engine/common/net_wins.c | 480 +++++++++++++++++--------------- engine/common/netinc.h | 10 +- engine/common/particles.h | 2 - engine/common/plugin.c | 178 +++++++----- engine/common/pr_bgcmd.c | 368 +++++++++++++++++++----- engine/common/pr_common.h | 22 +- engine/common/q3common.c | 24 +- engine/common/qvm.c | 75 +++-- engine/common/sys.h | 8 +- engine/common/sys_win_threads.c | 4 +- engine/common/vm.h | 8 +- engine/gl/gl_backend.c | 62 +++-- engine/gl/gl_heightmap.c | 2 +- engine/gl/gl_model.c | 31 ++- engine/gl/gl_model.h | 12 +- engine/gl/gl_rsurf.c | 40 ++- engine/gl/gl_shader.c | 2 +- engine/gl/gl_vidcommon.c | 31 ++- engine/gl/gl_vidlinuxglx.c | 104 +++---- engine/gl/gl_vidnt.c | 6 + engine/gl/glquake.h | 1 + engine/gl/glsupp.h | 4 + engine/http/ftpserver.c | 18 +- engine/http/httpclient.c | 6 + engine/http/httpserver.c | 2 +- engine/http/webgen.c | 12 +- engine/qclib/hash.c | 42 +++ engine/qclib/hash.h | 2 + engine/qclib/initlib.c | 3 + engine/qclib/progslib.h | 1 + engine/server/pr_cmds.c | 226 ++++++++------- engine/server/server.h | 2 +- engine/server/sv_ccmds.c | 54 ++-- engine/server/sv_main.c | 170 ++++++----- engine/server/sv_master.c | 2 +- engine/server/sv_mvd.c | 4 +- engine/server/sv_send.c | 2 +- engine/server/sv_sys_unix.c | 29 +- engine/server/sv_user.c | 14 +- engine/server/svq3_game.c | 20 +- 93 files changed, 2811 insertions(+), 1336 deletions(-) create mode 100644 engine/client/quake.manifest diff --git a/engine/Makefile b/engine/Makefile index 027c01052..f609023f2 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -6,7 +6,7 @@ STRIPFLAGS=--strip-unneeded --remove-section=.comment CPUOPTIMIZATIONS= -BASE_DIR=. +BASE_DIR=$(realpath .) SVNREVISION:=-DSVNREVISION=$(shell test -d .svn && svnversion || echo -) @@ -1364,13 +1364,19 @@ debugdir: endif plugins: - ifneq ($(shell grep all ../plugins/Makefile),) - $(MAKE) -C ../plugins - else - @-echo no plugins directory installed - endif + @if test -e ../plugins/Makefile; \ + then echo falala $(MAKE) -C ../plugins; \ + else echo no plugins directory installed; \ + fi plugins: +plugins-rel: + @if test -e ../plugins/Makefile; \ + then $(MAKE) native -C ../plugins OUT_DIR="$(RELEASE_DIR)" CC="$(CC) $(W32_CFLAGS) $(RELEASE_CFLAGS)" BASE_CFLAGS="$(BASE_CFLAGS)"; \ + else echo no plugins directory installed; \ + fi +plugins-rel: + help: @-echo "Specfic targets:" @-echo "clean - removes all output (use make dirs afterwards)" diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index ae32cad27..f7900fefc 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -489,10 +489,10 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con break; case CG_CVAR_REGISTER: if (arg[0]) - VALIDATEPOINTER(arg[0], sizeof(vmcvar_t)); + VALIDATEPOINTER(arg[0], sizeof(q3vmcvar_t)); return VMQ3_Cvar_Register(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3])); case CG_CVAR_UPDATE: - VALIDATEPOINTER(arg[0], sizeof(vmcvar_t)); + VALIDATEPOINTER(arg[0], sizeof(q3vmcvar_t)); return VMQ3_Cvar_Update(VM_POINTER(arg[0])); case CG_CVAR_SET: diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index cc7dc03b9..16800fe60 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1538,7 +1538,7 @@ void CL_PlayDemo(char *demoname) cls.state = ca_demostart; net_message.packing = SZ_RAWBYTES; - Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0); + Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, 0); demtime = 0; cl.gametime = 0; cl.gametimemark = demtime; @@ -1611,7 +1611,7 @@ void CL_QTVPlay (vfsfile_t *newf, qboolean iseztv) cls.state = ca_demostart; net_message.packing = SZ_RAWBYTES; - Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0); + Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, 0); demtime = -BUFFERTIME; cl.gametime = -BUFFERTIME; cl.gametimemark = demtime; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d0cc1c536..5d0861d0a 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -333,7 +333,7 @@ void CL_Quit_f (void) Sys_Quit (); } -void CL_ConnectToDarkPlaces(char *challenge, netadr_t adr) +void CL_ConnectToDarkPlaces(char *challenge, netadr_t *adr) { char data[2048]; cls.fteprotocolextensions = 0; @@ -373,7 +373,7 @@ void CL_SupportedFTEExtensions(int *pext1, int *pext2) } #endif -char *CL_GUIDString(netadr_t adr) +char *CL_GUIDString(netadr_t *adr) { static qbyte buf[2048]; static int buflen; @@ -483,7 +483,7 @@ void CL_SendConnectPacket (int mtu, return; } - NET_AdrToString(data, sizeof(data), adr); + NET_AdrToString(data, sizeof(data), &adr); Cvar_ForceSet(&cl_serveraddress, data); if (!NET_IsClientLegal(&adr)) @@ -526,7 +526,7 @@ void CL_SendConnectPacket (int mtu, #ifdef Q3CLIENT if (cls.protocol == CP_QUAKE3) { //q3 requires some very strange things. - CLQ3_SendConnectPacket(adr); + CLQ3_SendConnectPacket(&adr); return; } #endif @@ -590,11 +590,11 @@ void CL_SendConnectPacket (int mtu, #endif cls.netchan.compress = false; - info = CL_GUIDString(adr); + info = CL_GUIDString(&adr); if (info) Q_strncatz(data, va("0x%x \"%s\"\n", PROTOCOL_INFO_GUID, info), sizeof(data)); - NET_SendPacket (NS_CLIENT, strlen(data), data, adr); + NET_SendPacket (NS_CLIENT, strlen(data), data, &adr); cl.splitclients = 0; } @@ -697,7 +697,7 @@ void CL_CheckForResend (void) SCR_EndLoadingPlaque(); return; } - NET_AdrToString(data, sizeof(data), adr); + NET_AdrToString(data, sizeof(data), &adr); /*eat up the server's packets, to clear any lingering loopback packets*/ while(NET_GetPacket (NS_SERVER, 0) >= 0) @@ -728,7 +728,7 @@ void CL_CheckForResend (void) SVC_DirectConnect(); } else - CL_ConnectToDarkPlaces("", adr); + CL_ConnectToDarkPlaces("", &adr); } else CL_SendConnectPacket (8192-16, Net_PextMask(1, false), Net_PextMask(2, false), false); @@ -785,7 +785,7 @@ void CL_CheckForResend (void) //Q3 clients send their cdkey to the q3 authorize server. //they send this packet with the challenge. //and the server will refuse the client if it hasn't sent it. - CLQ3_SendAuthPacket(adr); + CLQ3_SendAuthPacket(&adr); #endif Con_TPrintf (TLC_CONNECTINGTO, cls.servername); @@ -805,7 +805,7 @@ void CL_CheckForResend (void) if (contype & 1) { Q_snprintfz (data, sizeof(data), "%c%c%c%cgetchallenge\n", 255, 255, 255, 255); - NET_SendPacket (NS_CLIENT, strlen(data), data, adr); + NET_SendPacket (NS_CLIENT, strlen(data), data, &adr); } /*NQ*/ #ifdef NQPROT @@ -836,7 +836,7 @@ void CL_CheckForResend (void) MSG_WriteString(&sb, "getchallenge"); *(int*)sb.data = LongSwap(NETFLAG_CTL | sb.cursize); - NET_SendPacket (NS_CLIENT, sb.cursize, sb.data, adr); + NET_SendPacket (NS_CLIENT, sb.cursize, sb.data, &adr); } #endif @@ -1056,8 +1056,7 @@ void CL_Rcon_f (void) NET_StringToAdr (rcon_address.string, PORT_QWSERVER, &to); } - NET_SendPacket (NS_CLIENT, strlen(message)+1, message - , to); + NET_SendPacket (NS_CLIENT, strlen(message)+1, message, &to); } @@ -1072,7 +1071,7 @@ void CL_ClearState (void) int i; #ifndef CLIENTONLY #define serverrunning (sv.state != ss_dead) -#define tolocalserver NET_IsLoopBackAddress(cls.netchan.remote_address) +#define tolocalserver NET_IsLoopBackAddress(&cls.netchan.remote_address) #else #define serverrunning false #define tolocalserver false @@ -1112,7 +1111,7 @@ void CL_ClearState (void) if (cl.playernum[0] == -1) { //left over from q2 connect. - Media_PlayFilm(""); + Media_StopFilm(true); } for (i = 0; i < UPDATE_BACKUP; i++) @@ -1984,7 +1983,7 @@ void CL_Packet_f (void) } *out = 0; - NET_SendPacket (NS_CLIENT, out-send, send, adr); + NET_SendPacket (NS_CLIENT, out-send, send, &adr); if (Cmd_FromGamecode()) { @@ -2217,7 +2216,7 @@ void CL_ConnectionlessPacket (void) if (cls.realserverip.type == NA_INVALID) return; //not done a realip yet - if (NET_CompareBaseAdr(cls.realserverip, net_from) == false) + if (NET_CompareBaseAdr(&cls.realserverip, &net_from) == false) return; //only reply if it came from the real server's ip. data[0] = 0xff; @@ -2234,7 +2233,7 @@ void CL_ConnectionlessPacket (void) Q_snprintfz(data+6, sizeof(data)-6, "%i %i", atoi(MSG_ReadString()), cls.realip_ident); len = strlen(data); - NET_SendPacket (NS_CLIENT, len, &data, net_from); + NET_SendPacket (NS_CLIENT, len, &data, &net_from); return; } @@ -2242,8 +2241,8 @@ void CL_ConnectionlessPacket (void) { if (!strncmp(net_message.data+msg_readcount, "\\chunk", 6)) { - if (NET_CompareBaseAdr(cls.netchan.remote_address, net_from) == false) - if (cls.realserverip.type == NA_INVALID || NET_CompareBaseAdr(cls.realserverip, net_from) == false) + if (NET_CompareBaseAdr(&cls.netchan.remote_address, &net_from) == false) + if (cls.realserverip.type == NA_INVALID || NET_CompareBaseAdr(&cls.realserverip, &net_from) == false) return; //only use it if it came from the real server's ip (this breaks on proxies). MSG_ReadLong(); @@ -2263,7 +2262,7 @@ void CL_ConnectionlessPacket (void) } if (cls.demoplayback == DPB_NONE && net_from.type != NA_LOOPBACK) - Con_TPrintf (TL_ST_COLON, NET_AdrToString (adr, sizeof(adr), net_from)); + Con_TPrintf (TL_ST_COLON, NET_AdrToString (adr, sizeof(adr), &net_from)); // Con_DPrintf ("%s", net_message.data + 4); if (c == S2C_CHALLENGE) @@ -2322,7 +2321,7 @@ void CL_ConnectionlessPacket (void) lasttime = curtime; cls.protocol = CP_NETQUAKE; - CL_ConnectToDarkPlaces(s+9, net_from); + CL_ConnectToDarkPlaces(s+9, &net_from); } else Con_Printf("\nChallenge from another protocol, ignoring DP challenge\n"); @@ -2434,7 +2433,7 @@ void CL_ConnectionlessPacket (void) } else if (!strcmp(s, "disconnect")) { - if (NET_CompareAdr(net_from, cls.netchan.remote_address)) + if (NET_CompareAdr(&net_from, &cls.netchan.remote_address)) { Con_Printf ("disconnect\n"); CL_Disconnect_f(); @@ -2464,7 +2463,7 @@ void CL_ConnectionlessPacket (void) { Con_Printf ("accept\n"); Validation_Apply_Ruleset(); - Netchan_Setup(NS_CLIENT, &cls.netchan, net_from, cls.qport); + Netchan_Setup(NS_CLIENT, &cls.netchan, &net_from, cls.qport); CL_ParseEstablished(); Con_DPrintf ("CL_EstablishConnection: connected to %s\n", cls.servername); @@ -2511,7 +2510,7 @@ client_connect: //fixme: make function } compress = cls.netchan.compress; mtu = cls.netchan.fragmentsize; - Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.qport); + Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, cls.qport); cls.netchan.fragmentsize = mtu; cls.netchan.compress = compress; CL_ParseEstablished(); @@ -2657,7 +2656,7 @@ void CLNQ_ConnectionlessPacket(void) Validation_Apply_Ruleset(); - Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.qport); + Netchan_Setup (NS_CLIENT, &cls.netchan, &net_from, cls.qport); CL_ParseEstablished(); cls.netchan.isnqprotocol = true; cls.netchan.compress = 0; @@ -2736,7 +2735,7 @@ void CL_ReadPackets (void) if (net_message.cursize < 6 && (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) //MVDs don't have the whole sequence header thing going on { - Con_TPrintf (TL_RUNTPACKET,NET_AdrToString(adr, sizeof(adr), net_from)); + Con_TPrintf (TL_RUNTPACKET,NET_AdrToString(adr, sizeof(adr), &net_from)); continue; } @@ -2752,10 +2751,10 @@ void CL_ReadPackets (void) // packet from server // if (!cls.demoplayback && - !NET_CompareAdr (net_from, cls.netchan.remote_address)) + !NET_CompareAdr (&net_from, &cls.netchan.remote_address)) { Con_DPrintf ("%s:sequenced packet from wrong server\n" - ,NET_AdrToString(adr, sizeof(adr), net_from)); + ,NET_AdrToString(adr, sizeof(adr), &net_from)); continue; } @@ -3880,11 +3879,21 @@ void CL_StartCinematicOrMenu(void) ol_depth = COM_FDepthFile("video/openinglogos.roq", true); //jk2 if (ol_depth != 0x7fffffff && (ol_depth <= idroq_depth || ol_depth <= idcin_depth)) - Media_PlayFilm("video/openinglogos.roq"); + Media_PlayFilm("video/openinglogos.roq", true); else if (idroq_depth != 0x7fffffff && idroq_depth <= idcin_depth) - Media_PlayFilm("video/idlogo.roq"); + Media_PlayFilm("video/idlogo.roq", true); else if (idcin_depth != 0x7fffffff) - Media_PlayFilm("video/idlog.cin"); + Media_PlayFilm("video/idlog.cin", true); + + //and for fun: + if (COM_FCheckExists("data/local/video/New_Bliz640x480.bik")) + Media_PlayFilm("av:data/local/video/New_Bliz640x480.bik", true); + if (COM_FCheckExists("data/local/video/BlizNorth640x480.bik")) + Media_PlayFilm("av:data/local/video/BlizNorth640x480.bik", true); + if (COM_FCheckExists("data/local/video/eng/d2intro640x292.bik")) + Media_PlayFilm("av:data/local/video/eng/d2intro640x292.bik", true); + if (COM_FCheckExists("Data/Local/Video/ENG/D2x_Intro_640x292.bik")) + Media_PlayFilm("av:Data/Local/Video/ENG/D2x_Intro_640x292.bik", true); } #endif @@ -4050,7 +4059,7 @@ void Host_Init (quakeparms_t *parms) #endif #ifdef PLUGINS - Plug_Init(); + Plug_Initialise(true); #endif #ifdef VM_UI UI_Init(); diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index df2effd36..c45fc3068 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -168,7 +168,7 @@ void CL_QueryServers(void); int Master_CheckPollSockets(void); void MasterInfo_Shutdown(void); void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles); -serverinfo_t *Master_InfoForServer (netadr_t addr); +serverinfo_t *Master_InfoForServer (netadr_t *addr); serverinfo_t *Master_InfoForNum (int num); unsigned int Master_TotalCount(void); unsigned int Master_NumPolled(void); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 9a2d003ff..ca81b498b 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2688,7 +2688,7 @@ void CLQ2_ParseServerData (void) if (cl.playernum[0] == -1) { // playing a cinematic or showing a pic, not a level SCR_EndLoadingPlaque(); - if (!Media_PlayFilm(str)) + if (!Media_PlayFilm(str, false)) { CL_SendClientCommand(true, "nextserver %i", cl.servercount); } @@ -2701,7 +2701,7 @@ void CLQ2_ParseServerData (void) Con_TPrintf (TLC_LINEBREAK_NEWLEVEL); Con_TPrintf (TLC_PC_PS_NL, 2, str); - Media_PlayFilm(""); + Media_StopFilm(true); // need to prep refresh at next oportunity //cl.refresh_prepped = false; diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index 987c55c0d..4635ef193 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -476,7 +476,7 @@ qintptr_t VARGS Plug_Con_NameForNum(void *offset, quintptr_t mask, const qintptr char num = VM_LONG(arg[0]); char *buffer = VM_POINTER(arg[1]); int buffersize = VM_LONG(arg[2]); - if (VM_OOB(arg[1], arg[2]) || buffersize < 1) + if (VM_OOB(arg[1], buffersize) || buffersize < 1) return false; if (qrenderer == QR_NONE) return false; @@ -484,7 +484,23 @@ qintptr_t VARGS Plug_Con_NameForNum(void *offset, quintptr_t mask, const qintptr return Con_NameForNum(num, buffer, buffersize); } - +qintptr_t VARGS Plug_S_RawAudio(void *offset, quintptr_t mask, const qintptr_t *arg) +{ + int sourceid = VM_LONG(arg[0]); + qbyte *data = VM_POINTER(arg[1]); + int speed = VM_LONG(arg[2]); + int samples = VM_LONG(arg[3]); + int channels = VM_LONG(arg[4]); + int width = VM_LONG(arg[5]); + + int datasize = samples * channels * width; + + if (VM_OOB(arg[1], datasize) || datasize < 1) + return false; + + S_RawAudio(sourceid, data, speed, samples, channels, width); + return 0; +} void Plug_Client_Init(void) { @@ -516,6 +532,8 @@ void Plug_Client_Init(void) Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER); + + Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER); } void Plug_Client_Close(plugin_t *plug) diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 84aeeb98e..932c1c30e 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -774,7 +774,7 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con { serverinfo_t *info; NET_StringToAdr(cmdtext + 5, 0, &ui_pings[i]); - info = Master_InfoForServer(ui_pings[i]); + info = Master_InfoForServer(&ui_pings[i]); if (info) { info->special |= SS_KEEPINFO; @@ -1010,10 +1010,10 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con { char *buf = VM_POINTER(arg[1]); char *adr; - serverinfo_t *info = Master_InfoForServer(ui_pings[VM_LONG(arg[0])]); + serverinfo_t *info = Master_InfoForServer(&ui_pings[VM_LONG(arg[0])]); if (info) { - adr = NET_AdrToString(adrbuf, sizeof(adrbuf), info->adr); + adr = NET_AdrToString(adrbuf, sizeof(adrbuf), &info->adr); if (strlen(adr) < VM_LONG(arg[2])) { strcpy(buf, adr); @@ -1037,7 +1037,7 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con { char *buf = VM_POINTER(arg[1]); char *adr; - serverinfo_t *info = Master_InfoForServer(ui_pings[VM_LONG(arg[0])]); + serverinfo_t *info = Master_InfoForServer(&ui_pings[VM_LONG(arg[0])]); if (info) { adr = info->moreinfo->info; @@ -1063,12 +1063,12 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con #endif case UI_CVAR_REGISTER: - if (VM_OOB(arg[0], sizeof(vmcvar_t))) + if (VM_OOB(arg[0], sizeof(q3vmcvar_t))) break; //out of bounds. return VMQ3_Cvar_Register(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3])); case UI_CVAR_UPDATE: - if (VM_OOB(arg[0], sizeof(vmcvar_t))) + if (VM_OOB(arg[0], sizeof(q3vmcvar_t))) break; //out of bounds. return VMQ3_Cvar_Update(VM_POINTER(arg[0])); @@ -1114,7 +1114,7 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con serverinfo_t *info = Master_InfoForNum(VM_LONG(arg[1])); if (info) { - adr = NET_AdrToString(adrbuf, sizeof(adrbuf), info->adr); + adr = NET_AdrToString(adrbuf, sizeof(adrbuf), &info->adr); if (strlen(adr) < VM_LONG(arg[3])) { strcpy(buf, adr); @@ -1477,7 +1477,7 @@ qboolean UI_KeyPress(int key, int unicode, qboolean down) { if (Media_PlayingFullScreen()) { - Media_PlayFilm(""); + Media_StopFilm(true); } UI_OpenMenu(); diff --git a/engine/client/client.h b/engine/client/client.h index 495e1f92c..ff06c2eb9 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1073,8 +1073,8 @@ qboolean CL_MayLerp(void); // #ifdef Q3CLIENT void VARGS CLQ3_SendClientCommand(const char *fmt, ...) LIKEPRINTF(1); -void CLQ3_SendAuthPacket(netadr_t gameserver); -void CLQ3_SendConnectPacket(netadr_t to); +void CLQ3_SendAuthPacket(netadr_t *gameserver); +void CLQ3_SendConnectPacket(netadr_t *to); void CLQ3_SendCmd(usercmd_t *cmd); qboolean CLQ3_Netchan_Process(void); void CLQ3_ParseServerMessage (void); @@ -1320,12 +1320,14 @@ typedef struct cin_s cin_t; #define Media_Playing() false #define Media_Init() 0 #define Media_PlayingFullScreen() false -#define Media_PlayFilm(n) false +#define Media_PlayFilm(n,e) false +#define Media_StopFilm() true #else /*media playing system*/ qboolean Media_PlayingFullScreen(void); void Media_Init(void); -qboolean Media_PlayFilm(char *name); +qboolean Media_PlayFilm(char *name, qboolean enqueue); +qboolean Media_StopFilm(qboolean all); qboolean Media_Playing(void); struct cin_s *Media_StartCin(char *name); texid_tf Media_UpdateForShader(cin_t *cin); diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 78890b701..d1ea5825e 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -977,14 +977,14 @@ void CLQ3_SendCmd(usercmd_t *cmd) Netchan_TransmitNextFragment(&cls.netchan); } -void CLQ3_SendAuthPacket(netadr_t gameserver) +void CLQ3_SendAuthPacket(netadr_t *gameserver) { char data[2048]; sizebuf_t msg; //send the auth packet //this should be the right code, but it doesn't work. - if (gameserver.type == NA_IP) + if (gameserver->type == NA_IP) { char *key = Cvar_Get("cl_cdkey", "", 0, "Quake3 auth")->string; netadr_t authaddr; @@ -1009,7 +1009,7 @@ void CLQ3_SendAuthPacket(netadr_t gameserver) } MSG_WriteByte(&msg, 0); - NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, authaddr); + NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, &authaddr); } else Con_Printf(" failed\n"); @@ -1017,7 +1017,7 @@ void CLQ3_SendAuthPacket(netadr_t gameserver) } } -void CLQ3_SendConnectPacket(netadr_t to) +void CLQ3_SendConnectPacket(netadr_t *to) { char data[2048]; char adrbuf[MAX_ADR_SIZE]; @@ -1031,7 +1031,7 @@ void CLQ3_SendConnectPacket(netadr_t to) msg.overflowed = msg.allowoverflow = 0; msg.maxsize = sizeof(data); MSG_WriteLong(&msg, -1); - MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", cls.challenge, cls.qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), net_local_cl_ipadr), cls.userinfo[0])); + MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", cls.challenge, cls.qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), &net_local_cl_ipadr), cls.userinfo[0])); Huff_EncryptPacket(&msg, 12); Huff_PreferedCompressionCRC(); NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, to); diff --git a/engine/client/console.c b/engine/client/console.c index ffa590c3c..e653593fa 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -842,7 +842,7 @@ Con_DPrintf A Con_Printf that only shows up if the "developer" cvar is set ================ */ -void VARGS Con_DPrintf (char *fmt, ...) +void VARGS Con_DPrintf (const char *fmt, ...) { va_list argptr; char msg[MAXPRINTMSG]; diff --git a/engine/client/keys.c b/engine/client/keys.c index 381139de0..5e57f2fe2 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -681,6 +681,12 @@ void Key_DefaultLinkClicked(char *text, char *info) Cbuf_AddText(va("\nimpulse %s\n", c), RESTRICT_LOCAL); return; } + c = Info_ValueForKey(info, "film"); + if (*c && !strchr(c, ';') && !strchr(c, '\n')) + { + Cbuf_AddText(va("\nplayfilm \"%s\"\n", c), RESTRICT_LOCAL); + return; + } c = Info_ValueForKey(info, "desc"); if (*c) { @@ -1239,7 +1245,7 @@ int chat_bufferlen = 0; void Key_Message (int key, int unicode) { - if (key == K_ENTER) + if (key == K_ENTER || key == K_KP_ENTER) { if (chat_buffer[0]) { //send it straight into the command. @@ -1651,6 +1657,7 @@ void Key_Init (void) for (i=32 ; i<128 ; i++) consolekeys[i] = true; consolekeys[K_ENTER] = true; + consolekeys[K_KP_ENTER] = true; consolekeys[K_TAB] = true; consolekeys[K_LEFTARROW] = true; consolekeys[K_RIGHTARROW] = true; @@ -1916,7 +1923,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down) { if (down && Media_PlayingFullScreen()) { - Media_PlayFilm(""); + Media_StopFilm(false); return; } if (UI_KeyPress(key, unicode, down)) //Allow the UI to see the escape key. It is possible that a developer may get stuck at a menu. @@ -1946,7 +1953,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down) case key_game: if (Media_PlayingFullScreen()) { - Media_PlayFilm(""); + Media_StopFilm(true); break; } case key_console: @@ -2102,7 +2109,7 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down) #endif case key_game: case key_console: - if ((key && unicode) || key == K_ENTER || key == K_TAB) + if ((key && unicode) || key == K_ENTER || key == K_KP_ENTER || key == K_TAB) key_dest = key_console; Key_Console (unicode, key); break; diff --git a/engine/client/keys.h b/engine/client/keys.h index 7cfd76979..1ec082986 100644 --- a/engine/client/keys.h +++ b/engine/client/keys.h @@ -46,8 +46,8 @@ K_LEFTARROW, K_RIGHTARROW, K_LALT, -K_CTRL, -K_SHIFT, +K_LCTRL, +K_LSHIFT, K_INS, K_DEL, K_PGDN, @@ -163,10 +163,10 @@ K_RALT = 245, K_MAX = 256 }; -#define K_LSHIFT K_SHIFT -#define K_RSHIFT K_SHIFT -#define K_RCTRL K_CTRL -#define K_LCTRL K_CTRL +#define K_SHIFT K_LSHIFT +#define K_RSHIFT K_LSHIFT +#define K_CTRL K_LCTRL +#define K_RCTRL K_LCTRL #define K_ALT K_LALT typedef enum {key_game, key_console, key_message, key_menu, key_editor} keydest_t; diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 3189ac4e7..299ff04ab 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -305,7 +305,7 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key) { package_t *p, *p2; p = c->dptr; - if (key == K_ENTER || key == K_MOUSE1) + if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1) { p->flags ^= DPF_WANTTOINSTALL; @@ -329,7 +329,7 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key) qboolean MD_PopMenu (union menuoption_s *mo,struct menu_s *m,int key) { - if (key == K_ENTER || key == K_MOUSE1) + if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1) { M_RemoveMenu(m); return true; @@ -340,7 +340,7 @@ qboolean MD_PopMenu (union menuoption_s *mo,struct menu_s *m,int key) static void Menu_Download_Got(struct dl_download *dl); qboolean MD_ApplyDownloads (union menuoption_s *mo,struct menu_s *m,int key) { - if (key == K_ENTER || key == K_MOUSE1) + if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1) { char *temp; package_t *last = NULL, *p; @@ -810,7 +810,7 @@ static int numbootdownloads; #include "fs.h" #ifdef AVAIL_ZLIB extern searchpathfuncs_t zipfilefuncs; -static int CL_BootDownload_Extract(const char *fname, int fsize, void *ptr, void *spath) +static int QDECL CL_BootDownload_Extract(const char *fname, int fsize, void *ptr, void *spath) { char buffer[512*1024]; int read; @@ -1043,11 +1043,13 @@ static void CL_BootDownload_Complete(struct dl_download *dl) Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL); CL_StartCinematicOrMenu(); } + + free(dl->user_ctx); } static void CL_Manifest_Complete(struct dl_download *dl) { - if (!dl->file) + if (!dl->file || dl->status == DL_FAILED) Con_Printf("Unable to load manifest from %s\n", dl->url); else { @@ -1062,6 +1064,18 @@ static void CL_Manifest_Complete(struct dl_download *dl) if (!Cmd_Argc()) continue; fname = Cmd_Argv(0); + + if (*fname == '*') + { + //for future expansion. + /*if (!stricmp(fname, "*game")) + { + //switch current gamedir to the new one, so we don't end up downloading if they already have it installed. + //this should be quake/quake2/etc. + }*/ + continue; + } + crc = strtoul(Cmd_Argv(1), NULL, 0); f = FS_OpenVFS(fname, "rb", FS_ROOT); @@ -1152,6 +1166,16 @@ qboolean CL_CheckBootDownloads(void) #endif numbootdownloads++; } + else + { + struct dl_download fake; + fake.file = VFSOS_Open(fname, "rb"); + fake.status = fake.file?DL_FINISHED:DL_FAILED; + numbootdownloads++; + CL_Manifest_Complete(&fake); + if (fake.file) + VFS_CLOSE(fake.file); + } } } diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 12049f0bc..b87e7e477 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -1277,7 +1277,7 @@ void MC_Slider_Key(menuslider_t *option, int key) if (option->var) Cvar_SetValue(option->var, range); } - else if (key == K_ENTER || key == K_MOUSE1) + else if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1) { range += delta; @@ -1297,7 +1297,7 @@ void MC_Slider_Key(menuslider_t *option, int key) void MC_CheckBox_Key(menucheck_t *option, menu_t *menu, int key) { - if (key != K_ENTER && key != K_LEFTARROW && key != K_RIGHTARROW && key != K_MOUSE1) + if (key != K_ENTER && key != K_KP_ENTER && key != K_LEFTARROW && key != K_RIGHTARROW && key != K_MOUSE1) return; if (option->func) option->func(option, menu, CHK_TOGGLE); @@ -1363,7 +1363,7 @@ void MC_EditBox_Key(menuedit_t *edit, int key, unsigned int unicode) void MC_Combo_Key(menucombo_t *combo, int key) { - if (key == K_ENTER || key == K_RIGHTARROW || key == K_MOUSE1) + if (key == K_ENTER || key == K_KP_ENTER || key == K_RIGHTARROW || key == K_MOUSE1) { combo->selectedoption++; if (combo->selectedoption >= combo->numoptions) @@ -1714,7 +1714,7 @@ void M_Complex_Key(int key, int unicode) case mt_qbuttonbigfont: if (!currentmenu->selecteditem->button.command) currentmenu->selecteditem->button.key(currentmenu->selecteditem, currentmenu, key); - else if (key == K_ENTER || key == K_MOUSE1) + else if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1) { Cbuf_AddText(currentmenu->selecteditem->button.command, RESTRICT_LOCAL); if (mgt == MGT_HEXEN2) @@ -1734,7 +1734,7 @@ void M_Complex_Key(int key, int unicode) MC_Combo_Key(¤tmenu->selecteditem->combo, key); break; case mt_bind: - if (key == K_ENTER || key == K_MOUSE1) + if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1) bindingactive = true; else if (key == K_BACKSPACE || key == K_DEL) M_UnbindCommand (currentmenu->selecteditem->bind.command); @@ -1779,6 +1779,7 @@ qboolean MC_GuiKey(int key, menu_t *menu) break; case K_ENTER: + case K_KP_ENTER: case K_RIGHTARROW: if (info->dropout) MC_GuiKey(key, info->dropout); diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 28b0fd4b3..26aa102b0 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -234,7 +234,7 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) } else if (thisone == info->scrollpos + (mousecursor_y-16)/8 && mousecursor_x < x) R2D_ImageColours((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, 1.0); - else if (selectedserver.inuse && NET_CompareAdr(si->adr, selectedserver.adr)) + else if (selectedserver.inuse && NET_CompareAdr(&si->adr, &selectedserver.adr)) R2D_ImageColours(((sin(realtime*4.4)*0.25)+0.5) * 0.5, ((sin(realtime*4.4)*0.25)+0.5)*0.5, 0.08*0.5, 1.0); else { @@ -252,7 +252,7 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu) if (sb_showmap.value) {Draw_FunStringWidth((x-8*8), y, si->map, 8*8); x-=9*8;} if (sb_showgamedir.value) {Draw_FunStringWidth((x-8*8), y, si->gamedir, 8*8); x-=9*8;} if (sb_showping.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->ping), 3*8); x-=4*8;} - if (sb_showaddress.value) {Draw_FunStringWidth((x-21*8), y, NET_AdrToString(adr, sizeof(adr), si->adr), 21*8); x-=22*8;} + if (sb_showaddress.value) {Draw_FunStringWidth((x-21*8), y, NET_AdrToString(adr, sizeof(adr), &si->adr), 21*8); x-=22*8;} Draw_FunStringWidth(0, y, si->name, x); } } @@ -306,7 +306,7 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key) } } - if (key == K_ENTER || key == 's' || key == 'j' || key == K_SPACE) + if (key == K_ENTER || key == K_KP_ENTER || key == K_KP_ENTER || key == 's' || key == 'j' || key == K_SPACE) { server = Master_SortedServer(info->selectedpos); if (server) @@ -320,9 +320,9 @@ joinserver: } if (server->special & SS_NETQUAKE) - Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(adr, sizeof(adr), server->adr)), RESTRICT_LOCAL); + Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(adr, sizeof(adr), &server->adr)), RESTRICT_LOCAL); else - Cbuf_AddText(va("connect %s\n", NET_AdrToString(adr, sizeof(adr), server->adr)), RESTRICT_LOCAL); + Cbuf_AddText(va("connect %s\n", NET_AdrToString(adr, sizeof(adr), &server->adr)), RESTRICT_LOCAL); M_RemoveAllMenus(); } @@ -722,9 +722,9 @@ static void M_QuickConnect_PreDraw(menu_t *menu) Con_Printf("Quick connect found %s (gamedir %s, players %i/%i, ping %ims)\n", best->name, best->gamedir, best->players, best->maxplayers, best->ping); if (best->special & SS_NETQUAKE) - Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(adr, sizeof(adr), best->adr)), RESTRICT_LOCAL); + Cbuf_AddText(va("nqconnect %s\n", NET_AdrToString(adr, sizeof(adr), &best->adr)), RESTRICT_LOCAL); else - Cbuf_AddText(va("join %s\n", NET_AdrToString(adr, sizeof(adr), best->adr)), RESTRICT_LOCAL); + Cbuf_AddText(va("join %s\n", NET_AdrToString(adr, sizeof(adr), &best->adr)), RESTRICT_LOCAL); M_ToggleMenu_f(); return; diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 3f459cc32..85eadf233 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -412,7 +412,7 @@ void M_Media_Draw (void) char compleatenamepath[MAX_OSPATH]; char compleatenamename[MAX_OSPATH]; qboolean compleatenamemultiple; -int Com_CompleatenameCallback(const char *name, int size, void *data, void *spath) +int QDECL Com_CompleatenameCallback(const char *name, int size, void *data, void *spath) { if (*compleatenamename) compleatenamemultiple = true; @@ -514,7 +514,7 @@ void M_Media_Key (int key) } } } - else if (key == K_ENTER) + else if (key == K_ENTER || key == K_KP_ENTER) { switch(selectedoption) { @@ -2167,53 +2167,101 @@ qboolean Media_Playing(void) return false; } -qboolean Media_PlayFilm(char *name) +struct pendingfilms_s +{ + struct pendingfilms_s *next; + char name[1]; +} *pendingfilms; +qboolean Media_BeginNextFilm(void) { cin_t *cin; static char sname[MAX_QPATH]; + struct pendingfilms_s *p; + + if (!pendingfilms) + return false; + p = pendingfilms; + pendingfilms = p->next; + snprintf(sname, sizeof(sname), "cinematic/%s", p->name); + Z_Free(p); if (!qrenderer) return false; + videoshader = R_RegisterCustom(sname, Shader_DefaultCinematic, sname+10); + + cin = R_ShaderGetCinematic(videoshader); + if (cin) + { + cin->ended = false; + if (cin->rewind) + cin->rewind(cin); + if (cin->changestream) + cin->changestream(cin, "cmd:focus"); + + return true; + } + else + { + R_UnloadShader(videoshader); + videoshader = NULL; + + return false; + } +} +qboolean Media_StopFilm(qboolean all) +{ + if (all) + { + struct pendingfilms_s *p; + while(pendingfilms) + { + p = pendingfilms; + pendingfilms = p->next; + Z_Free(p); + } + } if (videoshader) { R_UnloadShader(videoshader); videoshader = NULL; + + S_RawAudio(-1, NULL, 0, 0, 0, 0); } - if (!*name) + while (pendingfilms && !videoshader) { - if (cls.state == ca_active) - { - CL_SendClientCommand(true, "nextserver %i", cl.servercount); - } - S_RawAudio(0, NULL, 0, 0, 0, 0); - videoshader = NULL; + if (Media_BeginNextFilm()) + break; } - else + + //for q2 cinematic-maps. + if (!videoshader && cls.state == ca_active) { - snprintf(sname, sizeof(sname), "cinematic/%s", name); - videoshader = R_RegisterCustom(sname, Shader_DefaultCinematic, sname+10); + CL_SendClientCommand(true, "nextserver %i", cl.servercount); + } + return true; +} +qboolean Media_PlayFilm(char *name, qboolean enqueue) +{ + if (!enqueue || !*name) + Media_StopFilm(true); - cin = R_ShaderGetCinematic(videoshader); - if (cin) + if (*name) + { + struct pendingfilms_s **p; + for (p = &pendingfilms; *p; p = &(*p)->next) + ; + (*p) = Z_Malloc(sizeof(**p) + strlen(name)); + strcpy((*p)->name, name); + + while (pendingfilms && !videoshader) { - cin->ended = false; - if (cin->rewind) - cin->rewind(cin); - if (cin->changestream) - cin->changestream(cin, "cmd:focus"); - } - else - { - R_UnloadShader(videoshader); - videoshader = NULL; + if (Media_BeginNextFilm()) + break; } } -// Media_ShutdownCin(fullscreenvid); -// fullscreenvid = Media_StartCin(name); - if (videoshader) { CDAudio_Stop(); @@ -2237,17 +2285,56 @@ qboolean Media_ShowFilm(void) { cin_t *cin = R_ShaderGetCinematic(videoshader); if (cin && cin->ended) - Media_PlayFilm(""); + { + if (videoshader) + { + R_UnloadShader(videoshader); + videoshader = NULL; + } + Media_StopFilm(false); + } else { + float ratiox, ratioy; if (cin->cursormove) cin->cursormove(cin, mousecursor_x/(float)vid.width, mousecursor_y/(float)vid.height); if (cin->setsize) cin->setsize(cin, vid.pixelwidth, vid.pixelheight); -// GL_Set2D (false); - R2D_ImageColours(1, 1, 1, 1); - R2D_ScalePic(0, 0, vid.width, vid.height, videoshader); + ratiox = (float)cin->outwidth / vid.pixelwidth; + ratioy = (float)cin->outheight / vid.pixelheight; + + if (!cin->outheight || !cin->outwidth) + { + R2D_ImageColours(0, 0, 0, 1); + R2D_FillBlock(0, 0, vid.width, vid.height); + R2D_ScalePic(0, 0, 0, 0, videoshader); + } + else if (ratiox > ratioy) + { + int h = (vid.width * cin->outheight) / cin->outwidth; + int p = vid.height - h; + + //letterbox + R2D_ImageColours(0, 0, 0, 1); + R2D_FillBlock(0, 0, vid.width, p/2); + R2D_FillBlock(0, h + (p/2), vid.width, p/2); + + R2D_ImageColours(1, 1, 1, 1); + R2D_ScalePic(0, p/2, vid.width, h, videoshader); + } + else + { + int w = (vid.height * cin->outwidth) / cin->outheight; + int p = vid.width - w; + //sidethingies + R2D_ImageColours(0, 0, 0, 1); + R2D_FillBlock(0, 0, (p/2), vid.height); + R2D_FillBlock(w + (p/2), 0, p/2, vid.height); + + R2D_ImageColours(1, 1, 1, 1); + R2D_ScalePic(p/2, 0, w, vid.height, videoshader); + } SCR_SetUpToDrawConsole(); if (scr_con_current) @@ -2328,14 +2415,19 @@ void Media_Send_GetSize(cin_t *cin, int *x, int *y) void Media_PlayFilm_f (void) { + int i; if (Cmd_Argc() < 2) { Con_Printf("playfilm "); } if (!strcmp(Cmd_Argv(0), "cinematic")) - Media_PlayFilm(va("video/%s", Cmd_Argv(1))); + Media_PlayFilm(va("video/%s", Cmd_Argv(1)), false); else - Media_PlayFilm(Cmd_Argv(1)); + { + Media_PlayFilm(Cmd_Argv(1), false); + for (i = 2; i < Cmd_Argc(); i++) + Media_PlayFilm(Cmd_Argv(i), true); + } } diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 62ef405b0..862fb8726 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -123,7 +123,7 @@ typedef struct { qboolean ApplySetupMenu (union menuoption_s *option,struct menu_s *menu, int key) { setupmenu_t *info = menu->data; - if (key != K_ENTER) + if (key != K_ENTER && key != K_KP_ENTER) return false; Cvar_Set(&name, info->nameedit->text); Cvar_Set(&team, info->teamedit->text); @@ -141,7 +141,7 @@ qboolean SetupMenuColour (union menuoption_s *option,struct menu_s *menu, int ke setupmenu_t *info = menu->data; if (*option->button.text == 'T') { - if (key == K_ENTER || key == K_RIGHTARROW) + if (key == K_ENTER || key == K_KP_ENTER || key == K_RIGHTARROW) { info->topcolour ++; if (info->topcolour>=14) @@ -161,7 +161,7 @@ qboolean SetupMenuColour (union menuoption_s *option,struct menu_s *menu, int ke } else { - if (key == K_ENTER || key == K_RIGHTARROW) + if (key == K_ENTER || key == K_KP_ENTER || key == K_RIGHTARROW) { info->lowercolour ++; if (info->lowercolour>=14) @@ -188,7 +188,7 @@ typedef struct { int match; } q2skinsearch_t; -int q2skin_enumerate(const char *name, int fsize, void *parm, void *spath) +int QDECL q2skin_enumerate(const char *name, int fsize, void *parm, void *spath) { char blah[MAX_QPATH]; q2skinsearch_t *s = parm; @@ -223,7 +223,7 @@ qboolean MSetupQ2_ChangeSkin (struct menucustom_s *option,struct menu_s *menu, i 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) + if (key == K_ENTER || key == K_KP_ENTER || key == K_RIGHTARROW) { s->match ++; if (s->match>=s->entries) @@ -482,7 +482,7 @@ static const char *numplayeroptions[] = { qboolean MultiBeginGame (union menuoption_s *option,struct menu_s *menu, int key) { newmultimenu_t *info = menu->data; - if (key != K_ENTER) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; if (cls.state) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 9c9c65864..be10ab10e 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -518,12 +518,6 @@ static void ApplyPreset (int presetnum) int i; //this function is written backwards, to ensure things work properly in configs etc. - //make sure the presets always set up particles correctly for certain other game modes. - if (M_GameType() == MGT_HEXEN2) - { - Cbuf_InsertText("r_particledesc $r_particledesc h2part\n", RESTRICT_LOCAL, false); - } - // TODO: work backwards and only set cvars once for (i = presetnum; i >= 0; i--) { @@ -584,7 +578,7 @@ qboolean M_PresetApply (union menuoption_s *op, struct menu_s *menu, int key) { fpsmenuinfo_t *info = (fpsmenuinfo_t*)menu->data; - if (key != K_ENTER && key != K_MOUSE1) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; Cbuf_AddText("fps_preset ", RESTRICT_LOCAL); @@ -820,7 +814,7 @@ qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct menu_s *menu, { lightingmenuinfo_t *info = (lightingmenuinfo_t*)menu->data; - if (key != K_ENTER && key != K_MOUSE1) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; { @@ -1209,7 +1203,7 @@ qboolean M_Apply_SP_Cheats (union menuoption_s *op,struct menu_s *menu,int key) { singleplayerinfo_t *info = menu->data; - if (key != K_ENTER) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; switch(info->skillcombo->selectedoption) @@ -1328,7 +1322,7 @@ qboolean M_Apply_SP_Cheats_Q2 (union menuoption_s *op,struct menu_s *menu,int ke { singleplayerq2info_t *info = menu->data; - if (key != K_ENTER) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; switch(info->skillcombo->selectedoption) @@ -1454,7 +1448,7 @@ qboolean M_Apply_SP_Cheats_H2 (union menuoption_s *op,struct menu_s *menu,int ke { singleplayerh2info_t *info = menu->data; - if (key != K_ENTER) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; switch(info->skillcombo->selectedoption) @@ -2011,7 +2005,7 @@ qboolean M_VideoApply (union menuoption_s *op, struct menu_s *menu, int key) extern cvar_t vid_desktopsettings; videomenuinfo_t *info = (videomenuinfo_t*)menu->data; - if (key != K_ENTER && key != K_MOUSE1) + if (key != K_ENTER && key != K_KP_ENTER && key != K_MOUSE1) return false; // force update display options diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 304f77547..c1e53e9fe 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -470,6 +470,7 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key) } return true; case K_ENTER: + case K_KP_ENTER: if (info->selected) { if (info->selected->isdir) @@ -494,7 +495,7 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key) return false; } -static int DemoAddItem(const char *filename, int size, void *parm, void *spath) +static int QDECL DemoAddItem(const char *filename, int size, void *parm, void *spath) { int extnum; demomenu_t *menu = parm; diff --git a/engine/client/merged.h b/engine/client/merged.h index e8c5611f6..2f29a2807 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -143,7 +143,7 @@ extern int Mod_TagNumForName (struct model_s *model, char *name); int Mod_GetNumBones(struct model_s *model, qboolean allowtags); int Mod_GetBoneRelations(struct model_s *model, int firstbone, int lastbone, framestate_t *fstate, float *result); int Mod_GetBoneParent(struct model_s *model, int bonenum); -struct galiasbone_s *Mod_GetBoneInfo(struct model_s *model); +struct galiasbone_s *Mod_GetBoneInfo(struct model_s *model, int *numbones); char *Mod_GetBoneName(struct model_s *model, int bonenum); void Draw_FunString(int x, int y, const void *str); diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 598216095..6c3e862c2 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -514,7 +514,7 @@ char *Master_ReadKeyString(serverinfo_t *server, int keynum) case SLKEY_NAME: return server->name; case SLKEY_ADDRESS: - return NET_AdrToString(adr, sizeof(adr), server->adr); + return NET_AdrToString(adr, sizeof(adr), &server->adr); case SLKEY_GAMEDIR: return server->gamedir; @@ -622,7 +622,7 @@ void Master_AddMaster (char *address, int type, char *description) for (mast = master; mast; mast = mast->next) { - if (NET_CompareAdr(mast->adr, adr) && mast->type == type) //already exists. + if (NET_CompareAdr(&mast->adr, &adr) && mast->type == type) //already exists. return; } mast = Z_Malloc(sizeof(master_t)+strlen(description)+1+strlen(address)+1); @@ -924,7 +924,7 @@ int Master_CheckPollSockets(void) { SockadrToNetadr (&from, &net_from); Con_Printf ("Warning: Oversize packet from %s\n", - NET_AdrToString (adr, sizeof(adr), net_from)); + NET_AdrToString (adr, sizeof(adr), &net_from)); continue; } if (qerrno == ECONNABORTED || qerrno == ECONNRESET) @@ -942,7 +942,7 @@ int Master_CheckPollSockets(void) net_message.cursize = ret; if (ret == sizeof(net_message_buffer) ) { - Con_Printf ("Oversize packet from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + Con_Printf ("Oversize packet from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from)); continue; } @@ -1100,7 +1100,7 @@ void SListOptionChanged(serverinfo_t *newserver) { for (oldserver = firstserver; oldserver; oldserver=oldserver->next) { - if (NET_CompareAdr(selectedserver.adr, oldserver->adr))//*(int*)selectedserver.ipaddress == *(int*)server->ipaddress && selectedserver.port == server->port) + if (NET_CompareAdr(&selectedserver.adr, &oldserver->adr))//*(int*)selectedserver.ipaddress == *(int*)server->ipaddress && selectedserver.port == server->port) { if (oldserver->moreinfo) { @@ -1164,7 +1164,7 @@ void MasterInfo_ProcessHTTP(vfsfile_t *file, int type) if (!NET_StringToAdr(s, 80, &adr)) continue; - if ((info = Master_InfoForServer(adr))) //remove if the server already exists. + if ((info = Master_InfoForServer(&adr))) //remove if the server already exists. { info->sends = 1; //reset. } @@ -1177,7 +1177,7 @@ void MasterInfo_ProcessHTTP(vfsfile_t *file, int type) info->refreshtime = 0; info->ping = 0xffff; - snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adrbuf, sizeof(adrbuf), info->adr)); + snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adrbuf, sizeof(adrbuf), &info->adr)); info->next = firstserver; firstserver = info; @@ -1261,7 +1261,7 @@ char *jsonnode(int level, char *node) if (port) adr.port = htons(port); - if ((info = Master_InfoForServer(adr))) //remove if the server already exists. + if ((info = Master_InfoForServer(&adr))) //remove if the server already exists. { info->sends = 1; //reset. } @@ -1275,7 +1275,7 @@ char *jsonnode(int level, char *node) info->players = cp; info->maxplayers = mp; - snprintf(info->name, sizeof(info->name), "%s", *servername?servername:NET_AdrToString(servername, sizeof(servername), info->adr)); + snprintf(info->name, sizeof(info->name), "%s", *servername?servername:NET_AdrToString(servername, sizeof(servername), &info->adr)); info->next = firstserver; firstserver = info; @@ -1496,7 +1496,7 @@ void MasterInfo_WriteServers(void) if (mast->address) VFS_PUTS(mf, va("%s\t%s\t%s\n", mast->address , typename, mast->name)); else - VFS_PUTS(mf, va("%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) @@ -1511,15 +1511,15 @@ void MasterInfo_WriteServers(void) if (server->special & SS_FAVORITE) { if (server->special & SS_QUAKE3) - VFS_PUTS(mf, va("%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) - VFS_PUTS(mf, va("%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) - VFS_PUTS(mf, va("%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. - VFS_PUTS(qws, va("%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! - VFS_PUTS(mf, va("%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)); } } @@ -1778,13 +1778,13 @@ unsigned int Master_NumPolled(void) } //true if server is on a different master's list. -serverinfo_t *Master_InfoForServer (netadr_t addr) +serverinfo_t *Master_InfoForServer (netadr_t *addr) { serverinfo_t *info; for (info = firstserver; info; info = info->next) { - if (NET_CompareAdr(info->adr, addr)) + if (NET_CompareAdr(&info->adr, addr)) return info; } return NULL; @@ -1811,13 +1811,13 @@ void MasterInfo_RemoveAllPlayers(void) Z_Free(p); } } -void MasterInfo_RemovePlayers(netadr_t adr) +void MasterInfo_RemovePlayers(netadr_t *adr) { player_t *p, *prev; prev = NULL; for (p = mplayers; p; ) { - if (NET_CompareAdr(p->adr, adr)) + if (NET_CompareAdr(&p->adr, adr)) { if (prev) prev->next = p->next; @@ -1835,12 +1835,12 @@ void MasterInfo_RemovePlayers(netadr_t adr) } } -void MasterInfo_AddPlayer(netadr_t serveradr, char *name, int ping, int frags, int colours, char *skin) +void MasterInfo_AddPlayer(netadr_t *serveradr, char *name, int ping, int frags, int colours, char *skin) { player_t *p; p = Z_Malloc(sizeof(player_t)); p->next = mplayers; - p->adr = serveradr; + p->adr = *serveradr; p->colour = colours; p->frags = frags; Q_strncpyz(p->name, name, sizeof(p->name)); @@ -1861,7 +1861,7 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) serverinfo_t *info; char adr[MAX_ADR_SIZE]; - info = Master_InfoForServer(net_from); + info = Master_InfoForServer(&net_from); if (!info) //not found... { @@ -1874,7 +1874,7 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) info->adr = net_from; - snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adr, sizeof(adr), info->adr)); + snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adr, sizeof(adr), &info->adr)); info->next = firstserver; firstserver = info; @@ -1882,7 +1882,7 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) } else { - MasterInfo_RemovePlayers(info->adr); + MasterInfo_RemovePlayers(&info->adr); } nl = strchr(msg, '\n'); @@ -2055,7 +2055,7 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) details.players[clnum].botc = atoi(token); } - MasterInfo_AddPlayer(info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin); + MasterInfo_AddPlayer(&info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin); info->players = ++details.numplayers; @@ -2065,9 +2065,9 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) msg++; } } - if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(info->adr, selectedserver.adr)) || (info->special & SS_KEEPINFO))) + if (!info->moreinfo && ((slist_cacheinfo.value == 2 || NET_CompareAdr(&info->adr, &selectedserver.adr)) || (info->special & SS_KEEPINFO))) info->moreinfo = Z_Malloc(sizeof(serverdetailedinfo_t)); - if (NET_CompareAdr(info->adr, selectedserver.adr)) + if (NET_CompareAdr(&info->adr, &selectedserver.adr)) selectedserver.detail = info->moreinfo; if (info->moreinfo) @@ -2147,7 +2147,7 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) Z_Free(info); break; } - if ((old = Master_InfoForServer(info->adr))) //remove if the server already exists. + if ((old = Master_InfoForServer(&info->adr))) //remove if the server already exists. { if ((info->special & (SS_DARKPLACES | SS_NETQUAKE | SS_QUAKE2 | SS_QUAKE3)) && !(type & (SS_DARKPLACES | SS_NETQUAKE | SS_QUAKE2 | SS_QUAKE3))) old->special = type | (old->special & SS_FAVORITE); @@ -2160,7 +2160,7 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad) info->special = type; info->refreshtime = 0; - snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adr, sizeof(adr), info->adr)); + snprintf(info->name, sizeof(info->name), "%s", NET_AdrToString(adr, sizeof(adr), &info->adr)); info->next = last; last = info; diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index 65cce06d8..80ee29c53 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -189,12 +189,6 @@ qboolean PClassic_Query(int type, int body, char *outstr, int outstrlen) return false; } -//returns a valid effect if both its existance is known, and it is fully functional -static int PClassic_ParticleTypeForName(char *name) -{ - return P_FindParticleType(name); -} - //a convienience function. static int PClassic_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name) { @@ -927,7 +921,6 @@ particleengine_t pe_classic = "Classic", NULL, - PClassic_ParticleTypeForName, PClassic_FindParticleType, PClassic_Query, diff --git a/engine/client/p_null.c b/engine/client/p_null.c index d0e268f68..55e381f4c 100644 --- a/engine/client/p_null.c +++ b/engine/client/p_null.c @@ -4,14 +4,7 @@ #include "particles.h" #include "renderque.h" -//obtains an index for the name, even if it is unknown (one can be loaded after. will only fail if the effect limit is reached) -static int PNULL_ParticleTypeForName(char *name) -{ - Con_DPrintf("P_ParticleTypeForName %s\n", name); - return P_INVALID; -} - -//returns a valid effect if its existance is known, even if simply referenced. This should be phased out. +//returns a valid effect if its existance is known. static int PNULL_FindParticleType(char *name) { Con_DPrintf("P_FindParticleType %s\n", name); @@ -60,7 +53,6 @@ particleengine_t pe_null = "null", "none", - PNULL_ParticleTypeForName, PNULL_FindParticleType, NULL, diff --git a/engine/client/p_script.c b/engine/client/p_script.c index f140516fb..6adee76db 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -71,6 +71,8 @@ static qboolean pe_script_enabled; static float psintable[256]; +static qboolean P_LoadParticleSet(char *name, qboolean implicit); + static void buildsintable(void) { int i; @@ -171,6 +173,7 @@ typedef struct { // TODO: merge in alpha with rgb to gain benefit of vector opts typedef struct part_type_s { char name[MAX_QPATH]; + char config[MAX_QPATH]; char texname[MAX_QPATH]; int nummodels; @@ -268,7 +271,7 @@ typedef struct part_type_s { int rampindexes; ramp_t *ramp; - int loaded; + int loaded; //0 if not loaded, 1 if automatically loaded, 2 if user loaded particle_t *particles; clippeddecal_t *clippeddecals; beamseg_t *beams; @@ -293,6 +296,13 @@ typedef struct part_type_s { #define PS_INRUNLIST 0x1 // particle type is currently in execution list } part_type_t; +typedef struct pcfg_s +{ + struct pcfg_s *next; + char name[1]; +} pcfg_t; +static pcfg_t *loadedconfigs; + #ifndef TYPESONLY //triangle fan sparks use these. // defined but not used @@ -365,28 +375,41 @@ static int numparticletypes; static part_type_t *part_type; static part_type_t *part_run_list; +static char part_parsenamespace[MAX_QPATH]; +static qboolean part_parseweak; + static struct { char *oldn; char *newn; } legacynames[] = { - {"t_rocket", "TR_ROCKET"}, + {"t_rocket", "TR_ROCKET"}, //{"t_blastertrail", "TR_BLASTERTRAIL"}, - {"t_grenade", "TR_GRENADE"}, - {"t_gib", "TR_BLOOD"}, + {"t_grenade", "TR_GRENADE"}, + {"t_gib", "TR_BLOOD"}, - {"te_plasma", "TE_TEI_PLASMAHIT"}, - {"te_smoke", "TE_TEI_SMOKE"}, + {"te_plasma", "TE_TEI_PLASMAHIT"}, + {"te_smoke", "TE_TEI_SMOKE"}, {NULL} }; -static part_type_t *P_GetParticleType(char *name) +static part_type_t *P_GetParticleType(char *config, char *name) { int i; part_type_t *ptype; part_type_t *oldlist = part_type; + char cfgbuf[MAX_QPATH]; + char *dot = strchr(name, '.'); + if (dot && (dot - name) < MAX_QPATH-1) + { + config = cfgbuf; + memcpy(cfgbuf, name, dot - name); + cfgbuf[dot - name] = 0; + name = dot+1; + } + for (i = 0; legacynames[i].oldn; i++) { if (!strcmp(name, legacynames[i].oldn)) @@ -399,12 +422,14 @@ static part_type_t *P_GetParticleType(char *name) { ptype = &part_type[i]; if (!stricmp(ptype->name, name)) - return ptype; + if (!stricmp(ptype->config, config)) //must be an exact match. + return ptype; } part_type = BZ_Realloc(part_type, sizeof(part_type_t)*(numparticletypes+1)); ptype = &part_type[numparticletypes++]; memset(ptype, 0, sizeof(*ptype)); - strcpy(ptype->name, name); + Q_strncpyz(ptype->name, name, sizeof(ptype->name)); + Q_strncpyz(ptype->config, config, sizeof(ptype->config)); ptype->assoc = P_INVALID; ptype->inwater = P_INVALID; ptype->cliptype = P_INVALID; @@ -429,29 +454,29 @@ static part_type_t *P_GetParticleType(char *name) return ptype; } -static int P_AllocateParticleType(char *name) //guarentees that the particle type exists, returning it's index. +//unconditionally allocates a particle object. this allows out-of-order allocations. +static int P_AllocateParticleType(char *config, char *name) //guarentees that the particle type exists, returning it's index. { - part_type_t *pt = P_GetParticleType(name); + part_type_t *pt = P_GetParticleType(config, name); return pt - part_type; } -static int PScript_ParticleTypeForName(char *name) -{ - int to; - - to = P_GetParticleType(name) - part_type; - if (to < 0 || to >= numparticletypes) - { - return P_INVALID; - } - - return to; -} - +//public interface. get without creating. static int PScript_FindParticleType(char *name) { int i; part_type_t *ptype = NULL; + char cfg[MAX_QPATH]; + char *dot; + dot = strchr(name, '.'); + if (dot && (dot - name) < MAX_QPATH-1) + { + memcpy(cfg, name, dot - name); + cfg[dot-name] = 0; + name = dot+1; + } + else + *cfg = 0; for (i = 0; legacynames[i].oldn; i++) { @@ -462,16 +487,37 @@ static int PScript_FindParticleType(char *name) } } - for (i = 0; i < numparticletypes; i++) - { - if (!stricmp(part_type[i].name, name)) + if (*cfg) + { //favour the namespace if one is specified + for (i = 0; i < numparticletypes; i++) { - ptype = &part_type[i]; - break; + if (!stricmp(part_type[i].name, name)) + { + if (!stricmp(part_type[i].config, cfg)) + { + ptype = &part_type[i]; + break; + } + } + } + } + else + { + //but be prepared to load it from any namespace if its not got a namespace specified. + for (i = 0; i < numparticletypes; i++) + { + if (!stricmp(part_type[i].name, name)) + { + ptype = &part_type[i]; + break; + } } } if (!ptype || !ptype->loaded) { + if (*cfg) + P_LoadParticleSet(cfg, true); + if (fallback) { if (!strncmp(name, "classic_", 8)) @@ -499,11 +545,11 @@ static void P_SetModified(void) //called when the particle system changes (from Cbuf_AddText("say particles description has changed\n", RESTRICT_LOCAL); } } -static int CheckAssosiation(char *name, int from) +static int CheckAssosiation(char *config, char *name, int from) { int to, orig; - orig = to = P_AllocateParticleType(name); + orig = to = P_AllocateParticleType(config, name); while(to != P_INVALID) { @@ -688,9 +734,17 @@ static void P_ParticleEffect_f(void) part_type_t *ptype, *torun; char tnamebuf[sizeof(ptype->name)]; int pnum, assoc; + char *config = part_parsenamespace; if (Cmd_Argc()!=2) { + if (!strcmp(Cmd_Argv(1), "namespace")) + { + Q_strncpyz(part_parsenamespace, Cmd_Argv(2), sizeof(part_parsenamespace)); + if (Cmd_Argc() >= 4) + part_parseweak = atoi(Cmd_Argv(3)); + return; + } Con_Printf("No name for particle effect\n"); return; } @@ -705,7 +759,14 @@ static void P_ParticleEffect_f(void) return; } - if (!pe_script_enabled) + var = Cmd_Argv(1); + if (*var == '+') + ptype = P_GetParticleType(config, var+1); + else + ptype = P_GetParticleType(config, var); + + //'weak' configs do not replace 'strong' configs + if (!pe_script_enabled || (part_parseweak && ptype->loaded)) { int depth = 1; while(1) @@ -727,10 +788,8 @@ static void P_ParticleEffect_f(void) return; } - var = Cmd_Argv(1); if (*var == '+') { - ptype = P_GetParticleType(var+1); if (ptype->loaded) { int i, parenttype; @@ -739,7 +798,7 @@ static void P_ParticleEffect_f(void) { parenttype = ptype - part_type; snprintf(newname, sizeof(newname), "+%i%s", i, var); - ptype = P_GetParticleType(newname); + ptype = P_GetParticleType(config, newname); if (!ptype->loaded) { if (part_type[parenttype].assoc != P_INVALID) @@ -757,7 +816,6 @@ static void P_ParticleEffect_f(void) } else { - ptype = P_GetParticleType(Cmd_Argv(1)); if (ptype->loaded) { assoc = ptype->assoc; @@ -1050,7 +1108,7 @@ static void P_ParticleEffect_f(void) else if (!strcmp(var, "assoc")) { - assoc = CheckAssosiation(value, pnum); //careful - this can realloc all the particle types + assoc = CheckAssosiation(config, value, pnum); //careful - this can realloc all the particle types ptype = &part_type[pnum]; ptype->assoc = assoc; } @@ -1058,7 +1116,7 @@ static void P_ParticleEffect_f(void) { // the underwater effect switch should only occur for // 1 level so the standard assoc check works - assoc = CheckAssosiation(value, pnum); + assoc = CheckAssosiation(config, value, pnum); ptype = &part_type[pnum]; ptype->inwater = assoc; } @@ -1237,7 +1295,7 @@ static void P_ParticleEffect_f(void) ptype->spawnchance = atof(value); else if (!strcmp(var, "cliptype")) { - assoc = PScript_ParticleTypeForName(value);//careful - this can realloc all the particle types + assoc = P_AllocateParticleType(config, value);//careful - this can realloc all the particle types ptype = &part_type[pnum]; ptype->cliptype = assoc; } @@ -1246,7 +1304,7 @@ static void P_ParticleEffect_f(void) else if (!strcmp(var, "emit")) { - assoc = PScript_ParticleTypeForName(value);//careful - this can realloc all the particle types + assoc = P_AllocateParticleType(config, value);//careful - this can realloc all the particle types ptype = &part_type[pnum]; ptype->emit = assoc; } @@ -1462,7 +1520,7 @@ static void P_ParticleEffect_f(void) Con_DPrintf("%s is not a recognised particle type field (in %s)\n", var, ptype->name); } ptype->looks.invscalefactor = 1-ptype->looks.scalefactor; - ptype->loaded = 1; + ptype->loaded = part_parseweak?1:2; if (ptype->clipcount < 1) ptype->clipcount = 1; @@ -1828,6 +1886,7 @@ static void P_ImportEffectInfo_f(void) char *cmd; char arg[8][1024]; int args = 0; + char *config = "effectinfo"; FS_LoadFile("effectinfo.txt", (void**)&file); if (!file) @@ -1871,14 +1930,14 @@ static void P_ImportEffectInfo_f(void) FinishParticleType(ptype); } - ptype = P_GetParticleType(arg[1]); + ptype = P_GetParticleType(config, arg[1]); if (ptype->loaded) { for (i = 0; i < 64; i++) { parenttype = ptype - part_type; snprintf(newname, sizeof(newname), "%i+%s", i, arg[1]); - ptype = P_GetParticleType(newname); + ptype = P_GetParticleType(config, newname); if (!ptype->loaded) { part_type[parenttype].assoc = ptype - part_type; @@ -1891,7 +1950,7 @@ static void P_ImportEffectInfo_f(void) break; } } - ptype->loaded = true; + ptype->loaded = part_parseweak?1:2; ptype->scale = 1; ptype->alpha = 0; ptype->alpharand = 1; @@ -2203,11 +2262,11 @@ static qboolean PScript_InitParticles (void) #endif - pt_pointfile = P_AllocateParticleType("PT_POINTFILE"); - pe_default = P_AllocateParticleType("PE_DEFAULT"); - pe_size2 = P_AllocateParticleType("PE_SIZE2"); - pe_size3 = P_AllocateParticleType("PE_SIZE3"); - pe_defaulttrail = P_AllocateParticleType("PE_DEFAULTTRAIL"); + pt_pointfile = P_AllocateParticleType("", "PT_POINTFILE"); + pe_default = P_AllocateParticleType("", "PE_DEFAULT"); + pe_size2 = P_AllocateParticleType("", "PE_SIZE2"); + pe_size3 = P_AllocateParticleType("", "PE_SIZE3"); + pe_defaulttrail = P_AllocateParticleType("", "PE_DEFAULTTRAIL"); Cvar_Hook(&r_particledesc, R_ParticleDesc_Callback); Cvar_ForceCallback(&r_particledesc); @@ -2256,6 +2315,14 @@ static void PScript_Shutdown (void) Cmd_RemoveCommand("r_beaminfo"); #endif + while(loadedconfigs) + { + pcfg_t *cfg; + cfg = loadedconfigs; + loadedconfigs = cfg->next; + Z_Free(cfg); + } + while (numparticletypes > 0) { numparticletypes--; @@ -2356,15 +2423,27 @@ static void P_ExportBuiltinSet_f(void) Con_Printf("'%s' is not a built in particle set\n", efname); } -static void P_LoadParticleSet(char *name, qboolean first) +static qboolean P_LoadParticleSet(char *name, qboolean implicit) { char *file; int i; int restrictlevel = Cmd_FromGamecode() ? RESTRICT_SERVER : RESTRICT_LOCAL; + pcfg_t *cfg; - /*set up a default*/ - if (first && !*name) - name = "faithful"; + if (!*name) + return false; + + //protect against configs being loaded multiple times. this can easily happen with namespaces (especially if an effect is missing). + for (cfg = loadedconfigs; cfg; cfg = cfg->next) + { + //already loaded? + if (!strcmp(cfg->name, name)) + return false; + } + cfg = Z_Malloc(sizeof(*cfg) + strlen(name)); + strcpy(cfg->name, name); + cfg->next = loadedconfigs; + loadedconfigs = cfg; if (!strcmp(name, "classic")) { @@ -2376,7 +2455,7 @@ static void P_LoadParticleSet(char *name, qboolean first) fallback->InitParticles(); fallback->ClearParticles(); } - return; + return true; } for (i = 0; partset_list[i].name; i++) @@ -2387,14 +2466,14 @@ static void P_LoadParticleSet(char *name, qboolean first) { Cbuf_AddText(*partset_list[i].data, RESTRICT_LOCAL); } - return; + return true; } } if (!strcmp(name, "effectinfo")) { P_ImportEffectInfo_f(); - return; + return true; } @@ -2403,22 +2482,28 @@ static void P_LoadParticleSet(char *name, qboolean first) FS_LoadFile(va("%s.cfg", name), (void**)&file); if (file) { + Cbuf_AddText(va("\nr_part namespace %s %i\n", name, implicit), restrictlevel); Cbuf_AddText(file, restrictlevel); - Cbuf_AddText("\n", restrictlevel); + Cbuf_AddText("\nr_part namespace \"\" 0\n", restrictlevel); FS_FreeFile(file); } - else if (first) - { - Con_Printf(CON_WARNING "Couldn't find particle description %s, using spikeset\n", name); - Cbuf_AddText(particle_set_spikeset, RESTRICT_LOCAL); - } else - Con_Printf(CON_WARNING "Couldn't find particle description %s\n", name); + { + if (P_LoadParticleSet("high", true)) + Con_Printf(CON_WARNING "Couldn't find particle description %s, loading 'high' instead\n", name); + else + { + Con_Printf(CON_WARNING "Couldn't find particle description %s\n", name); + return false; + } + } + return true; } static void R_Particles_KillAllEffects(void) { int i; + pcfg_t *cfg; for (i = 0; i < numparticletypes; i++) { @@ -2440,6 +2525,13 @@ static void R_Particles_KillAllEffects(void) fallback->ShutdownParticles(); fallback = NULL; } + + while(loadedconfigs) + { + cfg = loadedconfigs; + loadedconfigs = cfg->next; + Z_Free(cfg); + } } static void R_ParticleDesc_Callback(struct cvar_s *var, char *oldvalue) @@ -2456,11 +2548,16 @@ static void R_ParticleDesc_Callback(struct cvar_s *var, char *oldvalue) first = true; for (c = COM_ParseStringSet(var->string); com_token[0]; c = COM_ParseStringSet(c)) { - P_LoadParticleSet(com_token, first); + /*set up a default*/ + if (first && !*com_token) + strcpy(com_token, "faithful"); + P_LoadParticleSet(com_token, false); first = false; } - Cbuf_AddText("r_effect\n", RESTRICT_LOCAL); +// Cbuf_AddText("r_effect\n", RESTRICT_LOCAL); + + //make sure nothing is stale. CL_RegisterParticles(); } @@ -5639,7 +5736,6 @@ particleengine_t pe_script = "script", "fte", - PScript_ParticleTypeForName, PScript_FindParticleType, PScript_Query, diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index 590826fbe..7a5cf6274 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -8,7 +8,7 @@ -int MP_TranslateFTEtoDPCodes(int code) +int MP_TranslateFTEtoQCCodes(int code) { switch(code) { @@ -111,7 +111,7 @@ int MP_TranslateFTEtoDPCodes(int code) } } -int MP_TranslateDPtoFTECodes(int code) +int MP_TranslateQCtoFTECodes(int code) { switch(code) { @@ -225,15 +225,15 @@ void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalva keyname[0] = '\0'; - Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[0])), sizeof(keyname)); - Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[1])), sizeof(keyname)); + Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoQCCodes(keynums[0])), sizeof(keyname)); + Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoQCCodes(keynums[1])), sizeof(keyname)); RETURN_TSTRING(keyname); } void QCBUILTIN PF_cl_getkeybind (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *binding = Key_GetBinding(MP_TranslateDPtoFTECodes(G_FLOAT(OFS_PARM0))); + char *binding = Key_GetBinding(MP_TranslateQCtoFTECodes(G_FLOAT(OFS_PARM0))); RETURN_TSTRING(binding); } @@ -250,7 +250,7 @@ void QCBUILTIN PF_cl_stringtokeynum(pubprogfuncs_t *prinst, struct globalvars_s G_FLOAT(OFS_RETURN) = -1; return; } - i = MP_TranslateFTEtoDPCodes(i); + i = MP_TranslateFTEtoQCCodes(i); G_FLOAT(OFS_RETURN) = i; } @@ -259,7 +259,7 @@ void QCBUILTIN PF_cl_keynumtostring (pubprogfuncs_t *prinst, struct globalvars_s { int code = G_FLOAT(OFS_PARM0); - code = MP_TranslateDPtoFTECodes (code); + code = MP_TranslateQCtoFTECodes (code); RETURN_TSTRING(Key_KeynumToString(code)); } @@ -329,7 +329,7 @@ void QCBUILTIN PF_cs_gecko_keyevent (pubprogfuncs_t *prinst, struct globalvars_s if (!cin) return; - Media_Send_KeyEvent(cin, MP_TranslateDPtoFTECodes(key), (key>127)?0:key, eventtype); + Media_Send_KeyEvent(cin, MP_TranslateQCtoFTECodes(key), (key>127)?0:key, eventtype); } // #491 void gecko_mousemove( string name, float x, float y ) void QCBUILTIN PF_cs_gecko_mousemove (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 9f9229b4e..396dacc2c 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -940,17 +940,17 @@ static void QCBUILTIN PF_R_AddEntityMask(pubprogfuncs_t *prinst, struct globalva if (ent->isfree) continue; - if (ent->xv->predraw) - { - *csqcg.self = EDICT_TO_PROG(prinst, (void*)ent); - PR_ExecuteProgram(prinst, ent->xv->predraw); - - if (ent->isfree || (int)ent->xv->renderflags & CSQCRF_NOAUTOADD) - continue; //bummer... - } - if ((int)ent->xv->drawmask & mask) { + if (ent->xv->predraw) + { + *csqcg.self = EDICT_TO_PROG(prinst, (void*)ent); + PR_ExecuteProgram(prinst, ent->xv->predraw); + + if (ent->isfree || (int)ent->xv->renderflags & CSQCRF_NOAUTOADD) + continue; //bummer... + } + if (CopyCSQCEdictToEntity(ent, &rent)) { CLQ1_AddShadow(&rent); @@ -2085,7 +2085,7 @@ static void QCBUILTIN PF_cs_sendevent (pubprogfuncs_t *prinst, struct globalvars static void cs_set_input_state (usercmd_t *cmd) { if (csqcg.input_timelength) - *csqcg.input_timelength = cmd->msec/1000.0f; + *csqcg.input_timelength = cmd->msec/1000.0f * cl.gamespeed; if (csqcg.input_angles) { csqcg.input_angles[0] = SHORT2ANGLE(cmd->angles[0]); @@ -2329,7 +2329,7 @@ static void QCBUILTIN PF_cs_serverkey (pubprogfuncs_t *prinst, struct globalvars ret = lastdemoname; } else - ret = NET_AdrToString(adr, sizeof(adr), cls.netchan.remote_address); + ret = NET_AdrToString(adr, sizeof(adr), &cls.netchan.remote_address); } else if (!strcmp(keyname, "state")) { @@ -3532,11 +3532,11 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src else if (src->solid) { ent->v->solid = SOLID_BBOX; - ent->v->mins[0] = 8*(src->solid & 31); - ent->v->maxs[0] = ent->v->mins[0]; + ent->v->mins[0] = -8*(src->solid & 31); + ent->v->maxs[0] = 8*(src->solid & 31); ent->v->mins[1] = ent->v->mins[0]; - ent->v->maxs[1] = ent->v->mins[0]; - ent->v->mins[2] = 8*((src->solid>>5) & 31); + ent->v->maxs[1] = ent->v->maxs[0]; + ent->v->mins[2] = -8*((src->solid>>5) & 31); ent->v->maxs[2] = 8*((src->solid>>10) & 63) - 32; } else @@ -4295,6 +4295,12 @@ static struct { {"frametoname", PF_frametoname, 284},//string(float modidx, float framenum) frametoname {"skintoname", PF_skintoname, 285},//string(float modidx, float skin) skintoname + {"hash_createtab", PF_hash_createtab, 287}, + {"hash_destroytab", PF_hash_destroytab, 288}, + {"hash_add", PF_hash_add, 289}, + {"hash_get", PF_hash_get, 290}, + {"hash_delete", PF_hash_delete, 291}, + {"hash_getkey", PF_hash_getkey, 292}, //300 {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) {"addentities", PF_R_AddEntityMask, 301}, // #301 void(float mask) addentities (EXT_CSQC) @@ -4399,40 +4405,43 @@ static struct { // {"readsingleentitystate", PF_ReadSingleEntityState, 370}, {"deltalisten", PF_DeltaListen, 371}, // #371 float(string modelname, float flags) deltalisten (EXT_CSQC_1) - {"dynamiclight_get", PF_R_DynamicLight_Get, 372}, - {"dynamiclight_set", PF_R_DynamicLight_Set, 373}, + {"dynamiclight_get", PF_R_DynamicLight_Get, 372}, + {"dynamiclight_set", PF_R_DynamicLight_Set, 373}, {"particleeffectquery", PF_cs_particleeffectquery, 374}, - {"adddecal", PF_R_AddDecal, 375}, + {"adddecal", PF_R_AddDecal, 375}, - {"memalloc", PF_memalloc, 384}, - {"memfree", PF_memfree, 385}, - {"memcpy", PF_memcpy, 386}, - {"memset", PF_memset, 387}, + {"memalloc", PF_memalloc, 384}, + {"memfree", PF_memfree, 385}, + {"memcpy", PF_memcpy, 386}, + {"memfill8", PF_memfill8, 387}, + {"memgetval", PF_memgetval, 388}, + {"memsetval", PF_memsetval, 389}, + {"memptradd", PF_memptradd, 390}, //400 - {"copyentity", PF_cs_copyentity, 400}, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) - {"setcolors", PF_NoCSQC, 401}, // #401 void(entity cl, float colours) setcolors (DP_SV_SETCOLOR) (don't implement) + {"copyentity", PF_cs_copyentity, 400}, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) + {"setcolors", PF_NoCSQC, 401}, // #401 void(entity cl, float colours) setcolors (DP_SV_SETCOLOR) (don't implement) {"findchain", PF_cs_findchain, 402}, // #402 entity(string field, string match) findchain (DP_QC_FINDCHAIN) {"findchainfloat", PF_cs_findchainfloat, 403}, // #403 entity(float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) - {"effect", PF_cl_effect, 404}, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) + {"effect", PF_cl_effect, 404}, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) - {"te_blood", PF_cl_te_blooddp, 405}, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) - {"te_bloodshower", PF_cl_te_bloodshower,406}, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) - {"te_explosionrgb", PF_cl_te_explosionrgb, 407}, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) - {"te_particlecube", PF_cl_te_particlecube,408}, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) - {"te_particlerain", PF_cl_te_particlerain, 409}, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) + {"te_blood", PF_cl_te_blooddp, 405}, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) + {"te_bloodshower", PF_cl_te_bloodshower, 406}, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) + {"te_explosionrgb", PF_cl_te_explosionrgb, 407}, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) + {"te_particlecube", PF_cl_te_particlecube, 408}, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) + {"te_particlerain", PF_cl_te_particlerain, 409}, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) - {"te_particlesnow", PF_cl_te_particlesnow,410}, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) - {"te_spark", PF_cl_te_spark, 411}, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) - {"te_gunshotquad", PF_cl_te_gunshotquad, 412}, // #412 void(vector org) te_gunshotquad (DP_TE_QUADEFFECTS1) - {"te_spikequad", PF_cl_te_spikequad, 413}, // #413 void(vector org) te_spikequad (DP_TE_QUADEFFECTS1) - {"te_superspikequad", PF_cl_te_superspikequad,414}, // #414 void(vector org) te_superspikequad (DP_TE_QUADEFFECTS1) + {"te_particlesnow", PF_cl_te_particlesnow, 410}, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) + {"te_spark", PF_cl_te_spark, 411}, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) + {"te_gunshotquad", PF_cl_te_gunshotquad, 412}, // #412 void(vector org) te_gunshotquad (DP_TE_QUADEFFECTS1) + {"te_spikequad", PF_cl_te_spikequad, 413}, // #413 void(vector org) te_spikequad (DP_TE_QUADEFFECTS1) + {"te_superspikequad", PF_cl_te_superspikequad, 414}, // #414 void(vector org) te_superspikequad (DP_TE_QUADEFFECTS1) - {"te_explosionquad", PF_cl_te_explosionquad, 415}, // #415 void(vector org) te_explosionquad (DP_TE_QUADEFFECTS1) - {"te_smallflash", PF_cl_te_smallflash, 416}, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) - {"te_customflash", PF_cl_te_customflash, 417}, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) - {"te_gunshot", PF_cl_te_gunshot, 418}, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) - {"te_spike", PF_cl_te_spike, 419}, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) + {"te_explosionquad", PF_cl_te_explosionquad, 415}, // #415 void(vector org) te_explosionquad (DP_TE_QUADEFFECTS1) + {"te_smallflash", PF_cl_te_smallflash, 416}, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) + {"te_customflash", PF_cl_te_customflash, 417}, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) + {"te_gunshot", PF_cl_te_gunshot, 418}, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) + {"te_spike", PF_cl_te_spike, 419}, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) {"te_superspike", PF_cl_te_superspike,420}, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) {"te_explosion", PF_cl_te_explosion, 421}, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) @@ -4511,7 +4520,7 @@ static struct { {"tan", PF_tan, 475}, // #475 float(float a) tan -////DP_QC_STRINGCOLORFUNCTIONS +//DP_QC_STRINGCOLORFUNCTIONS {"strlennocol", PF_strlennocol, 476}, // #476 float(string s) strlennocol {"strdecolorize", PF_strdecolorize, 477}, // #477 string(string s) strdecolorize @@ -5550,7 +5559,7 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid) pr_globals = PR_globals(csqcprogs, PR_CURRENT); G_FLOAT(OFS_PARM0) = down?CSIE_KEYDOWN:CSIE_KEYUP; - G_FLOAT(OFS_PARM1) = MP_TranslateFTEtoDPCodes(key); + G_FLOAT(OFS_PARM1) = MP_TranslateFTEtoQCCodes(key); G_FLOAT(OFS_PARM2) = unicode; G_FLOAT(OFS_PARM3) = devid; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index f1673869b..2b431db85 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -452,7 +452,7 @@ void QCBUILTIN PF_CL_drawcharacter (pubprogfuncs_t *prinst, struct globalvars_s PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y); Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha); - Font_DrawScaleChar(x, y, CON_WHITEMASK | /*0xe000|*/chara); + Font_DrawScaleChar(x, y, CON_WHITEMASK | chara); Font_InvalidateColour(); Font_EndString(NULL); @@ -470,6 +470,7 @@ void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s // float flag = G_FLOAT(OFS_PARM5); float x, y; unsigned int c; + int error; if (!text) { @@ -482,14 +483,19 @@ void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s while(*text) { - //FIXME: which charset is this meant to be using? - //quakes? 8859-1? utf8? some weird hacky mixture? - c = *text++&0xff; - if ((c&0x7f) < 32) - c |= 0xe000; //if its a control char, just use the quake range instead. - else if (c & 0x80) - c |= 0xe000; //if its a high char, just use the quake range instead. we could colour it, but why bother - x = Font_DrawScaleChar(x, y, CON_WHITEMASK|/*0xe000|*/c); + if (1)//VMUTF8) + c = unicode_decode(&error, text, &text); + else + { + //FIXME: which charset is this meant to be using? + //quakes? 8859-1? utf8? some weird hacky mixture? + c = *text++&0xff; + if ((c&0x7f) < 32) + c |= 0xe000; //if its a control char, just use the quake range instead. + else if (c & 0x80) + c |= 0xe000; //if its a high char, just use the quake range instead. we could colour it, but why bother + } + x = Font_DrawScaleChar(x, y, CON_WHITEMASK|c); } Font_InvalidateColour(); Font_EndString(NULL); @@ -1308,6 +1314,13 @@ static struct { //gap {"shaderforname", PF_shaderforname, 238}, //gap + {"hash_createtab", PF_hash_createtab, 287}, + {"hash_destroytab", PF_hash_destroytab, 288}, + {"hash_add", PF_hash_add, 289}, + {"hash_get", PF_hash_get, 290}, + {"hash_delete", PF_hash_delete, 291}, + {"hash_getkey", PF_hash_getkey, 292}, + //gap {"print", PF_print, 339}, {"keynumtostring", PF_cl_keynumtostring, 340}, {"stringtokeynum", PF_cl_stringtokeynum, 341}, @@ -1321,7 +1334,10 @@ static struct { {"memalloc", PF_memalloc, 384}, {"memfree", PF_memfree, 385}, {"memcpy", PF_memcpy, 386}, - {"memset", PF_memset, 387}, + {"memfill8", PF_memfill8, 387}, + {"memgetval", PF_memgetval, 388}, + {"memsetval", PF_memsetval, 389}, + {"memptradd", PF_memptradd, 390}, //gap {"buf_create", PF_buf_create, 440}, {"buf_del", PF_buf_del, 441}, @@ -1820,7 +1836,7 @@ void MP_Keydown(int key, int unicode) if (mp_keydown_function) { void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoDPCodes(key); + G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key); G_FLOAT(OFS_PARM1) = unicode; PR_ExecuteProgram(menu_world.progs, mp_keydown_function); } @@ -1845,7 +1861,7 @@ void MP_Keyup(int key, int unicode) if (mp_keyup_function) { void *pr_globals = PR_globals(menu_world.progs, PR_CURRENT); - G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoDPCodes(key); + G_FLOAT(OFS_PARM0) = MP_TranslateFTEtoQCCodes(key); G_FLOAT(OFS_PARM1) = unicode; PR_ExecuteProgram(menu_world.progs, mp_keyup_function); } diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index 71d9f8247..6f516f13b 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -35,6 +35,9 @@ qc must build the skeletal object still, which fills the skeletal object from th #include "quakedef.h" +qboolean Mod_FrameInfoForNum(model_t *model, int num, char **name, int *numframes, float *duration, qboolean *loop); +const char *Mod_SkinNameForNum(model_t *model, int num); + #if defined(RAGDOLL) || defined(SKELETALOBJECTS) #include "pr_common.h" @@ -116,9 +119,11 @@ static int numskelobjectsused; //copes with src==dst to convert rel->abs void skel_copy_toabs(skelobject_t *skelobjdst, skelobject_t *skelobjsrc, int startbone, int endbone) { - galiasbone_t *boneinfo = Mod_GetBoneInfo(skelobjsrc->model); + int maxbones; + galiasbone_t *boneinfo = Mod_GetBoneInfo(skelobjsrc->model, &maxbones); if (!boneinfo) return; + endbone = min(endbone, maxbones-1); if (skelobjsrc->type == SKOT_ABSOLUTE) { if (skelobjsrc != skelobjdst) @@ -289,6 +294,7 @@ int rag_finddolljoint(doll_t *d, char *name) typedef struct { qboolean errors; doll_t *d; + int numbones; galiasbone_t *bones; odebodyinfo_t *body; @@ -307,7 +313,7 @@ dollcreatectx_t *rag_createdoll(model_t *mod, char *fname, int numbones) ctx = malloc(sizeof(*ctx)); - ctx->bones = Mod_GetBoneInfo(mod); + ctx->bones = Mod_GetBoneInfo(mod, &ctx->numbones); ctx->errors = 0; memset(&ctx->defbody, 0, sizeof(ctx->defbody)); @@ -337,7 +343,7 @@ dollcreatectx_t *rag_createdoll(model_t *mod, char *fname, int numbones) ctx->d->uses = 0; ctx->d->joint = NULL; - ctx->d->numbones = numbones; + ctx->d->numbones = min(numbones, ctx->numbones); ctx->d->bone = BZ_Malloc(sizeof(*ctx->d->bone) * ctx->d->numbones); for (i = 0; i < ctx->d->numbones; i++) ctx->d->bone[i].bodyidx = -1; @@ -814,6 +820,150 @@ void skel_integrate(pubprogfuncs_t *prinst, skelobject_t *sko, skelobject_t *ske } #endif +void skel_generateragdoll_f_bones(vfsfile_t *f, galiasbone_t *bones, int numbones, int parent, int indent) +{ + int i, j; + for (i = 0; i < numbones; i++) + { + if (bones[i].parent == parent) + { + VFS_PUTS(f, "//"); + for (j = 0; j < indent; j++) + VFS_PUTS(f, "\t"); + VFS_PUTS(f, va("%i %s\n", i, bones[i].name)); + skel_generateragdoll_f_bones(f, bones, numbones, i, indent+1); + } + } +} +void skel_generateragdoll_f(void) +{ + char *modname = Cmd_Argv(1); + char *outname; + model_t *mod = Mod_ForName(modname, false); + galiasbone_t *bones; + vfsfile_t *f; + int i; + int numbones; + if (!mod) + { + Con_Printf("Cannot open %s\n", modname); + return; + } + bones = Mod_GetBoneInfo(mod, &numbones); + if (!bones || numbones < 1) + { + Con_Printf("Model %s has no bones\n", modname); + return; + } + outname = va("%s.doll", mod->name); + + f = FS_OpenVFS(outname, "wb", FS_GAMEONLY); + VFS_PUTS(f, va("//basic ragdoll info for model %s\n", mod->name)); + VFS_PUTS(f, va("//generated with: %s %s\n", Cmd_Argv(0), Cmd_Args())); + VFS_PUTS(f, "//this file will need editing by hand\n"); + VFS_PUTS(f, "//use the flush command to reload this file\n"); + + //print background bone info. + VFS_PUTS(f, "\n//bones are as follows:\n"); + skel_generateragdoll_f_bones(f, bones, numbones, -1, 0); + + //print background frame info. + VFS_PUTS(f, "\n//frames are as follows:\n"); + for (i = 0; i < 32768; i++) + { + char *fname; + int numframes; + float duration; + qboolean loop; + if (!Mod_FrameInfoForNum(mod, i, &fname, &numframes, &duration, &loop)) + break; + VFS_PUTS(f, va("//%i %s (%i frames) (%f secs)%s", i, fname, numframes, duration, loop?" (loop)":"")); + } + if (i == 0) + VFS_PUTS(f, "//NO FRAME INFO\n"); + + //print background frame info. + VFS_PUTS(f, "\n//skins are as follows:\n"); + for (i = 0; i < 32768; i++) + { + const char *sname; + sname = Mod_SkinNameForNum(mod, i); + if (!sname) + break; + VFS_PUTS(f, va("//%i %s", i, sname)); + } + if (i == 0) + VFS_PUTS(f, "//NO SKIN INFO\n"); + + VFS_PUTS(f, "\nupdatebody default\n"); + VFS_PUTS(f, "\tshape box //one of box, sphere, cylinder, capsule\n"); + VFS_PUTS(f, "\tdimensions 8 8 8\n"); + VFS_PUTS(f, "\tdraw 1 //1 for visualising debug, 0 for release\n"); + VFS_PUTS(f, "\tanimate 1 //0 will always be limp\n"); + VFS_PUTS(f, "\n"); + + //FIXME: only write out the bodies specified as arguments, and with no // + for (i = 0; i < numbones; i++) + VFS_PUTS(f, va("//body b_%s %s\n", bones[i].name, bones[i].name)); + VFS_PUTS(f, "\n"); + + VFS_PUTS(f, "updatejoint default\n"); + VFS_PUTS(f, "\ttype hinge //one of fixed, point, hinge, slider, universal, hinge2\n"); + VFS_PUTS(f, "\t//histop 1\n"); + VFS_PUTS(f, "\t//lostop -1\n"); + VFS_PUTS(f, "\t//histop2 1\n"); + VFS_PUTS(f, "\t//lostop2 -1\n"); + VFS_PUTS(f, "\t//erp\n"); + VFS_PUTS(f, "\t//erp2\n"); + VFS_PUTS(f, "\t//cfm\n"); + VFS_PUTS(f, "\t//cfm2\n"); + VFS_PUTS(f, "\t//fmax\n"); + VFS_PUTS(f, "\t//fmax2\n"); + VFS_PUTS(f, "\n"); + + for (i = 0; i < numbones; i++) + { + if (bones[i].parent >= 0) //don't generate joints for root bones. FIXME: also skip omitted bodies from argument list. + { + VFS_PUTS(f, va("//joint j_%s b_%s b_%s\n", bones[i].name, bones[bones[i].parent].name, bones[i].name)); + //FIXME: calc the extents in each pose and set the hi/lo stops. + } + } + VFS_PUTS(f, "\n"); + + VFS_CLOSE(f); +} +void skel_info_f(void) +{ + int i; + for (i = 0; i < numskelobjectsused; i++) + { + if (skelobjects[i].world) + { + extern world_t csqc_world; + Con_Printf("doll %i:\n", i); +#ifndef CLIENTONLY + if (skelobjects[i].world == &sv.world) + Con_Printf(" SSQC\n"); +#endif +#ifndef SERVERONLY + if (skelobjects[i].world == &csqc_world) + Con_Printf(" CSQC\n"); +#endif + Con_Printf(" type: %s\n", (skelobjects[i].type == SKOT_RELATIVE)?"parentspace":"modelspace"); + Con_Printf(" model: %s\n", skelobjects[i].model->name); + Con_Printf(" bone count: %i\n", skelobjects[i].numbones); + if (skelobjects[i].doll) + { + Con_Printf(" ragdoll: %s%s\n", skelobjects[i].doll->name, ((skelobjects[i].doll == skelobjects[i].model->dollinfo)?" (model default)":"")); + Con_Printf(" phys bodies: %i\n", skelobjects[i].doll->numbodies); + } + if (skelobjects[i].entity) + Con_Printf(" entity: %i (%s)\n", skelobjects[i].entity->entnum, skelobjects[i].world->progs->StringToNative(skelobjects[i].world->progs, skelobjects[i].entity->v->classname)); + } + } +} + /*destroys all skeletons*/ void skel_reset(pubprogfuncs_t *prinst) { @@ -987,7 +1137,8 @@ qboolean rag_instanciate(skelobject_t *sko, doll_t *doll, float *emat, wedict_t float *bmat; float bodymat[12], worldmat[12]; vec3_t aaa2[3]; - galiasbone_t *bones = Mod_GetBoneInfo(sko->model); + int numbones; + galiasbone_t *bones = Mod_GetBoneInfo(sko->model, &numbones); int bone; odebody_t *body1, *body2; odejointinfo_t *j; @@ -1065,7 +1216,8 @@ void rag_derive(skelobject_t *sko, skelobject_t *asko, float *emat) doll_t *doll = sko->doll; float *bmat = sko->bonematrix; float *amat = asko?asko->bonematrix:NULL; - galiasbone_t *bones = Mod_GetBoneInfo(sko->model); + int numbones; + galiasbone_t *bones = Mod_GetBoneInfo(sko->model, &numbones); int i; float invemat[12]; float bodymat[12], rel[12]; @@ -1281,7 +1433,7 @@ void rag_updatedeltaent(entity_t *ent, lerpents_t *le) skorel.numbones = sko->numbones; //FIXME: provide some way for the animation to auto-trigger ragdoll (so framegroups can work automagically) - if (ent->framestate.g[FS_REG].frame[0] == 65535 || ent->framestate.g[FS_REG].frame[1] == 65535) + if ((ent->framestate.g[FS_REG].frame[0] & 32767) || (ent->framestate.g[FS_REG].frame[1] & 32767)) sko->numanimated = 0; else if (sko->doll) sko->numanimated = sko->doll->numdefaultanimated; diff --git a/engine/client/quake.manifest b/engine/client/quake.manifest new file mode 100644 index 000000000..5eafbc15f --- /dev/null +++ b/engine/client/quake.manifest @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/engine/client/snd_directx.c b/engine/client/snd_directx.c index 34a7c07b0..6d384d068 100644 --- a/engine/client/snd_directx.c +++ b/engine/client/snd_directx.c @@ -966,7 +966,7 @@ static int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum) if (!sc->thread) { Con_SafePrintf ("Unable to create sound mixing thread\n"); - return SND_ERROR; + return SND_NOMORE; } //wait for the thread to finish (along with all its error con printfs etc diff --git a/engine/client/snd_sdl.c b/engine/client/snd_sdl.c index 014710e29..e5e1d8499 100644 --- a/engine/client/snd_sdl.c +++ b/engine/client/snd_sdl.c @@ -36,7 +36,6 @@ static unsigned int SSDL_GetDMAPos(soundcardinfo_t *sc) static void VARGS SSDL_Paint(void *userdata, qbyte *stream, int len) { soundcardinfo_t *sc = userdata; - int buffersize = sc->sn.samples*(sc->sn.samplebits/8); #ifdef SELFPAINT sc->sn.buffer = stream; @@ -45,6 +44,8 @@ static void VARGS SSDL_Paint(void *userdata, qbyte *stream, int len) S_MixerThread(sc); sc->snd_sent += len; #else + int buffersize = sc->sn.samples*(sc->sn.samplebits/8); + if (len > buffersize) { len = buffersize; //whoa nellie! diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 3157d8613..c1f833303 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -61,6 +61,10 @@ unsigned int sys_parentheight; extern int fs_switchgame; +//used to do special things with awkward windows versions. +int qwinvermaj; +int qwinvermin; + #ifdef RESTARTTEST jmp_buf restart_jmpbuf; @@ -594,7 +598,8 @@ DWORD CrashExceptionHandler (qboolean iswatchdog, DWORD exceptionCode, LPEXCEPTI /*if we have a current window, kill it, so it can't steal input of handle window messages or anything risky like that*/ if (iswatchdog) - ShowWindow(mainwindow, SW_MINIMIZE); + { + } else DestroyWindow(mainwindow); @@ -811,7 +816,7 @@ qboolean Sys_Rename (char *oldfname, char *newfname) return !rename(oldfname, newfname); } -static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) +static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) { HANDLE r; WIN32_FIND_DATA fd; @@ -917,7 +922,7 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart return go; } -int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) +int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) { char fullmatch[MAX_OSPATH]; int start; @@ -966,7 +971,11 @@ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) } } - +void Sys_DoFileAssociations(qboolean elevated); +void Sys_Register_File_Associations_f(void) +{ + Sys_DoFileAssociations(0); +} /* ================ Sys_Init @@ -981,6 +990,7 @@ void Sys_Init (void) #ifndef SERVERONLY Cvar_Register(&sys_disableWinKeys, "System vars"); Cvar_Register(&sys_disableTaskSwitch, "System vars"); + Cmd_AddCommandD("sys_register_file_associations", Sys_Register_File_Associations_f, "Register FTE as the system handler for .bsp .mvd .qwd .dem files. Also register the qw:// URL protocol. This command will probably trigger a UAC prompt in Windows Vista and up. Deny it for current-user-only asociations (will also prevent listing in windows' 'default programs' ui due to microsoft bugs/limitations)."); #ifndef CLIENTONLY if (!isDedicated && !COM_CheckParm("-nomutex")) @@ -1050,6 +1060,9 @@ void Sys_Init (void) WinNT = true; else WinNT = false; + + qwinvermaj = vinfo.dwMajorVersion; + qwinvermin = vinfo.dwMinorVersion; } @@ -1738,7 +1751,7 @@ WinMain HINSTANCE global_hInstance; int global_nCmdShow; char *argv[MAX_NUM_ARGVS]; -static char exename[256]; +static char exename[MAX_PATH]; HWND hwnd_dialog; @@ -2022,6 +2035,15 @@ void Sys_RecentServer(char *command, char *target, char *title, char *desc) SHAddToRecentDocs(SHARD_APPIDINFOLINK, &appinfo); IShellLinkW_Release(link); } + + +typedef struct { + LPCWSTR pcszFile; + LPCWSTR pcszClass; + enum qOPEN_AS_INFO_FLAGS oaifInFlags; +} qOPENASINFO; +HRESULT (WINAPI *pSHOpenWithDialog)(HWND hwndParent, const qOPENASINFO *poainfo); + void Win7_Init(void) { HANDLE h; @@ -2031,6 +2053,8 @@ void Win7_Init(void) h = LoadLibrary("shell32.dll"); if (h) { + pSHOpenWithDialog = (void*)GetProcAddress(h, "SHOpenWithDialog"); + pSetCurrentProcessExplicitAppUserModelID = (void*)GetProcAddress(h, "SetCurrentProcessExplicitAppUserModelID"); if (pSetCurrentProcessExplicitAppUserModelID) pSetCurrentProcessExplicitAppUserModelID(WIN7_APPNAME); @@ -2149,6 +2173,20 @@ void Win7_TaskListInit(void) #endif +int MyRegGetIntValue(HKEY base, char *keyname, char *valuename, int defaultval) +{ + int result = defaultval; + DWORD datalen = sizeof(result); + HKEY subkey; + DWORD type = REG_NONE; + if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS) + { + if (ERROR_SUCCESS != RegQueryValueEx(subkey, valuename, NULL, &type, (void*)&result, &datalen) || type != REG_DWORD) + result = defaultval; + RegCloseKey (subkey); + } + return result; +} qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen) { qboolean result = false; @@ -2168,16 +2206,39 @@ qboolean MyRegGetStringValue(HKEY base, char *keyname, char *valuename, void *da return result; } -#ifdef UPDATE_URL - -void MyRegSetValue(HKEY base, char *keyname, char *valuename, int type, void *data, int datalen) +qboolean MyRegSetValue(HKEY base, char *keyname, char *valuename, int type, void *data, int datalen) { + qboolean result = false; HKEY subkey; + + //'trivially' return success if its already set. + //this allows success even when we don't have write access. + if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS) + { + DWORD oldtype; + char olddata[2048]; + DWORD olddatalen = sizeof(olddata); + result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &oldtype, olddata, &olddatalen); + RegCloseKey (subkey); + + if (oldtype == REG_SZ || oldtype == REG_EXPAND_SZ) + { + while(olddatalen > 0 && olddata[olddatalen-1] == 0) + olddatalen--; + } + + if (result && datalen == olddatalen && type == oldtype && !memcmp(data, olddata, datalen)) + return result; + result = false; + } + if (RegCreateKeyEx(base, keyname, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) { - RegSetValueEx(subkey, valuename, 0, type, data, datalen); + if (ERROR_SUCCESS == RegSetValueEx(subkey, valuename, 0, type, data, datalen)) + result = true; RegCloseKey (subkey); } + return result; } void MyRegDeleteKeyValue(HKEY base, char *keyname, char *valuename) { @@ -2188,6 +2249,7 @@ void MyRegDeleteKeyValue(HKEY base, char *keyname, char *valuename) RegCloseKey (subkey); } } +#ifdef UPDATE_URL qboolean Update_GetHomeDirectory(char *homedir, int homedirsize) { @@ -2360,6 +2422,8 @@ qboolean Sys_CheckUpdated(void) if (CreateProcess(com_argv[ffe+2], va("--fromfrontend \"%s\" \"%s\" %s", "", "", COM_Parse(GetCommandLineA())), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) return true; } + if (com_argv[ffe+2]) + com_argv[0] = com_argv[ffe+2]; } doupdatecheck = true; return false; @@ -2374,6 +2438,165 @@ void Update_Check(void) } #endif +#include "shellapi.h" +const GUID qIID_IApplicationAssociationRegistrationUI = {0x1f76a169,0xf994,0x40ac, {0x8f,0xc8,0x09,0x59,0xe8,0x87,0x47,0x10}}; +const GUID qCLSID_ApplicationAssociationRegistrationUI = {0x1968106d,0xf3b5,0x44cf,{0x89,0x0e,0x11,0x6f,0xcb,0x9e,0xce,0xf1}}; +struct qIApplicationAssociationRegistrationUI; +typedef struct qIApplicationAssociationRegistrationUI +{ + struct qIApplicationAssociationRegistrationUI_vtab + { + HRESULT (WINAPI *QueryInterface) (struct qIApplicationAssociationRegistrationUI *, const GUID *riid, void **ppvObject); + HRESULT (WINAPI *AddRef) (struct qIApplicationAssociationRegistrationUI *); + HRESULT (WINAPI *Release) (struct qIApplicationAssociationRegistrationUI *); + HRESULT (WINAPI *LaunchAdvancedAssociationUI) (struct qIApplicationAssociationRegistrationUI *, LPCWSTR app); + } *lpVtbl; +} qIApplicationAssociationRegistrationUI; + +void Sys_DoFileAssociations(qboolean elevated) +{ + char command[1024]; + qboolean ok = true; + HKEY root; + + //I'd do everything in current_user if I could, but windows sucks too much for that. + //'registered applications' simply does not work in hkcu, we MUST use hklm for that. + //if there's a registered application and we are not, we are unable to grab that association, ever. + //thus we HAVE to do things to the local machine or we might as well not bother doing anything. + //still, with a manifest not giving false success, if the user clicks 'no' to the UAC prompt, we'll write everything to the current user anyway, so if microsoft do ever fix things, then yay. + //also, I hate the idea of creating a 'registered application' in globally without the file types it uses being local. + + //on xp, we use ONLY current user. no 'registered applications' means no 'registered applications bug', which means no need to use hklm at all. + //in vista/7, we have to create stuff in local_machine. in which case we might as well put ALL associations in there. the ui stuff will allow user-specific settings, so this is not an issue other than the fact that it triggers uac. + //in 8, we cannot programatically force ownership of our associations, so we might as well just use the ui method even for vista+7 instead of the ruder version. + if (qwinvermaj < 6) + elevated = 2; + + root = elevated == 2?HKEY_CURRENT_USER:HKEY_LOCAL_MACHINE; + + #define ASSOC_VERSION 2 +#define ASSOCV "1" + + //register the basic demo class + Q_snprintfz(command, sizeof(command), "Quake or QuakeWorld Demo", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_DemoFile."ASSOCV, "", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "\"%s\",0", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_DemoFile."ASSOCV"\\DefaultIcon", "", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "\"%s\" \"%%1\"", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_DemoFile."ASSOCV"\\shell\\open\\command", "", REG_SZ, command, strlen(command)); + + //register the basic map class. yeah, the command is the same as for demos. but the description is different! + Q_snprintfz(command, sizeof(command), "Quake Map", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_BSPFile."ASSOCV, "", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "\"%s\",0", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_BSPFile."ASSOCV"\\DefaultIcon", "", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "\"%s\" \"%%1\"", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_BSPFile."ASSOCV"\\shell\\open\\command", "", REG_SZ, command, strlen(command)); + + //register the basic protocol class + Q_snprintfz(command, sizeof(command), "QuakeWorld Server"); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_Server."ASSOCV"", "", REG_SZ, command, strlen(command)); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_Server."ASSOCV"", "URL Protocol", REG_SZ, "", strlen("")); + Q_snprintfz(command, sizeof(command), "\"%s\",0", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_Server."ASSOCV"\\DefaultIcon", "", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "\"%s\" \"%%1\"", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\Classes\\"DISTRIBUTION"_Server."ASSOCV"\\shell\\open\\command", "", REG_SZ, command, strlen(command)); + + //try to get ourselves listed in windows' 'default programs' ui. + Q_snprintfz(command, sizeof(command), "%s", FULLENGINENAME); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities", "ApplicationName", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "%s", FULLENGINENAME" is an awesome hybrid game engine able to run multiple Quake-compatible/derived games.", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities", "ApplicationDescription", REG_SZ, command, strlen(command)); + + Q_snprintfz(command, sizeof(command), DISTRIBUTION"_DemoFile.1", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".qtv", REG_SZ, command, strlen(command)); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".mvd", REG_SZ, command, strlen(command)); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".qwd", REG_SZ, command, strlen(command)); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".dem", REG_SZ, command, strlen(command)); +// ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".dm2", REG_SZ, command, strlen(command)); + + Q_snprintfz(command, sizeof(command), DISTRIBUTION"_BSPFile.1", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".bsp", REG_SZ, command, strlen(command)); + +// ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\FileAssociations", ".fmf", REG_SZ, DISTRIBUTION"_ManifestFile", strlen(DISTRIBUTION"_ManifestFile")); +// ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\MIMEAssociations", "application/x-ftemanifest", REG_SZ, DISTRIBUTION"_ManifestFile", strlen(DISTRIBUTION"_ManifestFile")); + + Q_snprintfz(command, sizeof(command), DISTRIBUTION"_Server.1", com_argv[0]); + ok = ok & MyRegSetValue(root, "Software\\"FULLENGINENAME"\\Capabilities\\UrlAssociations", "qw", REG_SZ, command, strlen(command)); + + Q_snprintfz(command, sizeof(command), "Software\\"FULLENGINENAME"\\Capabilities"); + ok = ok & MyRegSetValue(root, "Software\\RegisteredApplications", FULLENGINENAME, REG_SZ, command, strlen(command)); + + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + + if (!ok && elevated < 2) + { + HINSTANCE ch = ShellExecute(mainwindow, "runas", com_argv[0], va("-register_types %i", elevated+1), NULL, SW_SHOWNORMAL); + if ((int)ch <= 32) + Sys_DoFileAssociations(2); + return; + } + + if (ok) + { +// char buf[1]; + //attempt to display the vista+ prompt (only way possible in win8, apparently) + qIApplicationAssociationRegistrationUI *aarui = NULL; + + //needs to be done anyway to ensure that its listed, and so that we get the association if nothing else has it. + //however, the popup for when you start new programs is very annoying, so lets try to avoid that. our file associations are somewhat explicit anyway. + //note that you'll probably still get the clumsy prompt if you try to run fte as a different user. really depends if you gave it local machine write access. +// if (!aarui || elevated==2 || !MyRegGetStringValue(root, "Software\\Classes\\.qtv", "", buf, sizeof(buf))) + MyRegSetValue(root, "Software\\Classes\\.qtv", "", REG_SZ, DISTRIBUTION"_DemoFile."ASSOCV, strlen(DISTRIBUTION"_DemoFile.1")); +// if (!aarui || elevated==2 || !MyRegGetStringValue(root, "Software\\Classes\\.mvd", "", buf, sizeof(buf))) + MyRegSetValue(root, "Software\\Classes\\.mvd", "", REG_SZ, DISTRIBUTION"_DemoFile."ASSOCV, strlen(DISTRIBUTION"_DemoFile.1")); +// if (!aarui || elevated==2 || !MyRegGetStringValue(root, "Software\\Classes\\.qwd", "", buf, sizeof(buf))) + MyRegSetValue(root, "Software\\Classes\\.qwd", "", REG_SZ, DISTRIBUTION"_DemoFile."ASSOCV, strlen(DISTRIBUTION"_DemoFile.1")); +// if (!aarui || elevated==2 || !MyRegGetStringValue(root, "Software\\Classes\\.dem", "", buf, sizeof(buf))) + MyRegSetValue(root, "Software\\Classes\\.dem", "", REG_SZ, DISTRIBUTION"_DemoFile."ASSOCV, strlen(DISTRIBUTION"_DemoFile.1")); +// if (!aarui || elevated==2 || !MyRegGetStringValue(root, "Software\\Classes\\.bsp", "", buf, sizeof(buf))) + MyRegSetValue(root, "Software\\Classes\\.bsp", "", REG_SZ, DISTRIBUTION"_BSPFile."ASSOCV, strlen(DISTRIBUTION"_BSPFile.1")); + //legacy url associations are a bit more explicit +// if (!aarui || elevated==2 || !MyRegGetStringValue(HKEY_CURRENT_USER, "Software\\Classes\\qw", "", buf, sizeof(buf))) + { + Q_snprintfz(command, sizeof(command), "QuakeWorld Server"); + MyRegSetValue(root, "Software\\Classes\\qw", "", REG_SZ, command, strlen(command)); + MyRegSetValue(root, "Software\\Classes\\qw", "URL Protocol", REG_SZ, "", strlen("")); + Q_snprintfz(command, sizeof(command), "\"%s\",0", com_argv[0]); + MyRegSetValue(root, "Software\\Classes\\qw\\DefaultIcon", "", REG_SZ, command, strlen(command)); + Q_snprintfz(command, sizeof(command), "\"%s\" \"%%1\"", com_argv[0]); + MyRegSetValue(root, "Software\\Classes\\qw\\shell\\open\\command", "", REG_SZ, command, strlen(command)); + } + + CoInitialize(NULL); + if (FAILED(CoCreateInstance(&qCLSID_ApplicationAssociationRegistrationUI, 0, CLSCTX_INPROC_SERVER, &qIID_IApplicationAssociationRegistrationUI, (LPVOID*)&aarui))) + aarui = NULL; + + if (aarui) + { +#define wideify2(a) L##a +#define wideify(a) wideify2(a) + aarui->lpVtbl->LaunchAdvancedAssociationUI(aarui, wideify(FULLENGINENAME)); + aarui->lpVtbl->Release(aarui); + } + else + { + +/* +#define wideify2(a) L##a +#define wideify(a) wideify2(a) + qOPENASINFO open_as_info = {0}; + open_as_info.pcszFile = L".mvd"; + open_as_info.pcszClass = wideify(DISTRIBUTION)L"_DemoFile.1"; + open_as_info.oaifInFlags = 8 | 2;//OAIF_FORCE_REGISTRATION | OAIF_REGISTER_EXT; + if (pSHOpenWithDialog) + pSHOpenWithDialog(NULL, &open_as_info); + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); +*/ + } + } +} + /* #ifdef _MSC_VER #include @@ -2386,12 +2609,45 @@ void VARGS Signal_Error_Handler(int i) #endif */ +void Sys_RunFile(const char *fname, int nlen) +{ + char buffer[MAX_OSPATH]; + char *ext; + if (nlen >= MAX_OSPATH) + { + Con_Printf("Filename too long.\n"); + return; + } + + memcpy(buffer, fname, nlen); + buffer[nlen] = 0; + fname = buffer; + ext = COM_FileExtension(fname); + if (!strncmp(fname, "qw:", 3)) + { + fname += 3; + if (!strncmp(fname, "//", 2)) + fname += 2; + ext = strchr(fname, '/'); //this also protects us against irc urls, etc. unsure if that's important right now. + if (ext) + *ext = 0; + Con_Printf("QW stream: \"%s\"\n", fname); + Cbuf_AddText(va("connect \"%s\"\n", fname), RESTRICT_LOCAL); + } + else if (!strcmp(ext, "qwd") || !strcmp(ext, "dem") || !strcmp(ext, "mvd")) + Cbuf_AddText(va("playdemo \"#%s\"\n", fname), RESTRICT_LOCAL); + else if (!strcmp(ext, "bsp")) + Cbuf_AddText(va("map \"#%s\"\n", fname), RESTRICT_LOCAL); + else + Cbuf_AddText(va("qtvplay \"#%s\"\n", fname), RESTRICT_LOCAL); +} + int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // MSG msg; quakeparms_t parms; double time, oldtime, newtime; - char cwd[1024], bindir[1024], *s; + char cwd[1024], bindir[1024]; const char *qtvfile = NULL; int delay = 0; @@ -2399,6 +2655,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (hPrevInstance) return 0; + Sys_SetThreadName(-1, "main thread"); + memset(&parms, 0, sizeof(parms)); #ifndef MINGW @@ -2498,9 +2756,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin #endif GetModuleFileName(NULL, bindir, sizeof(bindir)-1); - s = COM_SkipPath(exename); - strcpy(exename, s); - *s = 0; + Q_strncpyz(exename, bindir, sizeof(exename)); + *COM_SkipPath(bindir) = 0; parms.argv = (const char **)argv; COM_InitArgv (parms.argc, parms.argv); @@ -2508,12 +2765,31 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (Sys_CheckUpdated()) return true; + isPlugin = !!COM_CheckParm("-plugin"); + + if (COM_CheckParm("-register_types")) + { + Sys_DoFileAssociations(1); + return true; + } + /* + else if (!isPlugin) + { + if (MyRegGetIntValue(HKEY_CURRENT_USER, "Software\\"FULLENGINENAME, "filetypes", -1) != ASSOC_VERSION) + { + DWORD dw = ASSOC_VERSION; + if (IDYES == MessageBox(NULL, "Register file associations?", "FTE First Start", MB_YESNO)) + Sys_DoFileAssociations(0); + MyRegSetValue(HKEY_CURRENT_USER, "Software\\"FULLENGINENAME, "filetypes", REG_DWORD, &dw, sizeof(dw)); + } + } + */ + #ifdef CATCHCRASH if (COM_CheckParm("-watchdog")) Sys_CreateThread("watchdog", watchdogthread, NULL, 0, 0); #endif - isPlugin = !!COM_CheckParm("-plugin"); if (isPlugin) { printf("status Starting up!\n"); @@ -2536,7 +2812,31 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin { char *e; - qtvfile = parms.argv[1]; + if (parms.argc == 2 && !strchr(parms.argv[1], '\"') && !strchr(parms.argv[1], ';') && !strchr(parms.argv[1], '\n') && !strchr(parms.argv[1], '\r')) + { + HWND old; + qtvfile = parms.argv[1]; + + old = FindWindow("FTEGLQuake", NULL); + if (!old) + old = FindWindow("FTED3D11QUAKE", NULL); + if (!old) + old = FindWindow("FTED3D9QUAKE", NULL); + if (old) + { + COPYDATASTRUCT cds; + cds.dwData = 0xdeadf11eu; + cds.cbData = strlen(qtvfile); + cds.lpData = (void*)qtvfile; + if (SendMessage(old, WM_COPYDATA, (WPARAM)GetDesktopWindow(), (LPARAM)&cds)) + return 0; //message sent. + } + } + else + { + MessageBox(NULL, "Expected one argument, got multiple", "Blocking potential remote exploit", 0); + return 0; + } GetModuleFileName(NULL, cwd, sizeof(cwd)-1); for (e = cwd+strlen(cwd)-1; e >= cwd; e--) @@ -2613,11 +2913,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (qtvfile) { - char *ext = COM_FileExtension(qtvfile); - if (!strcmp(ext, "qwd") || !strcmp(ext, "dem") || !strcmp(ext, "mvd")) - Cbuf_AddText(va("playdemo \"#%s\"\n", qtvfile), RESTRICT_LOCAL); - else - Cbuf_AddText(va("qtvplay \"#%s\"\n", qtvfile), RESTRICT_LOCAL); + Sys_RunFile(qtvfile, strlen(qtvfile)); } //client console should now be initialized. diff --git a/engine/client/textedit.c b/engine/client/textedit.c index a5f2e0fd3..a84a72450 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -809,6 +809,7 @@ void Editor_Key(int key, int unicode) break; case K_ENTER: + case K_KP_ENTER: if (editenabled) { fileblock_t *b = cursorblock; diff --git a/engine/client/valid.c b/engine/client/valid.c index 66641ff48..3334912c0 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -300,7 +300,7 @@ static void Validation_Server(void) #endif if (!allow_f_server.ival) return; - Cbuf_AddText(va("say server is %s\n", NET_AdrToString(adr, sizeof(adr), cls.netchan.remote_address)), RESTRICT_LOCAL); + Cbuf_AddText(va("say server is %s\n", NET_AdrToString(adr, sizeof(adr), &cls.netchan.remote_address)), RESTRICT_LOCAL); } static void Validation_Skins(void) @@ -530,7 +530,7 @@ void Validation_AllChecks(void) } //get the current server address - NET_AdrToString(servername, sizeof(servername), cls.netchan.remote_address); + NET_AdrToString(servername, sizeof(servername), &cls.netchan.remote_address); //get the ruleset names if (!Validation_GetCurrentRulesetName(ruleset, sizeof(ruleset), true)) diff --git a/engine/client/winquake.rc b/engine/client/winquake.rc index fc551e72e..7f576c4fa 100644 --- a/engine/client/winquake.rc +++ b/engine/client/winquake.rc @@ -145,6 +145,10 @@ END ///////////////////////////////////////////////////////////////////////////// +//we need to use a manifest to avoid issues with UAC and hidden/buggy writes. There is no sane/other way to turn off virtualisation. +//oh god, this is going to fuck over xp, isn't it. +1 24 "quake.manifest" + #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 704a8392c..f532dd42c 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -410,6 +410,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #else #define PLATFORM "Win32" #endif + #define ARCH_DL_POSTFIX ".dll" #elif defined(ANDROID) #define PLATFORM "Android" /*technically also linux*/ #elif defined(__linux__) @@ -433,6 +434,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #endif +#ifndef ARCH_DL_POSTFIX + #define ARCH_DL_POSTFIX ".so" +#endif + +#if defined(__amd64__) + #define ARCH_CPU_POSTFIX "amd" +#elif defined(_M_IX86) || defined(__i386__) + #define ARCH_CPU_POSTFIX "x86" +#elif defined(__powerpc__) || defined(__ppc__) + #define ARCH_CPU_POSTFIX "ppc" +#elif defined(__arm__) + #define ARCH_CPU_POSTFIX "arm" +#else + #define ARCH_CPU_POSTFIX "unk" +#endif #if (defined(_M_IX86) || defined(__i386__)) && !defined(__amd64__) && !defined(_AMD64_) #define UNALIGNED_OK 1 // set to 0 if unaligned accesses are not supported @@ -510,7 +526,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SOUND_CHANNELS 8 -#define MAX_QPATH 64 // max length of a quake game pathname +#define MAX_QPATH 128 // max length of a quake game pathname #define MAX_OSPATH 256 // max length of a filesystem pathname #define ON_EPSILON 0.1 // point on plane side epsilon diff --git a/engine/common/cmd.c b/engine/common/cmd.c index ad73b02ba..3087251a1 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2975,6 +2975,18 @@ static char *Macro_UKDate (void) //and much but not all of EU strftime (macro_buf, sizeof(macro_buf)-1, "%d.%m.%Y", ptm); return macro_buf; } +static char *Macro_USDate (void) //and much but not all of EU +{ + time_t t; + struct tm *ptm; + + time (&t); + ptm = localtime (&t); + if (!ptm) + return "#bad date#"; + strftime (macro_buf, sizeof(macro_buf)-1, "%m.%s.%Y", ptm); + return macro_buf; +} static char *Macro_ProperDate (void) //americans get it wrong. besides, this is more easily sortable for filenames etc { time_t t; @@ -3049,8 +3061,9 @@ void Cmd_Init (void) Cmd_AddCommand ("fs_flush", COM_RefreshFSCache_f); Cmd_AddMacro("time", Macro_Time, true); - Cmd_AddMacro("date", Macro_UKDate, false); - Cmd_AddMacro("properdate", Macro_ProperDate, false); + Cmd_AddMacro("ukdate", Macro_UKDate, false); + Cmd_AddMacro("usdate", Macro_USDate, false); + Cmd_AddMacro("date", Macro_ProperDate, false); Cmd_AddMacro("version", Macro_Version, false); Cmd_AddMacro("qt", Macro_Quote, false); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 2c3e28e87..42b7cf0ba 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -2180,7 +2180,7 @@ static qboolean VARGS Mod_TryAddSkin(const char *skinname, ...) return true; } -int Mod_EnumerateSkins(const char *name, int size, void *param, void *spath) +int QDECL Mod_EnumerateSkins(const char *name, int size, void *param, void *spath) { Mod_TryAddSkin(name); return true; @@ -3502,7 +3502,7 @@ int Mod_GetBoneRelations(model_t *model, int firstbone, int lastbone, framestate return 0; } -galiasbone_t *Mod_GetBoneInfo(model_t *model) +galiasbone_t *Mod_GetBoneInfo(model_t *model, int *numbones) { #ifdef SKELETALMODELS galiasbone_t *bone; @@ -3515,8 +3515,10 @@ galiasbone_t *Mod_GetBoneInfo(model_t *model) inf = Mod_Extradata(model); bone = (galiasbone_t*)((char*)inf + inf->ofsbones); + *numbones = inf->numbones; return bone; #else + *numbones = 0; return NULL; #endif } @@ -3884,6 +3886,29 @@ const char *Mod_FrameNameForNum(model_t *model, int num) return group[num].name; } +qboolean Mod_FrameInfoForNum(model_t *model, int num, char **name, int *numframes, float *duration, qboolean *loop) +{ + galiasgroup_t *group; + galiasinfo_t *inf; + + if (!model) + return false; + if (model->type != mod_alias) + return false; + + inf = Mod_Extradata(model); + + if (num >= inf->groups) + return false; + group = (galiasgroup_t*)((char*)inf + inf->groupofs); + + *name = group[num].name; + *numframes = group[num].numposes; + *loop = group[num].loop; + *duration = group->numposes/group->rate; + return true; +} + const char *Mod_SkinNameForNum(model_t *model, int num) { #ifdef SERVERONLY diff --git a/engine/common/common.c b/engine/common/common.c index 7a28cbd1d..48c36cd51 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -497,6 +497,16 @@ void Q_ftoa(char *str, float in) } } +static int dehex(int i) +{ + if (i >= '0' && i <= '9') + return (i-'0'); + else if (i >= 'A' && i <= 'F') + return (i-'A'+10); + else + return (i-'a'+10); +} + int Q_atoi (const char *str) { int val; @@ -1936,7 +1946,7 @@ unsigned int utf8_decode(int *error, const void *in, char **out) { l = 2; uc = ((str[0] & 0x1f)<<6) | (str[1] & 0x3f); - if (uc >= (1u<<7)) + if (!uc || uc >= (1u<<7)) //allow modified utf-8 *error = 0; else *error = 2; @@ -2071,20 +2081,69 @@ unsigned int utf8_decode(int *error, const void *in, char **out) return uc; } + +unsigned int unicode_decode(int *error, const void *in, char **out) +{ + unsigned int charcode; + if (((char*)in)[0] == '^' && ((char*)in)[1] == 'U' && ishexcode(((char*)in)[2]) && ishexcode(((char*)in)[3]) && ishexcode(((char*)in)[4]) && ishexcode(((char*)in)[5])) + { + *out = (char*)in + 6; + charcode = (dehex(((char*)in)[2]) << 12) | (dehex(((char*)in)[2]) << 8) | (dehex(((char*)in)[2]) << 4) | (dehex(((char*)in)[2]) << 0); + } + else if (((char*)in)[0] == '^' && ((char*)in)[1] == '{') + { + *out = (char*)in + 2; + charcode = 0; + while (ishexcode(**out)) + { + charcode <<= 4; + charcode |= dehex(**out); + *out+=1; + } + if (**out == '}') + *out+=1; + } + else if (com_parseutf8.ival > 0) + charcode = utf8_decode(error, in, out); + else if (com_parseutf8.ival) + { + *error = 0; + charcode = *(unsigned char*)in; //iso8859-1 + *out = (char*)in + 1; + } + else + { //quake + *error = 0; + charcode = *(unsigned char*)in; + if (charcode != '\n' && charcode != '\t' && charcode != '\r' && (charcode < ' ' || charcode > 127)) + charcode |= 0xe000; + *out = (char*)in + 1; + } + + return charcode; +} + unsigned int utf8_encode(void *out, unsigned int unicode, int maxlen) { unsigned int bcount = 1; unsigned int lim = 0x80; unsigned int shift; - while (unicode >= lim) + if (!unicode) + { //modified utf-8 encodes encapsulated nulls as over-long. + bcount = 2; + } + else { - if (bcount == 1) - lim <<= 4; - else if (bcount < 7) - lim <<= 5; - else - lim <<= 6; - bcount++; + while (unicode >= lim) + { + if (bcount == 1) + lim <<= 4; + else if (bcount < 7) + lim <<= 5; + else + lim <<= 6; + bcount++; + } } //error if needed @@ -2224,6 +2283,101 @@ unsigned int unicode_encode(char *out, unsigned int unicode, int maxlen) return qchar_encode(out, unicode, maxlen); } +//char-based strlen. +unsigned int unicode_charcount(char *in, size_t buffersize) +{ + int error; + char *end = in + buffersize; + int chars = 0; + for(chars = 0; in < end && *in; chars+=1) + { + unicode_decode(&error, in, &in); + + if (in > end) + break; //exceeded buffer size uncleanly + } + return chars; +} + +//handy hacky function. +unsigned int unicode_byteofsfromcharofs(char *str, unsigned int charofs) +{ + char *in = str; + int error; + int chars = 0; + for(chars = 0; *in; chars+=1) + { + if (chars >= charofs) + return in - str; + + unicode_decode(&error, in, &in); + } + return chars; +} +//handy hacky function. +unsigned int unicode_charofsfrombyteofs(char *str, unsigned int byteofs) +{ + int error; + char *end = str + byteofs; + int chars = 0; + for(chars = 0; str < end && *str; chars+=1) + { + unicode_decode(&error, str, &str); + + if (str > end) + break; //exceeded buffer size uncleanly + } + return chars; +} + +size_t unicode_strtoupper(char *in, char *out, size_t outsize) +{ + //warning: towupper is locale-specific (eg: turkish has both I and dotted-I and thus i should transform to dotted-I rather than to I). + //also it can't easily cope with accent prefixes. + int error; + unsigned int c; + size_t l = 0; + outsize -= 1; + + while(*in) + { + c = unicode_decode(&error, in, &in); + if (c >= 0xe020 && c <= 0xe07f) //quake-char-aware. + c = towupper(c & 0x7f) + (c & 0xff80); + else + c = towupper(c); + l = unicode_encode(out, c, outsize - l); + out += l; + } + *out = 0; + + return l; +} + +size_t unicode_strtolower(char *in, char *out, size_t outsize) +{ + //warning: towlower is locale-specific (eg: turkish has both i and dotless-i and thus I should transform to dotless-i rather than to i). + //also it can't easily cope with accent prefixes. + int error; + unsigned int c; + size_t l = 0; + outsize -= 1; + + while(*in) + { + c = unicode_decode(&error, in, &in); + if (c >= 0xe020 && c <= 0xe07f) //quake-char-aware. + c = towlower(c & 0x7f) + (c & 0xff80); + else + c = towlower(c); + l = unicode_encode(out, c, outsize - l); + out += l; + } + *out = 0; + + return l; +} + ///===================================== // This is the standard RGBI palette used in CGA text mode @@ -2412,16 +2566,6 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q return out; } -static int dehex(int i) -{ - if (i >= '0' && i <= '9') - return (i-'0'); - else if (i >= 'A' && i <= 'F') - return (i-'A'+10); - else - return (i-'a'+10); -} - //Takes a q3-style fun string, and returns an expanded string-with-flags (actual return value is the null terminator) //outsize parameter is in _BYTES_ (so sizeof is safe). conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, int flags) @@ -2618,7 +2762,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t { int len; uc = 0; - for (len = 2; (str[len] >= '0' && str[len] <= '9') || (str[len] >= 'a' && str[len] <= 'f') || (str[len] >= 'A' && str[len] <= 'F'); len++) + for (len = 2; ishexcode(str[len]); len++) { uc <<= 4; uc |= dehex(str[len]); @@ -2673,24 +2817,9 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t //we don't support the full 12bit colour depth (only 4-bit CGA) //so find the closest that we do support int r, g, b; - if (str[2] >= '0' && str[2] <= '9') - r = (str[2]-'0'); - else if (str[2] >= 'A' && str[2] <= 'F') - r = (str[2]-'A'+10); - else - r = (str[2]-'a'+10); - if (str[3] >= '0' && str[3] <= '9') - g = (str[3]-'0'); - else if (str[3] >= 'A' && str[3] <= 'F') - g = (str[3]-'A'+10); - else - g = (str[3]-'a'+10); - if (str[4] >= '0' && str[4] <= '9') - b = (str[4]-'0'); - else if (str[4] >= 'A' && str[4] <= 'F') - b = (str[4]-'A'+10); - else - b = (str[4]-'a'+10); + r = dehex(str[2]); + g = dehex(str[3]); + b = dehex(str[4]); ext = (ext & ~CON_RICHFOREMASK) | CON_RICHFORECOLOUR; ext |= r<Close(vf)) @@ -388,6 +399,7 @@ void VARGS VFS_PRINTF(vfsfile_t *vf, char *fmt, ...) LIKEPRINTF(2); enum fs_relative{ FS_GAME, //standard search (not generally valid for save/rename/delete/etc) + FS_BINARYPATH, //for dlls and stuff FS_ROOT, //./ FS_GAMEONLY, //$gamedir/ FS_GAMEDOWNLOADCACHE, //typically the same as FS_GAMEONLY @@ -442,7 +454,7 @@ qbyte *COM_LoadFile (const char *path, int usehunk); qboolean COM_LoadMapPackFile(const char *name, int offset); void COM_FlushTempoaryPacks(void); -void COM_EnumerateFiles (const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm); +void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm); extern struct cvar_s registered; extern qboolean standard_quake; //fixme: remove diff --git a/engine/common/console.h b/engine/common/console.h index 89dba0baf..bdbdc1171 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -165,7 +165,7 @@ char *Con_CopyConsole(qboolean nomarkup); void Con_Print (char *txt); void VARGS Con_Printf (const char *fmt, ...) LIKEPRINTF(1); void VARGS Con_TPrintf (translation_t text, ...); -void VARGS Con_DPrintf (char *fmt, ...) LIKEPRINTF(1); +void VARGS Con_DPrintf (const char *fmt, ...) LIKEPRINTF(1); void VARGS Con_SafePrintf (char *fmt, ...) LIKEPRINTF(1); void Con_Footerf(qboolean append, char *fmt, ...) LIKEPRINTF(2); void Con_Clear_f (void); diff --git a/engine/common/fs.c b/engine/common/fs.c index c9907b3f6..6423eb540 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -25,12 +25,13 @@ int fs_switchgame = -1; struct { + void *module; const char *extension; searchpathfuncs_t *funcs; qboolean loadscan; } searchpathformats[64]; -int FS_RegisterFileSystemType(const char *extension, searchpathfuncs_t *funcs, qboolean loadscan) +int FS_RegisterFileSystemType(void *module, const char *extension, searchpathfuncs_t *funcs, qboolean loadscan) { unsigned int i; for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) @@ -43,6 +44,7 @@ int FS_RegisterFileSystemType(const char *extension, searchpathfuncs_t *funcs, q if (i == sizeof(searchpathformats)/sizeof(searchpathformats[0])) return 0; + searchpathformats[i].module = module; searchpathformats[i].extension = extension; searchpathformats[i].funcs = funcs; searchpathformats[i].loadscan = loadscan; @@ -57,10 +59,30 @@ void FS_UnRegisterFileSystemType(int idx) return; searchpathformats[idx-1].funcs = NULL; + searchpathformats[idx-1].module = NULL; com_fschanged = true; //FS_Restart will be needed } +void FS_UnRegisterFileSystemModule(void *module) +{ + int i; + qboolean found = false; + for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + { + if (searchpathformats[i].module == module) + { + searchpathformats[i].funcs = NULL; + searchpathformats[i].module = NULL; + found = true; + } + } + + if (found) + { + Cmd_ExecuteString("fs_restart", RESTRICT_LOCAL); + } +} vfsfile_t *FS_OpenVFSLoc(flocation_t *loc, char *mode); @@ -227,7 +249,7 @@ COM_Dir_f ============ */ -static int COM_Dir_List(const char *name, int size, void *parm, void *spath) +static int QDECL COM_Dir_List(const char *name, int size, void *parm, void *spath) { char pbuf[MAX_OSPATH] = "??"; searchpath_t *s; @@ -255,8 +277,8 @@ void COM_Dir_f (void) strncat(match, Cmd_Argv(2), sizeof(match)-1); match[sizeof(match)-1] = '\0'; } - else - strncat(match, "/*", sizeof(match)-1); +// else +// strncat(match, "/*", sizeof(match)-1); COM_EnumerateFiles(match, COM_Dir_List, NULL); } @@ -423,7 +445,7 @@ void FS_FlushFSHashRemoved(void) FS_FlushFSHashReally(); } -void FS_AddFileHash(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) +static void QDECL FS_AddFileHash(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) { fsbucket_t *old; @@ -480,12 +502,12 @@ void FS_RebuildFSHash(void) { //go for the pure paths first. for (search = com_purepaths; search; search = search->nextpure) { - search->funcs->BuildHash(search->handle, depth++); + search->funcs->BuildHash(search->handle, depth++, FS_AddFileHash); } } for (search = com_searchpaths ; search ; search = search->next) { - search->funcs->BuildHash(search->handle, depth++); + search->funcs->BuildHash(search->handle, depth++, FS_AddFileHash); } com_fschanged = false; @@ -849,6 +871,8 @@ static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen Con_Printf("Error: '..' characters in filename %s\n", pattern); else if (strstr(pattern, ":")) //win32 drive seperator (or mac path seperator, but / works there and they're used to it) (or amiga device separator) Con_Printf("Error: absolute path in filename %s\n", pattern); + else if (strlen(pattern) > outlen) + Con_Printf("Error: path %s too long\n", pattern); else { return pattern; @@ -894,6 +918,12 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out else snprintf(out, outlen, "%sqw/skins/%s", com_quakedir, fname); break; + case FS_BINARYPATH: + if (host_parms.binarydir && *host_parms.binarydir) + snprintf(out, outlen, "%s%s", host_parms.binarydir, fname); + else + snprintf(out, outlen, "%s%s", host_parms.basedir, fname); + break; case FS_ROOT: if (*com_homedir) snprintf(out, outlen, "%s%s", com_homedir, fname); @@ -907,7 +937,7 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out snprintf(out, outlen, "%sfte/%s", com_quakedir, fname); break; default: - Sys_Error("FS_Rename case not handled\n"); + Sys_Error("FS_NativePath case not handled\n"); } return true; } @@ -1224,7 +1254,7 @@ void FS_FreeFile(void *file) -void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void *, void *), void *parm) +void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *, int, void *, void *), void *parm) { searchpath_t *search; for (search = com_searchpaths; search ; search = search->next) @@ -1348,7 +1378,7 @@ typedef struct { const char *puredesc; } wildpaks_t; -static int FS_AddWildDataFiles (const char *descriptor, int size, void *vparam, struct searchpath_s *path) +static int QDECL FS_AddWildDataFiles (const char *descriptor, int size, void *vparam, struct searchpath_s *path) { wildpaks_t *param = vparam; vfsfile_t *vfs; @@ -1794,7 +1824,7 @@ void COM_Gamedir (const char *dir) /*some modern non-compat settings*/ #define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n" /*set some stuff so our regular qw client appears more like hexen2*/ -#define HEX2CFG "set com_parseutf8 -1\nset gl_font gfx/hexen2\nset in_builtinkeymap 0\nset_calc cl_playerclass int (random * 5) + 1\nset r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n" +#define HEX2CFG "set com_parseutf8 -1\nset gl_font gfx/hexen2\nset in_builtinkeymap 0\nset_calc cl_playerclass int (random * 5) + 1\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n" /*yay q2!*/ #define Q2CFG "gl_font \":?col=0.44 1 0.2\"\n" /*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/ @@ -1831,6 +1861,9 @@ const gamemode_info_t gamemode_info[] = { {"-spark", "spark", "Spark", {"base/src/progs.src", "base/qwprogs.dat", "base/pak0.pak"}, DMFCFG, {"base", }, "Spark"}, + {"-scouts", "scouts", "FTE-SJ", {"basesj/src/progs.src", + "basesj/progs.dat", + "basesj/pak0.pak"}, NULL, {"basesj", }, "Scouts Journey"}, {"-rmq", "rmq", "RMQ", {NULL}, RMQCFG, {"id1", "qw", "rmq", "fte"}, "Remake Quake"}, //supported commercial mods (some are currently only partially supported) @@ -2761,7 +2794,8 @@ void COM_InitFilesystem (void) //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].argname; i++) { - ev = strstr(com_argv[0], gamemode_info[i].exename); + ev = COM_SkipPath(com_argv[0]); + ev = strstr(ev, gamemode_info[i].exename); if (ev && (!strchr(ev, '\\') && !strchr(ev, '/'))) gamenum = i; } @@ -2970,6 +3004,9 @@ void COM_InitFilesystem (void) if (*com_homedir) Con_Printf("Using home directory \"%s\"\n", com_homedir); +#ifdef PLUGINS + Plug_Initialise(false); +#endif FS_StartupWithGame(gamenum); } @@ -2984,18 +3021,18 @@ extern searchpathfuncs_t zipfilefuncs; extern searchpathfuncs_t doomwadfilefuncs; void FS_RegisterDefaultFileSystems(void) { - FS_RegisterFileSystemType("pak", &packfilefuncs, true); + FS_RegisterFileSystemType(NULL, "pak", &packfilefuncs, true); #if !defined(_WIN32) && !defined(ANDROID) /*for systems that have case sensitive paths, also include *.PAK */ - FS_RegisterFileSystemType("PAK", &packfilefuncs, true); + FS_RegisterFileSystemType(NULL, "PAK", &packfilefuncs, true); #endif #ifdef AVAIL_ZLIB - FS_RegisterFileSystemType("pk3", &zipfilefuncs, true); - FS_RegisterFileSystemType("pk4", &zipfilefuncs, true); - FS_RegisterFileSystemType("apk", &zipfilefuncs, false); - FS_RegisterFileSystemType("zip", &zipfilefuncs, false); + FS_RegisterFileSystemType(NULL, "pk3", &zipfilefuncs, true); + FS_RegisterFileSystemType(NULL, "pk4", &zipfilefuncs, true); + FS_RegisterFileSystemType(NULL, "apk", &zipfilefuncs, false); + FS_RegisterFileSystemType(NULL, "zip", &zipfilefuncs, false); #endif #ifdef DOOMWADS - FS_RegisterFileSystemType("wad", &doomwadfilefuncs, true); + FS_RegisterFileSystemType(NULL, "wad", &doomwadfilefuncs, true); #endif } diff --git a/engine/common/fs.h b/engine/common/fs.h index 1cfe22425..fd51884e0 100644 --- a/engine/common/fs.h +++ b/engine/common/fs.h @@ -10,31 +10,30 @@ extern int fs_hash_files; //for tracking efficiency. no functional use. struct searchpath_s; typedef struct { - void (*GetDisplayPath)(void *handle, char *outpath, unsigned int pathsize); - void (*ClosePath)(void *handle); - void (*BuildHash)(void *handle, int depth); - qboolean (*FindFile)(void *handle, flocation_t *loc, const char *name, void *hashedresult); //true if found (hashedresult can be NULL) + void (QDECL *GetDisplayPath)(void *handle, char *outpath, unsigned int pathsize); + void (QDECL *ClosePath)(void *handle); + void (QDECL *BuildHash)(void *handle, int depth, void (QDECL *FS_AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)); + qboolean (QDECL *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 *fname, int fsize, void *parm, void *spath), void *parm); + void (QDECL *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 (QDECL *EnumerateFiles)(void *handle, const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm); - void *(*OpenNew)(vfsfile_t *file, const char *desc); //returns a handle to a new pak/path + void *(QDECL *OpenNew)(vfsfile_t *file, const char *desc); //returns a handle to a new pak/path - int (*GeneratePureCRC) (void *handle, int seed, int usepure); + int (QDECL *GeneratePureCRC) (void *handle, int seed, int usepure); - vfsfile_t *(*OpenVFS)(void *handle, flocation_t *loc, const char *mode); + vfsfile_t *(QDECL *OpenVFS)(void *handle, flocation_t *loc, const char *mode); - qboolean (*PollChanges)(void *handle); //returns true if there were changes + qboolean (QDECL *PollChanges)(void *handle); //returns true if there were changes } 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); +vfsfile_t *QDECL VFSOS_Open(const char *osname, const char *mode); vfsfile_t *FS_DecompressGZip(vfsfile_t *infile); -void FS_AddFileHash(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle); //called inside the BuildHash function - -int FS_RegisterFileSystemType(const char *extension, searchpathfuncs_t *funcs, qboolean loadscan); +int FS_RegisterFileSystemType(void *module, const char *extension, searchpathfuncs_t *funcs, qboolean loadscan); void FS_UnRegisterFileSystemType(int idx); +void FS_UnRegisterFileSystemModule(void *module); diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c index 8a6a30a0f..70572d5b5 100644 --- a/engine/common/fs_pak.c +++ b/engine/common/fs_pak.c @@ -54,7 +54,7 @@ typedef struct #define MAX_FILES_IN_PACK 2048 -void FSPAK_GetDisplayPath(void *handle, char *out, unsigned int outlen) +void QDECL FSPAK_GetDisplayPath(void *handle, char *out, unsigned int outlen) { pack_t *pak = handle; @@ -63,7 +63,7 @@ void FSPAK_GetDisplayPath(void *handle, char *out, unsigned int outlen) else Q_snprintfz(out, outlen, "%s", pak->descname); } -void FSPAK_ClosePath(void *handle) +void QDECL FSPAK_ClosePath(void *handle) { pack_t *pak = handle; @@ -77,17 +77,17 @@ void FSPAK_ClosePath(void *handle) Z_Free(pak->files); Z_Free(pak); } -void FSPAK_BuildHash(void *handle, int depth) +void QDECL FSPAK_BuildHash(void *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)) { pack_t *pak = handle; int i; for (i = 0; i < pak->numfiles; i++) { - FS_AddFileHash(depth, pak->files[i].name, &pak->files[i].bucket, &pak->files[i]); + AddFileHash(depth, pak->files[i].name, &pak->files[i].bucket, &pak->files[i]); } } -qboolean FSPAK_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +qboolean QDECL FSPAK_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { mpackfile_t *pf = hashedresult; int i, len; @@ -126,7 +126,7 @@ qboolean FSPAK_FLocate(void *handle, flocation_t *loc, const char *filename, voi } return false; } -int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm) +int QDECL FSPAK_EnumerateFiles (void *handle, const char *match, int (QDECL *func)(const char *, int, void *, void *spath), void *parm) { pack_t *pak = handle; int num; @@ -143,7 +143,7 @@ int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const cha return true; } -int FSPAK_GeneratePureCRC(void *handle, int seed, int crctype) +int QDECL FSPAK_GeneratePureCRC(void *handle, int seed, int crctype) { pack_t *pak = handle; @@ -182,7 +182,7 @@ 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) +void *QDECL FSPAK_LoadPackFile (vfsfile_t *file, const char *desc) { dpackheader_t header; int i; @@ -269,7 +269,7 @@ typedef struct { unsigned long length; unsigned long currentpos; } vfspack_t; -int VFSPAK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread) +int QDECL VFSPAK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread) { vfspack_t *vfsp = (vfspack_t*)vfs; int read; @@ -292,12 +292,12 @@ int VFSPAK_ReadBytes (struct vfsfile_s *vfs, void *buffer, int bytestoread) return read; } -int VFSPAK_WriteBytes (struct vfsfile_s *vfs, const void *buffer, int bytestoread) +int QDECL 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) +qboolean QDECL VFSPAK_Seek (struct vfsfile_s *vfs, unsigned long pos) { vfspack_t *vfsp = (vfspack_t*)vfs; if (pos < 0 || pos > vfsp->length) @@ -306,23 +306,23 @@ qboolean VFSPAK_Seek (struct vfsfile_s *vfs, unsigned long pos) return true; } -unsigned long VFSPAK_Tell (struct vfsfile_s *vfs) +unsigned long QDECL 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) +unsigned long QDECL VFSPAK_GetLen (struct vfsfile_s *vfs) { vfspack_t *vfsp = (vfspack_t*)vfs; return vfsp->length; } -void VFSPAK_Close(vfsfile_t *vfs) +void QDECL 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) +vfsfile_t *QDECL FSPAK_OpenVFS(void *handle, flocation_t *loc, const char *mode) { pack_t *pack = (pack_t*)handle; vfspack_t *vfs; @@ -352,7 +352,7 @@ vfsfile_t *FSPAK_OpenVFS(void *handle, flocation_t *loc, const char *mode) return (vfsfile_t *)vfs; } -void FSPAK_ReadFile(void *handle, flocation_t *loc, char *buffer) +void QDECL FSPAK_ReadFile(void *handle, flocation_t *loc, char *buffer) { vfsfile_t *f; f = FSPAK_OpenVFS(handle, loc, "rb"); @@ -386,7 +386,7 @@ searchpathfuncs_t packfilefuncs = { #ifdef DOOMWADS -void *FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, const char *desc) +void *QDECL FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, const char *desc) { dwadheader_t header; int i; diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index efb35f653..71343f5f2 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -17,37 +17,38 @@ typedef struct { int depth; char rootpath[1]; + void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle); } stdiopath_t; typedef struct { vfsfile_t funcs; FILE *handle; } vfsstdiofile_t; -static int VFSSTDIO_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +static int QDECL VFSSTDIO_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return fread(buffer, 1, bytestoread, intfile->handle); } -static int VFSSTDIO_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +static int QDECL VFSSTDIO_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return fwrite(buffer, 1, bytestoread, intfile->handle); } -static qboolean VFSSTDIO_Seek (struct vfsfile_s *file, unsigned long pos) +static qboolean QDECL VFSSTDIO_Seek (struct vfsfile_s *file, unsigned long pos) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return fseek(intfile->handle, pos, SEEK_SET) == 0; } -static unsigned long VFSSTDIO_Tell (struct vfsfile_s *file) +static unsigned long QDECL VFSSTDIO_Tell (struct vfsfile_s *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; return ftell(intfile->handle); } -static void VFSSTDIO_Flush(struct vfsfile_s *file) +static void QDECL VFSSTDIO_Flush(struct vfsfile_s *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; fflush(intfile->handle); } -static unsigned long VFSSTDIO_GetSize (struct vfsfile_s *file) +static unsigned long QDECL VFSSTDIO_GetSize (struct vfsfile_s *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; @@ -60,7 +61,7 @@ static unsigned long VFSSTDIO_GetSize (struct vfsfile_s *file) return maxlen; } -static void VFSSTDIO_Close(vfsfile_t *file) +static void QDECL VFSSTDIO_Close(vfsfile_t *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; fclose(intfile->handle); @@ -68,7 +69,7 @@ static void VFSSTDIO_Close(vfsfile_t *file) } #ifdef _WIN32 -static void VFSSTDIO_CloseTemp(vfsfile_t *file) +static void QDECL VFSSTDIO_CloseTemp(vfsfile_t *file) { vfsstdiofile_t *intfile = (vfsstdiofile_t*)file; char *fname = (char*)(intfile+1); @@ -195,7 +196,7 @@ vfsfile_t *VFSOS_Open(const char *osname, const char *mode) #endif #ifndef WEBSVONLY -static vfsfile_t *FSSTDIO_OpenVFS(void *handle, flocation_t *loc, const char *mode) +static vfsfile_t *QDECL FSSTDIO_OpenVFS(void *handle, flocation_t *loc, const char *mode) { vfsfile_t *f; stdiopath_t *sp = handle; @@ -207,26 +208,26 @@ static vfsfile_t *FSSTDIO_OpenVFS(void *handle, flocation_t *loc, const char *mo snprintf(diskname, sizeof(diskname), "%s/%s", sp->rootpath, loc->rawname); f = VFSSTDIO_Open(diskname, mode, &needsflush); - if (needsflush) - FS_AddFileHash(sp->depth, loc->rawname, NULL, sp); + if (needsflush && sp->AddFileHash) + sp->AddFileHash(sp->depth, loc->rawname, NULL, sp); return f; } -static void FSSTDIO_GetDisplayPath(void *handle, char *out, unsigned int outlen) +static void QDECL FSSTDIO_GetDisplayPath(void *handle, char *out, unsigned int outlen) { stdiopath_t *np = handle; Q_strncpyz(out, np->rootpath, outlen); } -static void FSSTDIO_ClosePath(void *handle) +static void QDECL FSSTDIO_ClosePath(void *handle) { Z_Free(handle); } -static qboolean FSSTDIO_PollChanges(void *handle) +static qboolean QDECL FSSTDIO_PollChanges(void *handle) { // stdiopath_t *np = handle; return true; //can't verify that or not, so we have to assume the worst } -static void *FSSTDIO_OpenPath(vfsfile_t *mustbenull, const char *desc) +static void *QDECL FSSTDIO_OpenPath(vfsfile_t *mustbenull, const char *desc) { stdiopath_t *np; int dlen = strlen(desc); @@ -240,9 +241,10 @@ static void *FSSTDIO_OpenPath(vfsfile_t *mustbenull, const char *desc) } return np; } -static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data, void *spath) +static int QDECL FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data, void *spath) { - stdiopath_t *sp = data; + stdiopath_t *sp = spath; + void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) = data; if (filename[strlen(filename)-1] == '/') { //this is actually a directory @@ -251,16 +253,17 @@ static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data, Sys_EnumerateFiles(sp->rootpath, childpath, FSSTDIO_RebuildFSHash, data, spath); return true; } - FS_AddFileHash(sp->depth, filename, NULL, sp); + AddFileHash(sp->depth, filename, NULL, sp); return true; } -static void FSSTDIO_BuildHash(void *handle, int depth) +static void QDECL FSSTDIO_BuildHash(void *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)) { stdiopath_t *sp = handle; sp->depth = depth; - Sys_EnumerateFiles(sp->rootpath, "*", FSSTDIO_RebuildFSHash, handle, handle); + sp->AddFileHash = AddFileHash; + Sys_EnumerateFiles(sp->rootpath, "*", FSSTDIO_RebuildFSHash, AddFileHash, handle); } -static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +static qboolean QDECL FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { stdiopath_t *sp = handle; int len; @@ -310,7 +313,7 @@ static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *file return true; } -static void FSSTDIO_ReadFile(void *handle, flocation_t *loc, char *buffer) +static void QDECL FSSTDIO_ReadFile(void *handle, flocation_t *loc, char *buffer) { FILE *f; size_t result; @@ -326,7 +329,7 @@ static void FSSTDIO_ReadFile(void *handle, flocation_t *loc, char *buffer) fclose(f); } -static int FSSTDIO_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm) +static int QDECL FSSTDIO_EnumerateFiles (void *handle, const char *match, int (QDECL *func)(const char *, int, void *, void *spath), void *parm) { stdiopath_t *sp = handle; return Sys_EnumerateFiles(sp->rootpath, match, func, parm, handle); diff --git a/engine/common/fs_win32.c b/engine/common/fs_win32.c index e64db408e..9dea732a9 100644 --- a/engine/common/fs_win32.c +++ b/engine/common/fs_win32.c @@ -26,7 +26,7 @@ typedef struct { unsigned int length; unsigned int offset; } vfsw32file_t; -static int VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +static int QDECL VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { DWORD read; vfsw32file_t *intfile = (vfsw32file_t*)file; @@ -43,7 +43,7 @@ static int VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestore return 0; return read; } -static int VFSW32_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +static int QDECL VFSW32_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) { DWORD written; vfsw32file_t *intfile = (vfsw32file_t*)file; @@ -61,7 +61,7 @@ static int VFSW32_WriteBytes (struct vfsfile_s *file, const void *buffer, int by return 0; return written; } -static qboolean VFSW32_Seek (struct vfsfile_s *file, unsigned long pos) +static qboolean QDECL VFSW32_Seek (struct vfsfile_s *file, unsigned long pos) { unsigned long upper, lower; vfsw32file_t *intfile = (vfsw32file_t*)file; @@ -76,21 +76,21 @@ static qboolean VFSW32_Seek (struct vfsfile_s *file, unsigned long pos) return SetFilePointer(intfile->hand, lower, &upper, FILE_BEGIN) != INVALID_SET_FILE_POINTER; } -static unsigned long VFSW32_Tell (struct vfsfile_s *file) +static unsigned long QDECL VFSW32_Tell (struct vfsfile_s *file) { vfsw32file_t *intfile = (vfsw32file_t*)file; if (intfile->mmap) return intfile->offset; return SetFilePointer(intfile->hand, 0, NULL, FILE_CURRENT); } -static void VFSW32_Flush(struct vfsfile_s *file) +static void QDECL VFSW32_Flush(struct vfsfile_s *file) { vfsw32file_t *intfile = (vfsw32file_t*)file; if (intfile->mmap) FlushViewOfFile(intfile->mmap, intfile->length); FlushFileBuffers(intfile->hand); } -static unsigned long VFSW32_GetSize (struct vfsfile_s *file) +static unsigned long QDECL VFSW32_GetSize (struct vfsfile_s *file) { vfsw32file_t *intfile = (vfsw32file_t*)file; @@ -98,7 +98,7 @@ static unsigned long VFSW32_GetSize (struct vfsfile_s *file) return intfile->length; return GetFileSize(intfile->hand, NULL); } -static void VFSW32_Close(vfsfile_t *file) +static void QDECL VFSW32_Close(vfsfile_t *file) { vfsw32file_t *intfile = (vfsw32file_t*)file; if (intfile->mmap) @@ -112,7 +112,7 @@ static void VFSW32_Close(vfsfile_t *file) COM_FlushFSCache(); } -vfsfile_t *VFSW32_Open(const char *osname, const char *mode) +vfsfile_t *QDECL VFSW32_Open(const char *osname, const char *mode) { HANDLE h, mh; unsigned int fsize; @@ -185,26 +185,26 @@ vfsfile_t *VFSW32_Open(const char *osname, const char *mode) return (vfsfile_t*)file; } -static vfsfile_t *VFSW32_OpenVFS(void *handle, flocation_t *loc, const char *mode) +static vfsfile_t *QDECL VFSW32_OpenVFS(void *handle, flocation_t *loc, const char *mode) { //path is already cleaned, as anything that gets a valid loc needs cleaning up first. return VFSW32_Open(loc->rawname, mode); } -static void VFSW32_GetDisplayPath(void *handle, char *out, unsigned int outlen) +static void QDECL VFSW32_GetDisplayPath(void *handle, char *out, unsigned int outlen) { vfsw32path_t *wp = handle; Q_strncpyz(out, wp->rootpath, outlen); } -static void VFSW32_ClosePath(void *handle) +static void QDECL VFSW32_ClosePath(void *handle) { vfsw32path_t *wp = handle; if (wp->changenotification != INVALID_HANDLE_VALUE) FindCloseChangeNotification(wp->changenotification); Z_Free(wp); } -static qboolean VFSW32_PollChanges(void *handle) +static qboolean QDECL VFSW32_PollChanges(void *handle) { qboolean result = false; vfsw32path_t *wp = handle; @@ -229,7 +229,7 @@ static qboolean VFSW32_PollChanges(void *handle) } return result; } -static void *VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc) +static void *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc) { vfsw32path_t *np; int dlen = strlen(desc); @@ -244,28 +244,29 @@ static void *VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc) } return np; } -static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle, void *spath) +static int QDECL VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle, void *spath) { - vfsw32path_t *wp = handle; + vfsw32path_t *wp = spath; + void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) = handle; if (filename[strlen(filename)-1] == '/') { //this is actually a directory char childpath[256]; Q_snprintfz(childpath, sizeof(childpath), "%s*", filename); - Sys_EnumerateFiles(wp->rootpath, childpath, VFSW32_RebuildFSHash, wp, handle); + Sys_EnumerateFiles(wp->rootpath, childpath, VFSW32_RebuildFSHash, handle, spath); return true; } - FS_AddFileHash(wp->hashdepth, filename, NULL, wp); + AddFileHash(wp->hashdepth, filename, NULL, wp); return true; } -static void VFSW32_BuildHash(void *handle, int hashdepth) +static void QDECL VFSW32_BuildHash(void *handle, int hashdepth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)) { vfsw32path_t *wp = handle; wp->hashdepth = hashdepth; - Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, handle, handle); + Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, AddFileHash, handle); } -static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +static qboolean QDECL VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { vfsw32path_t *wp = handle; FILE *f; @@ -304,7 +305,7 @@ static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filen return true; } -static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) +static void QDECL VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) { // vfsw32path_t *wp = handle; @@ -316,7 +317,7 @@ static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) fread(buffer, 1, loc->len, f); fclose(f); } -static int VFSW32_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm) +static int QDECL VFSW32_EnumerateFiles (void *handle, const char *match, int (QDECL *func)(const char *, int, void *, void *spath), void *parm) { vfsw32path_t *wp = handle; return Sys_EnumerateFiles(wp->rootpath, match, func, parm, handle); diff --git a/engine/common/fs_zip.c b/engine/common/fs_zip.c index 1481bf797..90179ac24 100644 --- a/engine/common/fs_zip.c +++ b/engine/common/fs_zip.c @@ -239,7 +239,7 @@ typedef struct zipfile_s } zipfile_t; -static void FSZIP_GetDisplayPath(void *handle, char *out, unsigned int outlen) +static void QDECL FSZIP_GetDisplayPath(void *handle, char *out, unsigned int outlen) { zipfile_t *zip = handle; @@ -248,7 +248,7 @@ static void FSZIP_GetDisplayPath(void *handle, char *out, unsigned int outlen) else Q_strncpyz(out, zip->filename, outlen); } -static void FSZIP_ClosePath(void *handle) +static void QDECL FSZIP_ClosePath(void *handle) { zipfile_t *zip = handle; @@ -260,17 +260,17 @@ static void FSZIP_ClosePath(void *handle) Z_Free(zip->files); Z_Free(zip); } -static void FSZIP_BuildHash(void *handle, int depth) +static void QDECL FSZIP_BuildHash(void *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle)) { zipfile_t *zip = handle; int i; for (i = 0; i < zip->numfiles; i++) { - FS_AddFileHash(depth, zip->files[i].name, &zip->files[i].bucket, &zip->files[i]); + AddFileHash(depth, zip->files[i].name, &zip->files[i].bucket, &zip->files[i]); } } -static qboolean FSZIP_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) +static qboolean QDECL FSZIP_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { zpackfile_t *pf = hashedresult; int i, len; @@ -318,7 +318,7 @@ static qboolean FSZIP_FLocate(void *handle, flocation_t *loc, const char *filena return false; } -static void FSZIP_ReadFile(void *handle, flocation_t *loc, char *buffer) +static void QDECL FSZIP_ReadFile(void *handle, flocation_t *loc, char *buffer) { zipfile_t *zip = handle; int err; @@ -337,7 +337,7 @@ static void FSZIP_ReadFile(void *handle, flocation_t *loc, char *buffer) return; } -static int FSZIP_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *, void *spath), void *parm) +static int QDECL FSZIP_EnumerateFiles (void *handle, const char *match, int (QDECL *func)(const char *, int, void *, void *spath), void *parm) { zipfile_t *zip = handle; int num; @@ -364,7 +364,7 @@ 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) +static void *QDECL FSZIP_LoadZipFile (vfsfile_t *packhandle, const char *desc) { int i; int nextfileziphandle; @@ -415,7 +415,7 @@ static void *FSZIP_LoadZipFile (vfsfile_t *packhandle, const char *desc) return zip; } -int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) +int QDECL FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) { zipfile_t *zip = handle; unz_file_info file_info; @@ -502,7 +502,7 @@ qboolean VFSZIP_MakeActive(vfszip_t *vfsz) return true; } -int VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +int QDECL VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { int read; vfszip_t *vfsz = (vfszip_t*)file; @@ -532,12 +532,12 @@ int VFSZIP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) vfsz->pos += read; return read; } -int VFSZIP_WriteBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +int QDECL 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) +qboolean QDECL VFSZIP_Seek (struct vfsfile_s *file, unsigned long pos) { vfszip_t *vfsz = (vfszip_t*)file; @@ -608,7 +608,7 @@ qboolean VFSZIP_Seek (struct vfsfile_s *file, unsigned long pos) return true; } -unsigned long VFSZIP_Tell (struct vfsfile_s *file) +unsigned long QDECL VFSZIP_Tell (struct vfsfile_s *file) { vfszip_t *vfsz = (vfszip_t*)file; @@ -617,12 +617,12 @@ unsigned long VFSZIP_Tell (struct vfsfile_s *file) return vfsz->pos; } -unsigned long VFSZIP_GetLen (struct vfsfile_s *file) +unsigned long QDECL VFSZIP_GetLen (struct vfsfile_s *file) { vfszip_t *vfsz = (vfszip_t*)file; return vfsz->length; } -void VFSZIP_Close (struct vfsfile_s *file) +void QDECL VFSZIP_Close (struct vfsfile_s *file) { vfszip_t *vfsz = (vfszip_t*)file; @@ -636,7 +636,7 @@ void VFSZIP_Close (struct vfsfile_s *file) Z_Free(vfsz); } -vfsfile_t *FSZIP_OpenVFS(void *handle, flocation_t *loc, const char *mode) +vfsfile_t *QDECL FSZIP_OpenVFS(void *handle, flocation_t *loc, const char *mode) { int rawofs; zipfile_t *zip = handle; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 66e55c024..ea7f062a5 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -3886,11 +3886,13 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c { noerrors = noerrors && CModRBSP_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); buildmeshes = CModRBSP_BuildSurfMesh; + loadmodel->lightmaps.surfstyles = 4; } else { noerrors = noerrors && CModQ3_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); buildmeshes = CModQ3_BuildSurfMesh; + loadmodel->lightmaps.surfstyles = 1; } noerrors = noerrors && CModQ3_LoadMarksurfaces (&header.lumps[Q3LUMP_LEAFSURFACES]); //fixme: duplicated loading. diff --git a/engine/common/log.c b/engine/common/log.c index 88a24f33d..d60511517 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -280,7 +280,7 @@ void SV_LogPlayer(client_t *cl, char *msg) snprintf(line, sizeof(line), "%s\\%s\\%i\\%s\\%s\\%i%s\n", msg, cl->name, cl->userid, - NET_BaseAdrToString(remote_adr, sizeof(remote_adr), cl->netchan.remote_address), (cl->realip_status > 0 ? NET_BaseAdrToString(realip_adr, sizeof(realip_adr), cl->realip) : "??"), + NET_BaseAdrToString(remote_adr, sizeof(remote_adr), &cl->netchan.remote_address), (cl->realip_status > 0 ? NET_BaseAdrToString(realip_adr, sizeof(realip_adr), &cl->realip) : "??"), cl->netchan.remote_address.port, cl->userinfo); Log_String(LOG_PLAYER, line); diff --git a/engine/common/net.h b/engine/common/net.h index db61bd0b9..acb131eda 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -43,6 +43,7 @@ typedef struct qbyte ipx[10]; #ifdef IRCCONNECT struct { + char host[32]; char user[32]; char channel[12]; } irc; @@ -78,7 +79,7 @@ extern qbyte net_message_buffer[MAX_OVERALLMSGLEN]; extern cvar_t hostname; -int TCP_OpenStream (netadr_t remoteaddr); //makes things easier +int TCP_OpenStream (netadr_t *remoteaddr); //makes things easier struct ftenet_connections_s; void NET_Init (void); @@ -90,27 +91,27 @@ void NET_CloseServer (void); void UDP_CloseSocket (int socket); void NET_Shutdown (void); int NET_GetPacket (netsrc_t netsrc, int firstsock); -void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to); +void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t *to); int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx); void NET_PrintAddresses(struct ftenet_connections_s *collection); -qboolean NET_AddressSmellsFunny(netadr_t a); +qboolean NET_AddressSmellsFunny(netadr_t *a); qboolean NET_EnsureRoute(struct ftenet_connections_s *collection, char *routename, char *host, qboolean islisten); -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_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 (const char *s, int defaultport, struct sockaddr_qstorage *sadr, int *addrfamily, int *addrsize); qboolean NET_StringToAdr (const char *s, int defaultport, netadr_t *a); qboolean NET_PortToAdr (int adrfamily, const char *s, netadr_t *a); qboolean NET_IsClientLegal(netadr_t *adr); -qboolean NET_IsLoopBackAddress (netadr_t adr); +qboolean NET_IsLoopBackAddress (netadr_t *adr); 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); +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); +qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask); qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *name, const char *address, netadrtype_t addrtype, qboolean islisten); @@ -192,11 +193,11 @@ extern int net_drop; // packets dropped before this one void Netchan_Init (void); int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate); -void Netchan_OutOfBand (netsrc_t sock, netadr_t adr, int length, qbyte *data); -void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t adr, char *format, ...) LIKEPRINTF(3); -void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t adr, int language, translation_t text, ...); +void Netchan_OutOfBand (netsrc_t sock, netadr_t *adr, int length, qbyte *data); +void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t *adr, char *format, ...) LIKEPRINTF(3); +void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t *adr, int language, translation_t text, ...); qboolean Netchan_Process (netchan_t *chan); -void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport); +void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t *adr, int qport); unsigned int Net_PextMask(int maskset, qboolean fornq); extern cvar_t net_mtu; diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 311d7969a..9aece7ebf 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -246,12 +246,13 @@ Netchan_OutOfBand Sends an out-of-band datagram ================ */ -void Netchan_OutOfBand (netsrc_t sock, netadr_t adr, int length, qbyte *data) +void Netchan_OutOfBand (netsrc_t sock, netadr_t *adr, int length, qbyte *data) { sizebuf_t send; qbyte send_buf[MAX_QWMSGLEN + PACKET_HEADER]; // write the packet header + memset(&send, 0, sizeof(send)); send.data = send_buf; send.maxsize = sizeof(send_buf); send.cursize = 0; @@ -274,7 +275,7 @@ Netchan_OutOfBandPrint Sends a text message in an out-of-band datagram ================ */ -void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t adr, char *format, ...) +void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t *adr, char *format, ...) { va_list argptr; static char string[8192]; // ??? why static? @@ -287,7 +288,7 @@ void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t adr, char *format, .. Netchan_OutOfBand (sock, adr, strlen(string), (qbyte *)string); } #ifndef CLIENTONLY -void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t adr, int language, translation_t text, ...) +void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t *adr, int language, translation_t text, ...) { va_list argptr; static char string[8192]; // ??? why static? @@ -311,12 +312,12 @@ Netchan_Setup called to open a channel to a remote system ============== */ -void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport) +void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t *adr, int qport) { memset (chan, 0, sizeof(*chan)); chan->sock = sock; - chan->remote_address = adr; + chan->remote_address = *adr; chan->last_received = realtime; #ifdef NQPROT chan->nqreliable_allowed = true; @@ -468,7 +469,7 @@ nqprot_t NQNetChan_Process(netchan_t *chan) //always reply. a stale sequence probably means our ack got lost. runt[0] = BigLong(NETFLAG_ACK | 8); runt[1] = BigLong(sequence); - NET_SendPacket (chan->sock, 8, runt, net_from); + NET_SendPacket (chan->sock, 8, runt, &net_from); if (showpackets.value) Con_Printf ("out %s a=%i %i\n" , chan->sock == NS_SERVER?"s2c":"c2s" @@ -578,7 +579,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) } else *(int*)send_buf = BigLong(NETFLAG_DATA | send.cursize); - NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); + NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address); chan->bytesout += send.cursize; sentsize += send.cursize; @@ -605,7 +606,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) SZ_Write (&send, data, length); *(int*)send_buf = BigLong(NETFLAG_UNRELIABLE | send.cursize); - NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); + NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address); sentsize += send.cursize; if (showpackets.value) @@ -626,7 +627,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) { chan->fatal_error = true; Con_TPrintf (TL_OUTMESSAGEOVERFLOW - , NET_AdrToString (remote_adr, sizeof(remote_adr), chan->remote_address)); + , NET_AdrToString (remote_adr, sizeof(remote_adr), &chan->remote_address)); return 0; } @@ -707,7 +708,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) int hsz = 10 + ((chan->sock == NS_CLIENT)?2:0); /*header size, if fragmentation is in use*/ if (!chan->fragmentsize || send.cursize < chan->fragmentsize - hsz) - NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); + NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address); else { int offset = chan->fragmentsize - hsz, no; @@ -715,7 +716,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) /*switch on the 'more flags' bit, and send the first part*/ send.data[hsz - 2] |= 0x1; offset &= ~7; - NET_SendPacket (chan->sock, offset + hsz, send.data, chan->remote_address); + NET_SendPacket (chan->sock, offset + hsz, send.data, &chan->remote_address); /*send the additional parts, adding new headers within the previous packet*/ while(offset < send.cursize-hsz) @@ -740,7 +741,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) #endif *(short*)&send.data[offset + hsz-2] = LittleShort((offset>>2) | (more?1:0)); - NET_SendPacket (chan->sock, (no - offset) + hsz, send.data + offset, chan->remote_address); + NET_SendPacket (chan->sock, (no - offset) + hsz, send.data + offset, &chan->remote_address); offset = no; } } @@ -786,7 +787,7 @@ qboolean Netchan_Process (netchan_t *chan) #ifndef SERVERONLY !cls.demoplayback && #endif - !NET_CompareAdr (net_from, chan->remote_address)) + !NET_CompareAdr (&net_from, &chan->remote_address)) return false; chan->bytesin += net_message.cursize; @@ -859,7 +860,7 @@ qboolean Netchan_Process (netchan_t *chan) { if (showdrop.value) Con_TPrintf (TL_OUTOFORDERPACKET - , NET_AdrToString (adr, sizeof(adr), chan->remote_address) + , NET_AdrToString (adr, sizeof(adr), &chan->remote_address) , sequence , chan->incoming_sequence); return false; @@ -937,7 +938,7 @@ qboolean Netchan_Process (netchan_t *chan) if (showdrop.value) Con_TPrintf (TL_DROPPEDPACKETCOUNT - , NET_AdrToString (adr, sizeof(adr), chan->remote_address) + , NET_AdrToString (adr, sizeof(adr), &chan->remote_address) , sequence-(chan->incoming_sequence+1) , sequence); } diff --git a/engine/common/net_ssl_winsspi.c b/engine/common/net_ssl_winsspi.c index 9795610b6..19d175cea 100644 --- a/engine/common/net_ssl_winsspi.c +++ b/engine/common/net_ssl_winsspi.c @@ -501,7 +501,7 @@ static void SSPI_Handshake (sslfile_t *f) } } -static int SSPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +static int QDECL SSPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { sslfile_t *f = (sslfile_t *)file; int err = SSPI_CheckNewInCrypt(f); @@ -530,7 +530,7 @@ static int SSPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread } return bytestoread; } -static int SSPI_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite) +static int QDECL SSPI_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite) { sslfile_t *f = (sslfile_t *)file; @@ -548,21 +548,21 @@ static int SSPI_WriteBytes (struct vfsfile_s *file, const void *buffer, int byte return bytestowrite; } -static qboolean SSPI_Seek (struct vfsfile_s *file, unsigned long pos) +static qboolean QDECL SSPI_Seek (struct vfsfile_s *file, unsigned long pos) { SSPI_Error((sslfile_t*)file, "unable to seek on streams"); return false; } -static unsigned long SSPI_Tell (struct vfsfile_s *file) +static unsigned long QDECL SSPI_Tell (struct vfsfile_s *file) { SSPI_Error((sslfile_t*)file, "unable to seek on streams"); return 0; } -static unsigned long SSPI_GetLen (struct vfsfile_s *file) +static unsigned long QDECL SSPI_GetLen (struct vfsfile_s *file) { return 0; } -static void SSPI_Close (struct vfsfile_s *file) +static void QDECL SSPI_Close (struct vfsfile_s *file) { SSPI_Error((sslfile_t*)file, ""); Z_Free(file); diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 7b63d7ef8..33c71f68a 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -90,7 +90,7 @@ typedef struct ftenet_generic_connection_s { int (*GetLocalAddress)(struct ftenet_generic_connection_s *con, netadr_t *local, int adridx); 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); + qboolean (*SendPacket)(struct ftenet_generic_connection_s *con, int length, void *data, netadr_t *to); void (*Close)(struct ftenet_generic_connection_s *con); #ifdef HAVE_PACKET int (*SetReceiveFDSet) (struct ftenet_generic_connection_s *con, fd_set *fdset); /*set for connections which have multiple sockets (ie: listening tcp connections)*/ @@ -237,39 +237,39 @@ void SockadrToNetadr (struct sockaddr_qstorage *s, netadr_t *a) } } -qboolean NET_CompareAdr (netadr_t a, netadr_t b) +qboolean NET_CompareAdr (netadr_t *a, netadr_t *b) { - if (a.type != b.type) + if (a->type != b->type) { int i; - if (a.type == NA_IP && b.type == NA_IPV6) + if (a->type == NA_IP && b->type == NA_IPV6) { for (i = 0; i < 10; i++) - if (b.address.ip6[i] != 0) + if (b->address.ip6[i] != 0) return false; //only matches if they're 0s, otherwise its not an ipv4 address there for (; i < 12; i++) - if (b.address.ip6[i] != 0xff && b.address.ip6[i] != 0x00) //0x00 is depricated + if (b->address.ip6[i] != 0xff && b->address.ip6[i] != 0x00) //0x00 is depricated return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there for (i = 0; i < 4; i++) { - if (a.address.ip[i] != b.address.ip6[12+i]) + if (a->address.ip[i] != b->address.ip6[12+i]) return false; //mask doesn't match } return true; //its an ipv4 address in there, the mask matched the whole way through } - if (a.type == NA_IPV6 && b.type == NA_IP) + if (a->type == NA_IPV6 && b->type == NA_IP) { for (i = 0; i < 10; i++) - if (a.address.ip6[i] != 0) + if (a->address.ip6[i] != 0) return false; //only matches if they're 0s, otherwise its not an ipv4 address there for (; i < 12; i++) - if (a.address.ip6[i] != 0xff && a.address.ip6[i] != 0x00) //0x00 is depricated + if (a->address.ip6[i] != 0xff && a->address.ip6[i] != 0x00) //0x00 is depricated return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there for (i = 0; i < 4; i++) { - if (a.address.ip6[12+i] != b.address.ip[i]) + if (a->address.ip6[12+i] != b->address.ip[i]) return false; //mask doesn't match } return true; //its an ipv4 address in there, the mask matched the whole way through @@ -277,7 +277,7 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b) return false; } - if (a.type == NA_LOOPBACK) + if (a->type == NA_LOOPBACK) return true; #ifdef HAVE_WEBSOCKCL @@ -290,36 +290,36 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b) #endif #ifdef HAVE_IPV4 - if (a.type == NA_IP || a.type == NA_BROADCAST_IP || a.type == NA_TCP) + if (a->type == NA_IP || a->type == NA_BROADCAST_IP || a->type == NA_TCP) { - if ((memcmp(a.address.ip, b.address.ip, sizeof(a.address.ip)) == 0) && a.port == b.port) + if ((memcmp(a->address.ip, b->address.ip, sizeof(a->address.ip)) == 0) && a->port == b->port) return true; return false; } #endif #ifdef IPPROTO_IPV6 - if (a.type == NA_IPV6 || a.type == NA_BROADCAST_IP6 || a.type == NA_TCPV6) + if (a->type == NA_IPV6 || a->type == NA_BROADCAST_IP6 || a->type == NA_TCPV6) { - if ((memcmp(a.address.ip6, b.address.ip6, sizeof(a.address.ip6)) == 0) && a.port == b.port) + if ((memcmp(a->address.ip6, b->address.ip6, sizeof(a->address.ip6)) == 0) && a->port == b->port) return true; return false; } #endif #ifdef USEIPX - if (a.type == NA_IPX || a.type == NA_BROADCAST_IPX) + if (a->type == NA_IPX || a->type == NA_BROADCAST_IPX) { - if ((memcmp(a.address.ipx, b.address.ipx, sizeof(a.address.ipx)) == 0) && a.port == b.port) + if ((memcmp(a->address.ipx, b->address.ipx, sizeof(a->address.ipx)) == 0) && a->port == b->port) return true; return false; } #endif #ifdef IRCCONNECT - if (a.type == NA_IRC) + if (a->type == NA_IRC) { - if (!strcmp(a.address.irc.user, b.address.irc.user)) + if (!strcmp(a->address.irc.user, b->address.irc.user)) return true; return false; } @@ -336,42 +336,42 @@ NET_CompareBaseAdr Compares without the port =================== */ -qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) +qboolean NET_CompareBaseAdr (netadr_t *a, netadr_t *b) { - if (a.type != b.type) + if (a->type != b->type) return false; - if (a.type == NA_LOOPBACK) + if (a->type == NA_LOOPBACK) return true; #ifdef HAVE_IPV4 - if (a.type == NA_IP || a.type == NA_TCP) + if (a->type == NA_IP || a->type == NA_TCP) { - if ((memcmp(a.address.ip, b.address.ip, sizeof(a.address.ip)) == 0)) + if ((memcmp(a->address.ip, b->address.ip, sizeof(a->address.ip)) == 0)) return true; return false; } #endif #ifdef IPPROTO_IPV6 - if (a.type == NA_IPV6 || a.type == NA_BROADCAST_IP6) + if (a->type == NA_IPV6 || a->type == NA_BROADCAST_IP6) { - if ((memcmp(a.address.ip6, b.address.ip6, 16) == 0)) + if ((memcmp(a->address.ip6, b->address.ip6, 16) == 0)) return true; return false; } #endif #ifdef USEIPX - if (a.type == NA_IPX) + if (a->type == NA_IPX) { - if ((memcmp(a.address.ipx, b.address.ipx, 10) == 0)) + if ((memcmp(a->address.ipx, b->address.ipx, 10) == 0)) return true; return false; } #endif #ifdef IRCCONNECT - if (a.type == NA_IRC) + if (a->type == NA_IRC) { - if (!strcmp(a.address.irc.user, b.address.irc.user)) + if (!strcmp(a->address.irc.user, b->address.irc.user)) return true; return false; } @@ -381,26 +381,26 @@ qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) return false; } -qboolean NET_AddressSmellsFunny(netadr_t a) +qboolean NET_AddressSmellsFunny(netadr_t *a) { #ifdef IPPROTO_IPV6 int i; #endif //rejects certain blacklisted addresses - switch(a.type) + switch(a->type) { #ifdef HAVE_IPV4 case NA_BROADCAST_IP: case NA_IP: //reject localhost - if (a.address.ip[0] == 127)// && a.address.ip[1] == 0 && a.address.ip[2] == 0 && a.address.ip[3] == 1 ) + if (a->address.ip[0] == 127)// && a->address.ip[1] == 0 && a->address.ip[2] == 0 && a->address.ip[3] == 1 ) return true; //'this' network (not an issue, but lets reject it anyway) - if (a.address.ip[0] == 0 && a.address.ip[1] == 0 && a.address.ip[2] == 0 && a.address.ip[3] == 0 ) + if (a->address.ip[0] == 0 && a->address.ip[1] == 0 && a->address.ip[2] == 0 && a->address.ip[3] == 0 ) return true; //reject any broadcasts - if (a.address.ip[0] == 255 && a.address.ip[1] == 255 && a.address.ip[2] == 255 && a.address.ip[3] == 0 ) + if (a->address.ip[0] == 255 && a->address.ip[1] == 255 && a->address.ip[2] == 255 && a->address.ip[3] == 0 ) return true; //not much else I can reject return false; @@ -411,7 +411,7 @@ qboolean NET_AddressSmellsFunny(netadr_t a) case NA_IPV6: //reject [::XXXX] (this includes obsolete ipv4-compatible (not ipv4 mapped), and localhost) for (i = 0; i < 12; i++) - if (a.address.ip6[i]) + if (a->address.ip6[i]) break; if (i == 12) return true; @@ -433,7 +433,7 @@ qboolean NET_AddressSmellsFunny(netadr_t a) } } -char *NET_AdrToString (char *s, int len, netadr_t a) +char *NET_AdrToString (char *s, int len, netadr_t *a) { char *rs = s; char *p; @@ -442,7 +442,7 @@ char *NET_AdrToString (char *s, int len, netadr_t a) qboolean doneblank; #endif - switch(a.type) + switch(a->type) { #ifdef HAVE_WEBSOCKCL case NA_WEBSOCKET: @@ -461,22 +461,22 @@ char *NET_AdrToString (char *s, int len, netadr_t a) #ifdef HAVE_IPV4 case NA_BROADCAST_IP: case NA_IP: - if (a.port) + if (a->port) { snprintf (s, len, "%i.%i.%i.%i:%i", - a.address.ip[0], - a.address.ip[1], - a.address.ip[2], - a.address.ip[3], - ntohs(a.port)); + a->address.ip[0], + a->address.ip[1], + a->address.ip[2], + a->address.ip[3], + ntohs(a->port)); } else { snprintf (s, len, "%i.%i.%i.%i", - a.address.ip[0], - a.address.ip[1], - a.address.ip[2], - a.address.ip[3]); + a->address.ip[0], + a->address.ip[1], + a->address.ip[2], + a->address.ip[3]); } break; #endif @@ -493,24 +493,24 @@ char *NET_AdrToString (char *s, int len, netadr_t a) case NA_BROADCAST_IP6: case NA_IPV6: - if (!*(int*)&a.address.ip6[0] && - !*(int*)&a.address.ip6[4] && - !*(short*)&a.address.ip6[8] && - *(short*)&a.address.ip6[10] == (short)0xffff) + if (!*(int*)&a->address.ip6[0] && + !*(int*)&a->address.ip6[4] && + !*(short*)&a->address.ip6[8] && + *(short*)&a->address.ip6[10] == (short)0xffff) { - if (a.port) + if (a->port) snprintf (s, len, "%i.%i.%i.%i:%i", - a.address.ip6[12], - a.address.ip6[13], - a.address.ip6[14], - a.address.ip6[15], - ntohs(a.port)); + a->address.ip6[12], + a->address.ip6[13], + a->address.ip6[14], + a->address.ip6[15], + ntohs(a->port)); else snprintf (s, len, "%i.%i.%i.%i", - a.address.ip6[12], - a.address.ip6[13], - a.address.ip6[14], - a.address.ip6[15]); + a->address.ip6[12], + a->address.ip6[13], + a->address.ip6[14], + a->address.ip6[15]); break; } *s = 0; @@ -521,7 +521,7 @@ char *NET_AdrToString (char *s, int len, netadr_t a) for (i = 0; i < 16; i+=2) { - if (doneblank!=true && a.address.ip6[i] == 0 && a.address.ip6[i+1] == 0) + if (doneblank!=true && a->address.ip6[i] == 0 && a->address.ip6[i+1] == 0) { if (!doneblank) { @@ -539,40 +539,40 @@ char *NET_AdrToString (char *s, int len, netadr_t a) snprintf (p, len-strlen(s), ":"); p += strlen(p); } - if (a.address.ip6[i+0]) + if (a->address.ip6[i+0]) { snprintf (p, len-strlen(s), "%x%02x", - a.address.ip6[i+0], - a.address.ip6[i+1]); + a->address.ip6[i+0], + a->address.ip6[i+1]); } else { snprintf (p, len-strlen(s), "%x", - a.address.ip6[i+1]); + a->address.ip6[i+1]); } p += strlen(p); } } snprintf (p, len-strlen(s), "]:%i", - ntohs(a.port)); + ntohs(a->port)); break; #endif #ifdef USEIPX case NA_BROADCAST_IPX: case NA_IPX: snprintf (s, len, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", - a.address.ipx[0], - a.address.ipx[1], - a.address.ipx[2], - a.address.ipx[3], - a.address.ipx[4], - a.address.ipx[5], - a.address.ipx[6], - a.address.ipx[7], - a.address.ipx[8], - a.address.ipx[9], - ntohs(a.port)); + a->address.ipx[0], + a->address.ipx[1], + a->address.ipx[2], + a->address.ipx[3], + a->address.ipx[4], + a->address.ipx[5], + a->address.ipx[6], + a->address.ipx[7], + a->address.ipx[8], + a->address.ipx[9], + ntohs(a->port)); break; #endif case NA_LOOPBACK: @@ -581,10 +581,10 @@ char *NET_AdrToString (char *s, int len, netadr_t a) #ifdef IRCCONNECT case NA_IRC: - if (*a.address.irc.channel) - snprintf (s, len, "irc://%s@%s", a.address.irc.user, a.address.irc.channel); + if (*a->address.irc.channel) + snprintf (s, len, "irc://%s@%s", a->address.irc.user, a->address.irc.channel); else - snprintf (s, len, "irc://%s", a.address.irc.user); + snprintf (s, len, "irc://%s", a->address.irc.user); break; #endif @@ -596,41 +596,41 @@ char *NET_AdrToString (char *s, int len, netadr_t a) return rs; } -char *NET_BaseAdrToString (char *s, int len, netadr_t a) +char *NET_BaseAdrToString (char *s, int len, netadr_t *a) { int i, doneblank; char *p; - switch(a.type) + switch(a->type) { case NA_BROADCAST_IP: case NA_IP: snprintf (s, len, "%i.%i.%i.%i", - a.address.ip[0], - a.address.ip[1], - a.address.ip[2], - a.address.ip[3]); + a->address.ip[0], + a->address.ip[1], + a->address.ip[2], + a->address.ip[3]); break; case NA_TCP: snprintf (s, len, "tcp://%i.%i.%i.%i", - a.address.ip[0], - a.address.ip[1], - a.address.ip[2], - a.address.ip[3]); + a->address.ip[0], + a->address.ip[1], + a->address.ip[2], + a->address.ip[3]); break; #ifdef IPPROTO_IPV6 case NA_BROADCAST_IP6: case NA_IPV6: - if (!*(int*)&a.address.ip6[0] && - !*(int*)&a.address.ip6[4] && - !*(short*)&a.address.ip6[8] && - *(short*)&a.address.ip6[10] == (short)0xffff) + if (!*(int*)&a->address.ip6[0] && + !*(int*)&a->address.ip6[4] && + !*(short*)&a->address.ip6[8] && + *(short*)&a->address.ip6[10] == (short)0xffff) { snprintf (s, len, "%i.%i.%i.%i", - a.address.ip6[12], - a.address.ip6[13], - a.address.ip6[14], - a.address.ip6[15]); + a->address.ip6[12], + a->address.ip6[13], + a->address.ip6[14], + a->address.ip6[15]); break; } *s = 0; @@ -638,7 +638,7 @@ char *NET_BaseAdrToString (char *s, int len, netadr_t a) p = s; for (i = 0; i < 16; i+=2) { - if (doneblank!=true && a.address.ip6[i] == 0 && a.address.ip6[i+1] == 0) + if (doneblank!=true && a->address.ip6[i] == 0 && a->address.ip6[i+1] == 0) { if (!doneblank) { @@ -656,16 +656,16 @@ char *NET_BaseAdrToString (char *s, int len, netadr_t a) snprintf (p, len-strlen(s), ":"); p += strlen(p); } - if (a.address.ip6[i+0]) + if (a->address.ip6[i+0]) { snprintf (p, len-strlen(s), "%x%02x", - a.address.ip6[i+0], - a.address.ip6[i+1]); + a->address.ip6[i+0], + a->address.ip6[i+1]); } else { snprintf (p, len-strlen(s), "%x", - a.address.ip6[i+1]); + a->address.ip6[i+1]); } p += strlen(p); } @@ -676,25 +676,25 @@ char *NET_BaseAdrToString (char *s, int len, netadr_t a) case NA_BROADCAST_IPX: case NA_IPX: snprintf (s, len, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x", - a.address.ipx[0], - a.address.ipx[1], - a.address.ipx[2], - a.address.ipx[3], - a.address.ipx[4], - a.address.ipx[5], - a.address.ipx[6], - a.address.ipx[7], - a.address.ipx[8], - a.address.ipx[9]); + a->address.ipx[0], + a->address.ipx[1], + a->address.ipx[2], + a->address.ipx[3], + a->address.ipx[4], + a->address.ipx[5], + a->address.ipx[6], + a->address.ipx[7], + a->address.ipx[8], + a->address.ipx[9]); break; #endif case NA_LOOPBACK: - snprintf (s, len, "LocalHost"); + snprintf (s, len, "QLoopBack"); break; #ifdef IRCCONNECT case NA_IRC: - snprintf (s, len, "irc://%s", a.address.irc.user); + NET_AdrToString(s, len, a); break; #endif default: @@ -976,10 +976,19 @@ qboolean NET_StringToAdr (const char *s, int defaultport, netadr_t *a) if (!strncmp (s, "irc://", 6)) { char *at; + char *slash; memset (a, 0, sizeof(*a)); a->type = NA_IRC; s+=6; + slash = strchr(s, '/'); + if (!slash) + return false; + if (slash - s+1 >= sizeof(a->address.irc.host)) + return false; + memcpy(a->address.irc.host, s, slash - s); + a->address.irc.host[slash - s] = 0; + s = slash+1; at = strchr(s, '@'); if (at) { @@ -1234,49 +1243,49 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask) // NET_CompareAdrMasked: given 3 addresses, 2 to compare with a complimentary mask, // returns true or false if they match -qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) +qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask) { int i; //make sure the address being checked against matches the mask - if (b.type != mask.type) + if (b->type != mask->type) return false; // check port if both are non-zero - if (a.port && b.port && a.port != b.port) + if (a->port && b->port && a->port != b->port) return false; // check to make sure all types match - if (a.type != b.type) + if (a->type != b->type) { - if (a.type == NA_IP && b.type == NA_IPV6 && mask.type == NA_IP) + if (a->type == NA_IP && b->type == NA_IPV6 && mask->type == NA_IP) { for (i = 0; i < 10; i++) - if (b.address.ip6[i] != 0) + if (b->address.ip6[i] != 0) return false; //only matches if they're 0s, otherwise its not an ipv4 address there for (; i < 12; i++) - if (b.address.ip6[i] != 0xff && b.address.ip6[i] != 0x00) //0x00 is depricated + if (b->address.ip6[i] != 0xff && b->address.ip6[i] != 0x00) //0x00 is depricated return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there for (i = 0; i < 4; i++) { - if ((a.address.ip[i] & mask.address.ip[i]) != (b.address.ip6[12+i] & mask.address.ip[i])) + if ((a->address.ip[i] & mask->address.ip[i]) != (b->address.ip6[12+i] & mask->address.ip[i])) return false; //mask doesn't match } return true; //its an ipv4 address in there, the mask matched the whole way through } - if (a.type == NA_IPV6 && b.type == NA_IP && mask.type == NA_IP) + if (a->type == NA_IPV6 && b->type == NA_IP && mask->type == NA_IP) { for (i = 0; i < 10; i++) - if (a.address.ip6[i] != 0) + if (a->address.ip6[i] != 0) return false; //only matches if they're 0s, otherwise its not an ipv4 address there for (; i < 12; i++) - if (a.address.ip6[i] != 0xff && a.address.ip6[i] != 0x00) //0x00 is depricated + if (a->address.ip6[i] != 0xff && a->address.ip6[i] != 0x00) //0x00 is depricated return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there for (i = 0; i < 4; i++) { - if ((a.address.ip6[12+i] & mask.address.ip[i]) != (b.address.ip[i] & mask.address.ip[i])) + if ((a->address.ip6[12+i] & mask->address.ip[i]) != (b->address.ip[i] & mask->address.ip[i])) return false; //mask doesn't match } return true; //its an ipv4 address in there, the mask matched the whole way through @@ -1285,7 +1294,7 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) } // match on protocol type and compare address - switch (a.type) + switch (a->type) { case NA_LOOPBACK: return true; @@ -1293,7 +1302,7 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) case NA_IP: for (i = 0; i < 4; i++) { - if ((a.address.ip[i] & mask.address.ip[i]) != (b.address.ip[i] & mask.address.ip[i])) + if ((a->address.ip[i] & mask->address.ip[i]) != (b->address.ip[i] & mask->address.ip[i])) return false; } break; @@ -1302,7 +1311,7 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) case NA_IPV6: for (i = 0; i < 16; i++) { - if ((a.address.ip6[i] & mask.address.ip6[i]) != (b.address.ip6[i] & mask.address.ip6[i])) + if ((a->address.ip6[i] & mask->address.ip6[i]) != (b->address.ip6[i] & mask->address.ip6[i])) return false; } break; @@ -1312,7 +1321,7 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) case NA_IPX: for (i = 0; i < 10; i++) { - if ((a.address.ipx[i] & mask.address.ipx[i]) != (b.address.ipx[i] & mask.address.ipx[i])) + if ((a->address.ipx[i] & mask->address.ipx[i]) != (b->address.ipx[i] & mask->address.ipx[i])) return false; } break; @@ -1321,7 +1330,7 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) #ifdef IRCCONNECT case NA_IRC: //masks are not supported, match explicitly - if (strcmp(a.address.irc.user, b.address.irc.user)) + if (strcmp(a->address.irc.user, b->address.irc.user)) return false; break; #endif @@ -1334,25 +1343,25 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) // UniformMaskedBits: counts number of bits in an assumed uniform mask, returns // -1 if not uniform -int UniformMaskedBits(netadr_t mask) +int UniformMaskedBits(netadr_t *mask) { int bits; int b; unsigned int bs; qboolean bitenc = false; - switch (mask.type) + switch (mask->type) { case NA_BROADCAST_IP: case NA_IP: bits = 32; for (b = 3; b >= 0; b--) { - if (mask.address.ip[b] == 0xFF) + if (mask->address.ip[b] == 0xFF) bitenc = true; - else if (mask.address.ip[b]) + else if (mask->address.ip[b]) { - bs = (~mask.address.ip[b]) & 0xFF; + bs = (~mask->address.ip[b]) & 0xFF; while (bs) { if (bs & 1) @@ -1378,11 +1387,11 @@ int UniformMaskedBits(netadr_t mask) bits = 128; for (b = 15; b >= 0; b--) { - if (mask.address.ip6[b] == 0xFF) + if (mask->address.ip6[b] == 0xFF) bitenc = true; - else if (mask.address.ip6[b]) + else if (mask->address.ip6[b]) { - bs = (~mask.address.ip6[b]) & 0xFF; + bs = (~mask->address.ip6[b]) & 0xFF; while (bs) { if (bs & 1) @@ -1409,11 +1418,11 @@ int UniformMaskedBits(netadr_t mask) bits = 80; for (b = 9; b >= 0; b--) { - if (mask.address.ipx[b] == 0xFF) + if (mask->address.ipx[b] == 0xFF) bitenc = true; - else if (mask.address.ipx[b]) + else if (mask->address.ipx[b]) { - bs = (~mask.address.ipx[b]) & 0xFF; + bs = (~mask->address.ipx[b]) & 0xFF; while (bs) { if (bs & 1) @@ -1441,7 +1450,7 @@ int UniformMaskedBits(netadr_t mask) return bits; // all checks passed } -char *NET_AdrToStringMasked (char *s, int len, netadr_t a, netadr_t amask) +char *NET_AdrToStringMasked (char *s, int len, netadr_t *a, netadr_t *amask) { int i; char adr[MAX_ADR_SIZE], mask[MAX_ADR_SIZE]; @@ -1487,10 +1496,10 @@ qboolean NET_IsClientLegal(netadr_t *adr) #endif } -qboolean NET_IsLoopBackAddress (netadr_t adr) +qboolean NET_IsLoopBackAddress (netadr_t *adr) { // return (!strcmp(cls.servername, NET_AdrToString(net_local_adr)) || !strcmp(cls.servername, "local"); - return adr.type == NA_LOOPBACK; + return adr->type == NA_LOOPBACK; } ///////////////////////////////////////////// @@ -1535,7 +1544,7 @@ qboolean NET_GetLoopPacket (int sock, netadr_t *from, sizebuf_t *message) } -void NET_SendLoopPacket (int sock, int length, void *data, netadr_t to) +void NET_SendLoopPacket (int sock, int length, void *data, netadr_t *to) { int i; loopback_t *loop; @@ -1572,9 +1581,9 @@ qboolean FTENET_Loop_GetPacket(ftenet_generic_connection_t *con) return NET_GetLoopPacket(con->thesocket, &net_from, &net_message); } -qboolean FTENET_Loop_SendPacket(ftenet_generic_connection_t *con, int length, void *data, netadr_t to) +qboolean FTENET_Loop_SendPacket(ftenet_generic_connection_t *con, int length, void *data, netadr_t *to) { - if (to.type == NA_LOOPBACK) + if (to->type == NA_LOOPBACK) { NET_SendLoopPacket(con->thesocket, length, data, to); return true; @@ -1683,7 +1692,7 @@ static qboolean NET_Was_NATPMP(ftenet_connections_t *collection) if (collection->conn[i]->GetLocalAddress == FTENET_NATPMP_GetLocalAddress) { pmp = (pmpcon_t*)collection->conn[i]; - if (NET_CompareAdr(pmp->pmpaddr, net_from)) + if (NET_CompareAdr(&pmp->pmpaddr, &net_from)) { pmpreqrep = (void*)net_message.data; @@ -1695,7 +1704,7 @@ static qboolean NET_Was_NATPMP(ftenet_connections_t *collection) pmp->natadr.type = NA_IP; pmp->natadr.port = 0; memcpy(pmp->natadr.address.ip, pmpreqrep->ipv4, sizeof(pmp->natadr.address.ip)); - NET_AdrToString(adrbuf, sizeof(adrbuf), pmp->natadr); + NET_AdrToString(adrbuf, sizeof(adrbuf), &pmp->natadr); // Con_Printf("Public ip is %s\n", adrbuf); return true; } @@ -1809,11 +1818,11 @@ static void FTENET_NATPMP_Refresh(pmpcon_t *pmp, short oldport, ftenet_connectio //get the public ip. pmpreqmsg.op = 0; - NET_SendPacket(NS_SERVER, 2, &pmpreqmsg, pmp->pmpaddr); + NET_SendPacket(NS_SERVER, 2, &pmpreqmsg, &pmp->pmpaddr); //open the firewall/nat. pmpreqmsg.op = 1; - NET_SendPacket(NS_SERVER, sizeof(pmpreqmsg), &pmpreqmsg, pmp->pmpaddr); + NET_SendPacket(NS_SERVER, sizeof(pmpreqmsg), &pmpreqmsg, &pmp->pmpaddr); break; } @@ -1841,7 +1850,7 @@ qboolean FTENET_NATPMP_GetPacket(struct ftenet_generic_connection_s *con) } return false; } -qboolean FTENET_NATPMP_SendPacket(struct ftenet_generic_connection_s *con, int length, void *data, netadr_t to) +qboolean FTENET_NATPMP_SendPacket(struct ftenet_generic_connection_s *con, int length, void *data, netadr_t *to) { return false; } @@ -2185,7 +2194,7 @@ qboolean FTENET_Generic_GetPacket(ftenet_generic_connection_t *con) { SockadrToNetadr (&from, &net_from); Con_TPrintf (TL_OVERSIZEPACKETFROM, - NET_AdrToString (adr, sizeof(adr), net_from)); + NET_AdrToString (adr, sizeof(adr), &net_from)); return false; } if (err == ECONNABORTED || err == ECONNRESET) @@ -2215,7 +2224,7 @@ qboolean FTENET_Generic_GetPacket(ftenet_generic_connection_t *con) net_message.cursize = ret; if (net_message.cursize == sizeof(net_message_buffer) ) { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), &net_from)); return false; } @@ -2223,7 +2232,7 @@ qboolean FTENET_Generic_GetPacket(ftenet_generic_connection_t *con) #endif } -qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length, void *data, netadr_t to) +qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length, void *data, netadr_t *to) { #ifndef HAVE_PACKET return false; @@ -2233,28 +2242,28 @@ qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length, int ret; for (size = 0; size < FTENET_ADDRTYPES; size++) - if (to.type == con->addrtype[size]) + if (to->type == con->addrtype[size]) break; if (size == FTENET_ADDRTYPES) return false; #ifdef IPPROTO_IPV6 /*special code to handle sending to hybrid sockets*/ - if (con->addrtype[1] == NA_IPV6 && to.type == NA_IP) + if (con->addrtype[1] == NA_IPV6 && to->type == NA_IP) { memset(&addr, 0, sizeof(struct sockaddr_in6)); ((struct sockaddr_in6*)&addr)->sin6_family = AF_INET6; *(short*)&((struct sockaddr_in6*)&addr)->sin6_addr.s6_addr[10] = 0xffff; - *(int*)&((struct sockaddr_in6*)&addr)->sin6_addr.s6_addr[12] = *(int*)&to.address.ip; - ((struct sockaddr_in6*)&addr)->sin6_port = to.port; + *(int*)&((struct sockaddr_in6*)&addr)->sin6_addr.s6_addr[12] = *(int*)&to->address.ip; + ((struct sockaddr_in6*)&addr)->sin6_port = to->port; size = sizeof(struct sockaddr_in6); } else #endif { - NetadrToSockadr (&to, &addr); + NetadrToSockadr (to, &addr); - switch(to.type) + switch(to->type) { default: Con_Printf("Bad address type\n"); @@ -2289,6 +2298,12 @@ qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length, if (ecode == ECONNREFUSED) return true; + if (ecode == EACCES) + { + Con_Printf("Access denied: check firewall\n"); + return true; + } + #ifndef SERVERONLY if (ecode == EADDRNOTAVAIL) Con_DPrintf("NET_SendPacket Warning: %i\n", ecode); @@ -2414,7 +2429,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i { SockadrToNetadr(&qs, &adr); //mneh, reuse qs. - NET_AdrToString((char*)&qs, sizeof(qs), adr); + NET_AdrToString((char*)&qs, sizeof(qs), &adr); Con_Printf("Unable to listen at %s\n", (char*)&qs); closesocket(newsocket); return NULL; @@ -2585,14 +2600,14 @@ qboolean FTENET_TCPConnect_GetPacket(ftenet_generic_connection_t *gcon) if (st->timeouttime < timeval) { - Con_Printf ("tcp peer %s timed out\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("tcp peer %s timed out\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; } ret = recv(st->socketnum, st->inbuffer+st->inlen, sizeof(st->inbuffer)-st->inlen, 0); if (ret == 0) { - Con_Printf ("tcp peer %s closed connection\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("tcp peer %s closed connection\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; } else if (ret == -1) @@ -2768,7 +2783,7 @@ closesvstream: { if (atoi(arg[WCATTR_WSVER]) != 13) { - Con_Printf("Outdated websocket request from %s. got version %i, expected version 13\n", arg[WCATTR_URL], NET_AdrToString (adr, sizeof(adr), st->remoteaddr), arg[WCATTR_WSVER]); + Con_Printf("Outdated websocket request from %s. got version %i, expected version 13\n", arg[WCATTR_URL], NET_AdrToString (adr, sizeof(adr), &st->remoteaddr), arg[WCATTR_WSVER]); memmove(st->inbuffer, st->inbuffer+i, st->inlen - (i)); st->inlen -= i; @@ -2789,7 +2804,7 @@ closesvstream: tobase64(acceptkey, sizeof(acceptkey), sha1digest, SHA1(sha1digest, sizeof(sha1digest), va("%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", arg[WCATTR_WSKEY]))); - Con_Printf("Websocket request for %s from %s\n", arg[WCATTR_URL], NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf("Websocket request for %s from %s\n", arg[WCATTR_URL], NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); resp = va( "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" @@ -2851,7 +2866,7 @@ closesvstream: */ else { - Con_Printf("Invalid download request %s to %s\n", arg[WCATTR_URL], NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf("Invalid download request %s to %s\n", arg[WCATTR_URL], NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); resp = va( "HTTP/1.1 404 Ok\r\n" "Connection: Close\r\n" "Content-Type: text/html\r\n" @@ -2872,7 +2887,7 @@ closesvstream: else { handshakeerror: - Con_Printf ("Unknown TCP handshake from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + Con_Printf ("Unknown TCP handshake from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from)); goto closesvstream; } @@ -2909,7 +2924,7 @@ handshakeerror: net_message.cursize = BigShort(*(short*)st->inbuffer); if (net_message.cursize >= sizeof(net_message_buffer) ) { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; } if (net_message.cursize+2 > st->inlen) @@ -2951,7 +2966,7 @@ handshakeerror: //as a payload is not allowed to be encoded as too large a type, and quakeworld never used packets larger than 1450 bytes anyway, this code isn't needed (65k is the max even without this) // if (sizeof(paylen) < 8) { - Con_Printf ("%s: payload frame too large\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("%s: payload frame too large\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; } /* else @@ -2984,7 +2999,7 @@ handshakeerror: ((unsigned char*)st->inbuffer)[payoffs+1]<<0; if (paylen < 126) { - Con_Printf ("%s: payload size encoded badly\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("%s: payload size encoded badly\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; } payoffs += 2; @@ -3022,7 +3037,7 @@ handshakeerror: switch((ctrl>>8) & 0xf) { case 0: /*continuation*/ - Con_Printf ("websocket continuation frame from %s\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("websocket continuation frame from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; case 1: /*text frame*/ // Con_Printf ("websocket text frame from %s\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); @@ -3063,22 +3078,22 @@ handshakeerror: net_message.cursize = paylen; if (net_message.cursize >= sizeof(net_message_buffer) ) { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), &net_from)); goto closesvstream; } memcpy(net_message_buffer, st->inbuffer+payoffs, paylen); break; case 8: /*connection close*/ - Con_Printf ("websocket closure %s\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("websocket closure %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; case 9: /*ping*/ - Con_Printf ("websocket ping from %s\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("websocket ping from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; case 10: /*pong*/ - Con_Printf ("websocket pong from %s\n", NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("websocket pong from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; default: - Con_Printf ("Unsupported websocket opcode (%i) from %s\n", (ctrl>>8) & 0xf, NET_AdrToString (adr, sizeof(adr), st->remoteaddr)); + Con_Printf ("Unsupported websocket opcode (%i) from %s\n", (ctrl>>8) & 0xf, NET_AdrToString (adr, sizeof(adr), &st->remoteaddr)); goto closesvstream; } @@ -3131,7 +3146,7 @@ handshakeerror: return false; } -qboolean FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t to) +qboolean FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t *to) { ftenet_tcpconnect_connection_t *con = (ftenet_tcpconnect_connection_t*)gcon; ftenet_tcpconnect_stream_t *st; @@ -3141,7 +3156,7 @@ qboolean FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int len if (st->socketnum == INVALID_SOCKET) continue; - if (NET_CompareAdr(to, st->remoteaddr)) + if (NET_CompareAdr(to, &st->remoteaddr)) { if (!st->outlen) { @@ -3345,7 +3360,7 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, { SockadrToNetadr(&qs, &adr); //mneh, reuse qs. - NET_AdrToString((char*)&qs, sizeof(qs), adr); + NET_AdrToString((char*)&qs, sizeof(qs), &adr); Con_Printf("Unable to listen at %s\n", (char*)&qs); closesocket(newsocket); return NULL; @@ -3362,7 +3377,7 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, if (adr.type == NA_IP) adr.type = NA_TCP; - newsocket = TCP_OpenStream(adr); + newsocket = TCP_OpenStream(&adr); if (newsocket == INVALID_SOCKET) return NULL; } @@ -3486,21 +3501,31 @@ qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) { if (con->income == 0) { + netadr_t ip; cvar_t *ircuser = Cvar_Get("ircuser", "none", 0, "IRC Connect"); - cvar_t *irchost = Cvar_Get("irchost", "none", 0, "IRC Connect"); - cvar_t *ircnick = Cvar_Get("ircnick", "ftesv", 0, "IRC Connect"); - //cvar_t *ircchannel = Cvar_Get("ircchannel", "#ftetest", 0, "IRC Connect"); //warning: unused variable ‘ircchannel’ + cvar_t *ircnick = Cvar_Get("ircnick", "", 0, "IRC Connect"); cvar_t *ircsomething = Cvar_Get("ircsomething", "moo", 0, "IRC Connect"); cvar_t *ircclientaddr = Cvar_Get("ircclientaddr", "127.0.0.1", 0, "IRC Connect"); - con->generic.thesocket = TCP_OpenStream(con->ircserver); + NET_StringToAdr(con->ircserver.address.irc.host, 6667, &ip); + con->generic.thesocket = TCP_OpenStream(&ip); - Q_strncpyz(con->ourusername, ircnick->string, sizeof(con->ourusername)); + //when hosting, the specified nick is the name we're using. + //when connecting, the specified nick is the name we're trying to send to, and our own name is inconsequential. + if (con->generic.islisten && *con->ircserver.address.irc.user) + Q_strncpyz(con->ourusername, con->ircserver.address.irc.user, sizeof(con->ourusername)); + else + Q_strncpyz(con->ourusername, ircnick->string, sizeof(con->ourusername)); + + if (!*con->ourusername) + { + Q_snprintfz(con->ourusername, sizeof(con->ourusername), "fte%x\n", rand()); + } send(con->generic.thesocket, "USER ", 5, 0); send(con->generic.thesocket, ircuser->string, strlen(ircuser->string), 0); send(con->generic.thesocket, " ", 1, 0); - send(con->generic.thesocket, irchost->string, strlen(irchost->string), 0); + send(con->generic.thesocket, con->ircserver.address.irc.host, strlen(con->ircserver.address.irc.host), 0); send(con->generic.thesocket, " ", 1, 0); send(con->generic.thesocket, ircclientaddr->string, strlen(ircclientaddr->string), 0); send(con->generic.thesocket, " :", 2, 0); @@ -3637,7 +3662,7 @@ qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) net_message.cursize = 4 + endl - s; if (net_message.cursize >= sizeof(net_message_buffer) ) { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), &net_from)); break; } @@ -3756,7 +3781,7 @@ qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) if (st->inlen > psize || psize >= sizeof(net_message_buffer) ) { st->inlen = 0; - Con_Printf ("Corrupt packet from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + Con_Printf ("Corrupt packet from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from)); } else if (st->inlen == psize) { @@ -3764,7 +3789,7 @@ qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) net_message.cursize = st->inlen; if (net_message.cursize >= sizeof(net_message_buffer) ) { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), &net_from)); break; } @@ -3798,11 +3823,10 @@ qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) { case 001: { - cvar_t *ircchannel = Cvar_Get("ircchannel", "", 0, "IRC Connect"); - if (*ircchannel->string) + if (con->ircserver.address.irc.channel) { send(con->generic.thesocket, "JOIN ", 5, 0); - send(con->generic.thesocket, ircchannel->string, strlen(ircchannel->string), 0); + send(con->generic.thesocket, con->ircserver.address.irc.channel, strlen(con->ircserver.address.irc.channel), 0); send(con->generic.thesocket, "\r\n", 2, 0); } } @@ -3838,7 +3862,7 @@ qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) return false; } -qboolean FTENET_IRCConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t to) +qboolean FTENET_IRCConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t *to) { ftenet_ircconnect_connection_t *con = (ftenet_ircconnect_connection_t*)gcon; @@ -3849,7 +3873,7 @@ qboolean FTENET_IRCConnect_SendPacket(ftenet_generic_connection_t *gcon, int len int newoutcount; for (packed = 0; packed < FTENET_ADDRTYPES; packed++) - if (to.type == con->generic.addrtype[packed]) + if (to->type == con->generic.addrtype[packed]) break; if (packed == FTENET_ADDRTYPES) return false; @@ -3876,21 +3900,21 @@ qboolean FTENET_IRCConnect_SendPacket(ftenet_generic_connection_t *gcon, int len { buffer = con->outbuf + newoutcount; - if (*to.address.irc.channel) + if (*to->address.irc.channel) { int unamelen; int chanlen; - unamelen = strlen(to.address.irc.user); - chanlen = strlen(to.address.irc.channel); + unamelen = strlen(to->address.irc.user); + chanlen = strlen(to->address.irc.channel); packed = 8+chanlen+3+unamelen+1 + 3; if (packed+1 + newoutcount > sizeof(con->outbuf)) break; memcpy(buffer, "PRIVMSG ", 8); - memcpy(buffer+8, to.address.irc.channel, chanlen); + memcpy(buffer+8, to->address.irc.channel, chanlen); memcpy(buffer+8+chanlen, " :$", 3); - memcpy(buffer+8+chanlen+3, to.address.irc.user, unamelen); + memcpy(buffer+8+chanlen+3, to->address.irc.user, unamelen); memcpy(buffer+8+chanlen+3+unamelen, "#", 1); lenofs = buffer+8+chanlen+3+unamelen+1; sprintf(lenofs, "%03x", fulllen); @@ -3899,14 +3923,14 @@ qboolean FTENET_IRCConnect_SendPacket(ftenet_generic_connection_t *gcon, int len else { int unamelen; - unamelen = strlen(to.address.irc.user); + unamelen = strlen(to->address.irc.user); packed = 8 + unamelen + 3 + 3; if (packed+1 + newoutcount > sizeof(con->outbuf)) break; memcpy(buffer, "PRIVMSG ", 8); - memcpy(buffer+8, to.address.irc.user, unamelen); + memcpy(buffer+8, to->address.irc.user, unamelen); memcpy(buffer+8+unamelen, " :#", 3); lenofs = buffer+8+unamelen+3; sprintf(lenofs, "%03x", fulllen); @@ -4293,7 +4317,7 @@ int NET_LocalAddressForRemote(ftenet_connections_t *collection, netadr_t *remote return collection->conn[remote->connum-1]->GetLocalAddress(collection->conn[remote->connum-1], local, idx); } -void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) +void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t *to) { char buffer[64]; ftenet_connections_t *collection; @@ -4327,10 +4351,10 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) return; } - if (to.connum) + if (to->connum) { - if (collection->conn[to.connum-1]) - if (collection->conn[to.connum-1]->SendPacket(collection->conn[to.connum-1], length, data, to)) + if (collection->conn[to->connum-1]) + if (collection->conn[to->connum-1]->SendPacket(collection->conn[to->connum-1], length, data, to)) return; } @@ -4386,7 +4410,7 @@ void NET_PrintAddresses(ftenet_connections_t *collection) { for (adrcount=1; (adrcount = collection->conn[i]->GetLocalAddress(collection->conn[i], &adr, adrno)) && adrno < adrcount; adrno++) { - Con_Printf("net address (%s): %s\n", collection->conn[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), adr)); + Con_Printf("net address (%s): %s\n", collection->conn[i]->name, NET_AdrToString(adrbuf, sizeof(adrbuf), &adr)); } } if (!adrno) @@ -4396,7 +4420,7 @@ void NET_PrintAddresses(ftenet_connections_t *collection) //============================================================================= -int TCP_OpenStream (netadr_t remoteaddr) +int TCP_OpenStream (netadr_t *remoteaddr) { #ifndef HAVE_TCP return INVALID_SOCKET; @@ -4408,7 +4432,7 @@ int TCP_OpenStream (netadr_t remoteaddr) // struct sockaddr_qstorage loc; int recvbufsize = (1<<19);//512kb - temp = NetadrToSockadr(&remoteaddr, &qs); + temp = NetadrToSockadr(remoteaddr, &qs); if ((newsocket = socket (((struct sockaddr_in*)&qs)->sin_family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) return INVALID_SOCKET; @@ -4426,11 +4450,13 @@ int TCP_OpenStream (netadr_t remoteaddr) { char buf[128]; NET_AdrToString(buf, sizeof(buf), remoteaddr); - if (remoteaddr.port == 0 && (remoteaddr.type == NA_IP || remoteaddr.type == NA_IPV6)) + if (remoteaddr->port == 0 && (remoteaddr->type == NA_IP || remoteaddr->type == NA_IPV6)) Con_Printf ("TCP_OpenStream: no port specified\n"); else Con_Printf ("TCP_OpenStream: invalid address trying to connect to %s\n", buf); } + else if (err == EACCES) + Con_Printf ("TCP_OpenStream: access denied: check firewall\n"); else Con_Printf ("TCP_OpenStream: connect: error %i\n", err); closesocket(newsocket); @@ -4814,7 +4840,7 @@ void NET_GetLocalAddress (int socket, netadr_t *out) if (notvalid) Con_Printf("Couldn't detect local ip\n"); else - Con_TPrintf(TL_IPADDRESSIS, NET_AdrToString (adrbuf, sizeof(adrbuf), *out) ); + Con_TPrintf(TL_IPADDRESSIS, NET_AdrToString (adrbuf, sizeof(adrbuf), out) ); #endif } @@ -4881,7 +4907,7 @@ static qboolean NET_WasStun(void) adr.type = NA_IP; adr.port = (((short*)attr)[3]); memcpy(adr.address.ip, &((qbyte*)attr)[8], 4); - NET_AdrToString(str, sizeof(str), adr); + NET_AdrToString(str, sizeof(str), &adr); Con_Printf("Public address %s\n", str); } else if (attr->attrtype == BigShort(1) && alen == 20 && ((qbyte*)attr)[5] == 2) //ipv6 MAPPED-ADDRESS @@ -4891,7 +4917,7 @@ static qboolean NET_WasStun(void) adr.type = NA_IPV6; adr.port = (((short*)attr)[3]); memcpy(adr.address.ip6, &((qbyte*)attr)[8], 16); - NET_AdrToString(str, sizeof(str), adr); + NET_AdrToString(str, sizeof(str), &adr); Con_Printf("Public address %s\n", str); } attr = (stunattr_t*)((char*)(attr+1) + alen); @@ -4921,7 +4947,7 @@ void SVNET_Stun_f(void) Sys_RandomBytes((qbyte*)&stunmsg.hdr.transactid[0], sizeof(stunmsg.hdr.transactid)); // 'and SHOULD be cryptographically random' stunmsg.hdr.msgtype = BigShort(0x0001); //binding request stunmsg.hdr.msglen = BigShort(0); - NET_SendPacket(NS_SERVER, sizeof(stunmsg), &stunmsg, stunserverip); + NET_SendPacket(NS_SERVER, sizeof(stunmsg), &stunmsg, &stunserverip); } #endif @@ -5068,7 +5094,7 @@ void SV_Port_NatPMP_Callback(struct cvar_s *var, char *oldvalue) { FTENET_AddToCollection(svs.sockets, var->name, va("natpmp://%s", var->string), NA_NATPMP, true); } -#ifdef SERVERONLY +#if 1//def SERVERONLY #define NATPMP_DEFAULT_PORT "" //don't fuck with dedicated servers #else #define NATPMP_DEFAULT_PORT "5351" //home users, yay, lucky people. @@ -5238,7 +5264,7 @@ void VFSTCP_Error(tcpfile_t *f) f->sock = INVALID_SOCKET; } } -int VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) +int QDECL VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) { tcpfile_t *tf = (tcpfile_t*)file; int len; @@ -5298,7 +5324,7 @@ int VFSTCP_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread) return 0; //signal nothing available } } -int VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) +int QDECL VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread) { tcpfile_t *tf = (tcpfile_t*)file; int len; @@ -5316,21 +5342,21 @@ int VFSTCP_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestore } return len; } -qboolean VFSTCP_Seek (struct vfsfile_s *file, unsigned long pos) +qboolean QDECL VFSTCP_Seek (struct vfsfile_s *file, unsigned long pos) { VFSTCP_Error((tcpfile_t*)file); return false; } -unsigned long VFSTCP_Tell (struct vfsfile_s *file) +unsigned long QDECL VFSTCP_Tell (struct vfsfile_s *file) { VFSTCP_Error((tcpfile_t*)file); return 0; } -unsigned long VFSTCP_GetLen (struct vfsfile_s *file) +unsigned long QDECL VFSTCP_GetLen (struct vfsfile_s *file) { return 0; } -void VFSTCP_Close (struct vfsfile_s *file) +void QDECL VFSTCP_Close (struct vfsfile_s *file) { VFSTCP_Error((tcpfile_t*)file); Z_Free(file); @@ -5343,7 +5369,7 @@ vfsfile_t *FS_OpenTCP(const char *name, int defaultport) netadr_t adr = {0}; if (NET_StringToAdr(name, defaultport, &adr)) { - sock = TCP_OpenStream(adr); + sock = TCP_OpenStream(&adr); if (sock == INVALID_SOCKET) return NULL; diff --git a/engine/common/netinc.h b/engine/common/netinc.h index e8e69461e..6622fc8b4 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -105,16 +105,18 @@ #undef EAFNOSUPPORT #undef ECONNABORTED #undef ECONNREFUSED - #undef ECONNRESET + #undef ECONNREFUSED #undef EMSGSIZE #undef EWOULDBLOCK #endif + #undef EACCES - #define EWOULDBLOCK WSAEWOULDBLOCK - #define EMSGSIZE WSAEMSGSIZE - #define ECONNRESET WSAECONNRESET + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EMSGSIZE WSAEMSGSIZE + #define ECONNRESET WSAECONNRESET #define ECONNABORTED WSAECONNABORTED #define ECONNREFUSED WSAECONNREFUSED + #define EACCES WSAEACCES #define EADDRNOTAVAIL WSAEADDRNOTAVAIL #define EAFNOSUPPORT WSAEAFNOSUPPORT diff --git a/engine/common/particles.h b/engine/common/particles.h index a8fd33316..b64c5e6b9 100644 --- a/engine/common/particles.h +++ b/engine/common/particles.h @@ -123,8 +123,6 @@ typedef struct { char *name1; char *name2; - - int (*ParticleTypeForName) (char *name); int (*FindParticleType) (char *name); qboolean (*ParticleQuery) (int type, int body, char *outstr, int outstrlen); diff --git a/engine/common/plugin.c b/engine/common/plugin.c index aa57e16ad..421315dc6 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -3,6 +3,7 @@ //named functions, this makes it *really* easy to port plugins from one engine to annother. #include "quakedef.h" +#include "fs.h" #ifdef PLUGINS //#define GNUTLS @@ -314,7 +315,10 @@ plugin_t *Plug_Load(char *file) newplug->name = (char*)(newplug+1); strcpy(newplug->name, file); - newplug->vm = VM_Create(NULL, file, Plug_SystemCallsNative, Plug_SystemCallsVM); + if (!strncmp(file, "fteplug_", 8)) + newplug->vm = VM_Create(NULL, file, Plug_SystemCallsNative, NULL); + else + newplug->vm = VM_Create(NULL, file, Plug_SystemCallsNative, Plug_SystemCallsVM); currentplug = newplug; if (newplug->vm) { @@ -344,7 +348,7 @@ plugin_t *Plug_Load(char *file) return newplug; } -static int Plug_Emumerated (const char *name, int size, void *param, struct searchpath_s *spath) +static int QDECL Plug_Emumerated (const char *name, int size, void *param, struct searchpath_s *spath) { char vmname[MAX_QPATH]; Q_strncpyz(vmname, name, sizeof(vmname)); @@ -354,6 +358,27 @@ static int Plug_Emumerated (const char *name, int size, void *param, struct sear return true; } +static int QDECL Plug_EnumeratedRoot (const char *name, int size, void *param, struct searchpath_s *spath) +{ + char vmname[MAX_QPATH]; + int len; + char *dot; + Q_strncpyz(vmname, name, sizeof(vmname)); + len = strlen(vmname); + len -= strlen(ARCH_CPU_POSTFIX ARCH_DL_POSTFIX); + if (!strcmp(vmname+len, ARCH_CPU_POSTFIX ARCH_DL_POSTFIX)) + vmname[len] = 0; + else + { + dot = strchr(vmname, '.'); + if (dot) + *dot = 0; + } + if (!Plug_Load(vmname)) + Con_Printf("Couldn't load plugin %s\n", vmname); + + return true; +} static qintptr_t VARGS Plug_Con_Print(void *offset, quintptr_t mask, const qintptr_t *arg) { @@ -452,13 +477,10 @@ static qintptr_t VARGS Plug_ExportNative(void *offset, quintptr_t mask, const qi //this is useful for certain things, like if the plugin uses some external networking or direct disk access or whatever. currentplug->blockcloses++; } - /* - else if (!strncmp(name, "FS_LoadModule")) //module as in pak/pk3 + else if (!strncmp(name, "FS_RegisterArchiveType_", 23)) //module as in pak/pk3 { - FS_RegisterModuleDriver(name + 13, func); - currentplug->blockcloses++; + FS_RegisterFileSystemType(currentplug, name+23, func, true); } - */ /* else if (!strncmp(name, "S_OutputDriver")) //a sound driver (takes higher priority over the built-in ones) { @@ -890,7 +912,7 @@ static qintptr_t VARGS Plug_Net_Accept(void *offset, quintptr_t mask, const qint netadr_t a; char *s; SockadrToNetadr((struct sockaddr_qstorage *)&address, &a); - s = NET_AdrToString(adr, sizeof(adr), a); + s = NET_AdrToString(adr, sizeof(adr), &a); Q_strncpyz(VM_POINTER(arg[1]), s, addrlen); } @@ -1084,6 +1106,18 @@ qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr_t *arg *ret = handle; return VFS_GETLEN(pluginstreamarray[handle].vfs); } +qintptr_t VARGS Plug_FS_Seek(void *offset, quintptr_t mask, const qintptr_t *arg) +{ + int handle = arg[0]; + unsigned int low = arg[1], high = arg[2]; + pluginstream_t *stream; + + stream = &pluginstreamarray[handle]; + if (stream->type != STREAM_VFS) + return -1; + VFS_SEEK(stream->vfs, low | ((unsigned long long)high<<32)); + return VFS_TELL(stream->vfs); +} qintptr_t VARGS Plug_memset(void *offset, quintptr_t mask, const qintptr_t *arg) { @@ -1297,7 +1331,7 @@ qintptr_t VARGS Plug_Net_SendTo(void *offset, quintptr_t mask, const qintptr_t * struct sockaddr_qstorage sockaddr; if (handle == -1) { - NET_SendPacket(NS_CLIENT, srclen, src, *address); + NET_SendPacket(NS_CLIENT, srclen, src, address); return srclen; } @@ -1403,83 +1437,91 @@ void VM_Test_f(void) } }*/ -void Plug_Init(void) +void Plug_Initialise(qboolean fromgamedir) { -// Cmd_AddCommand("testvm", VM_Test_f); + char nat[MAX_OSPATH]; - Cvar_Register(&plug_sbar, "plugins"); - Cvar_Register(&plug_loaddefault, "plugins"); - Cmd_AddCommand("plug_closeall", Plug_CloseAll_f); - Cmd_AddCommand("plug_close", Plug_Close_f); - Cmd_AddCommand("plug_load", Plug_Load_f); - Cmd_AddCommand("plug_list", Plug_List_f); + if (!numplugbuiltins) + { + Cvar_Register(&plug_sbar, "plugins"); + Cvar_Register(&plug_loaddefault, "plugins"); + Cmd_AddCommand("plug_closeall", Plug_CloseAll_f); + Cmd_AddCommand("plug_close", Plug_Close_f); + Cmd_AddCommand("plug_load", Plug_Load_f); + Cmd_AddCommand("plug_list", Plug_List_f); - Plug_RegisterBuiltin("Plug_GetEngineFunction", Plug_GetBuiltin, 0);//plugin wishes to find a builtin number. - Plug_RegisterBuiltin("Plug_ExportToEngine", Plug_ExportToEngine, 0); //plugin has a call back that we might be interested in. - Plug_RegisterBuiltin("Plug_ExportNative", Plug_ExportNative, PLUG_BIF_DLLONLY); - Plug_RegisterBuiltin("Plug_GetPluginName", Plug_GetPluginName, 0); - Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles. - Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0); - Plug_RegisterBuiltin("Sys_Milliseconds", Plug_Sys_Milliseconds, 0); - Plug_RegisterBuiltin("Com_Error", Plug_Sys_Error, 0); //make zquake programmers happy. + Plug_RegisterBuiltin("Plug_GetEngineFunction", Plug_GetBuiltin, 0);//plugin wishes to find a builtin number. + Plug_RegisterBuiltin("Plug_ExportToEngine", Plug_ExportToEngine, 0); //plugin has a call back that we might be interested in. + Plug_RegisterBuiltin("Plug_ExportNative", Plug_ExportNative, PLUG_BIF_DLLONLY); + Plug_RegisterBuiltin("Plug_GetPluginName", Plug_GetPluginName, 0); + Plug_RegisterBuiltin("Con_Print", Plug_Con_Print, 0); //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles. + Plug_RegisterBuiltin("Sys_Error", Plug_Sys_Error, 0); + Plug_RegisterBuiltin("Sys_Milliseconds", Plug_Sys_Milliseconds, 0); + Plug_RegisterBuiltin("Com_Error", Plug_Sys_Error, 0); //make zquake programmers happy. - Plug_RegisterBuiltin("Cmd_AddCommand", Plug_Cmd_AddCommand, 0); - Plug_RegisterBuiltin("Cmd_Args", Plug_Cmd_Args, 0); - Plug_RegisterBuiltin("Cmd_Argc", Plug_Cmd_Argc, 0); - Plug_RegisterBuiltin("Cmd_Argv", Plug_Cmd_Argv, 0); - Plug_RegisterBuiltin("Cmd_AddText", Plug_Cmd_AddText, 0); + Plug_RegisterBuiltin("Cmd_AddCommand", Plug_Cmd_AddCommand, 0); + Plug_RegisterBuiltin("Cmd_Args", Plug_Cmd_Args, 0); + Plug_RegisterBuiltin("Cmd_Argc", Plug_Cmd_Argc, 0); + Plug_RegisterBuiltin("Cmd_Argv", Plug_Cmd_Argv, 0); + Plug_RegisterBuiltin("Cmd_AddText", Plug_Cmd_AddText, 0); - Plug_RegisterBuiltin("Cvar_Register", Plug_Cvar_Register, 0); - Plug_RegisterBuiltin("Cvar_Update", Plug_Cvar_Update, 0); - Plug_RegisterBuiltin("Cvar_SetString", Plug_Cvar_SetString, 0); - Plug_RegisterBuiltin("Cvar_SetFloat", Plug_Cvar_SetFloat, 0); - Plug_RegisterBuiltin("Cvar_GetString", Plug_Cvar_GetString, 0); - Plug_RegisterBuiltin("Cvar_GetFloat", Plug_Cvar_GetFloat, 0); + Plug_RegisterBuiltin("Cvar_Register", Plug_Cvar_Register, 0); + Plug_RegisterBuiltin("Cvar_Update", Plug_Cvar_Update, 0); + Plug_RegisterBuiltin("Cvar_SetString", Plug_Cvar_SetString, 0); + Plug_RegisterBuiltin("Cvar_SetFloat", Plug_Cvar_SetFloat, 0); + Plug_RegisterBuiltin("Cvar_GetString", Plug_Cvar_GetString, 0); + Plug_RegisterBuiltin("Cvar_GetFloat", Plug_Cvar_GetFloat, 0); #ifndef NACL - Plug_RegisterBuiltin("Net_TCPListen", Plug_Net_TCPListen, 0); - Plug_RegisterBuiltin("Net_Accept", Plug_Net_Accept, 0); - Plug_RegisterBuiltin("Net_TCPConnect", Plug_Net_TCPConnect, 0); + Plug_RegisterBuiltin("Net_TCPListen", Plug_Net_TCPListen, 0); + Plug_RegisterBuiltin("Net_Accept", Plug_Net_Accept, 0); + Plug_RegisterBuiltin("Net_TCPConnect", Plug_Net_TCPConnect, 0); #ifdef GNUTLS - if (Init_GNUTLS()) - Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); + if (Init_GNUTLS()) + Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); #endif #ifdef HAVE_SSL - Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); + Plug_RegisterBuiltin("Net_SetTLSClient", Plug_Net_SetTLSClient, 0); #endif - Plug_RegisterBuiltin("Net_Recv", Plug_Net_Recv, 0); - Plug_RegisterBuiltin("Net_Send", Plug_Net_Send, 0); - Plug_RegisterBuiltin("Net_SendTo", Plug_Net_SendTo, 0); - Plug_RegisterBuiltin("Net_Close", Plug_Net_Close, 0); + Plug_RegisterBuiltin("Net_Recv", Plug_Net_Recv, 0); + Plug_RegisterBuiltin("Net_Send", Plug_Net_Send, 0); + Plug_RegisterBuiltin("Net_SendTo", Plug_Net_SendTo, 0); + Plug_RegisterBuiltin("Net_Close", Plug_Net_Close, 0); #endif - Plug_RegisterBuiltin("FS_Open", Plug_FS_Open, 0); - Plug_RegisterBuiltin("FS_Read", Plug_Net_Recv, 0); - Plug_RegisterBuiltin("FS_Write", Plug_Net_Send, 0); - Plug_RegisterBuiltin("FS_Close", Plug_Net_Close, 0); + Plug_RegisterBuiltin("FS_Open", Plug_FS_Open, 0); + Plug_RegisterBuiltin("FS_Read", Plug_Net_Recv, 0); + Plug_RegisterBuiltin("FS_Write", Plug_Net_Send, 0); + Plug_RegisterBuiltin("FS_Close", Plug_Net_Close, 0); + Plug_RegisterBuiltin("FS_Seek", Plug_FS_Seek, 0); - Plug_RegisterBuiltin("memset", Plug_memset, 0); - Plug_RegisterBuiltin("memcpy", Plug_memcpy, 0); - Plug_RegisterBuiltin("memmove", Plug_memmove, 0); - Plug_RegisterBuiltin("sqrt", Plug_sqrt, 0); - Plug_RegisterBuiltin("sin", Plug_sin, 0); - Plug_RegisterBuiltin("cos", Plug_cos, 0); - Plug_RegisterBuiltin("atan2", Plug_atan2, 0); + Plug_RegisterBuiltin("memset", Plug_memset, 0); + Plug_RegisterBuiltin("memcpy", Plug_memcpy, 0); + Plug_RegisterBuiltin("memmove", Plug_memmove, 0); + Plug_RegisterBuiltin("sqrt", Plug_sqrt, 0); + Plug_RegisterBuiltin("sin", Plug_sin, 0); + Plug_RegisterBuiltin("cos", Plug_cos, 0); + Plug_RegisterBuiltin("atan2", Plug_atan2, 0); - Plug_RegisterBuiltin("ReadInputBuffer", Plug_ReadInputBuffer, 0); - Plug_RegisterBuiltin("UpdateInputBuffer", Plug_UpdateInputBuffer, 0); + Plug_RegisterBuiltin("ReadInputBuffer", Plug_ReadInputBuffer, 0); + Plug_RegisterBuiltin("UpdateInputBuffer", Plug_UpdateInputBuffer, 0); - Plug_Client_Init(); + Plug_Client_Init(); + } - if (plug_loaddefault.value) + if (!fromgamedir) { -#ifdef _WIN32 - COM_EnumerateFiles("plugins/*x86.dll", Plug_Emumerated, "x86.dll"); -#elif defined(__linux__) - COM_EnumerateFiles("plugins/*x86.so", Plug_Emumerated, "x86.so"); -#endif - COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm"); + FS_NativePath("", FS_BINARYPATH, nat, sizeof(nat)); + Sys_EnumerateFiles(nat, "fteplug_*"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_EnumeratedRoot, NULL, NULL); + } + if (fromgamedir) + { + if (plug_loaddefault.value) + { + COM_EnumerateFiles("plugins/*"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, Plug_Emumerated, ARCH_CPU_POSTFIX ARCH_DL_POSTFIX); + COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm"); + } } } @@ -1763,6 +1805,7 @@ void Plug_Close(plugin_t *plug) Media_UnregisterDecoder(plug, NULL); Media_UnregisterEncoder(plug, NULL); #endif + FS_UnRegisterFileSystemModule(plug); if (plug->shutdown) VM_Call(plug->vm, plug->shutdown); VM_Destroy(plug->vm); @@ -1841,7 +1884,6 @@ void Plug_List_f(void) plugin_t *plug; for (plug = plugs; plug; plug = plug->next) { - Con_Printf("%s - \n", plug->name); VM_PrintInfo(plug->vm); } } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index ee5bac81a..a4473eea8 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -8,6 +8,8 @@ #include +#define VMUTF8 0 + static char *cvargroup_progs = "Progs variables"; cvar_t pr_brokenfloatconvert = SCVAR("pr_brokenfloatconvert", "0"); @@ -16,34 +18,8 @@ cvar_t pr_tempstringsize = SCVAR("pr_tempstringsize", "4096"); cvar_t pr_enable_uriget = SCVAR("pr_enable_uriget", "1"); int tokenizeqc(char *str, qboolean dpfuckage); -static char *strtoupper(char *s) -{ - char *p; - - p = s; - while(*p) - { - *p = toupper(*p); - p++; - } - - return s; -} - -static char *strtolower(char *s) -{ - char *p; - - p = s; - while(*p) - { - *p = tolower(*p); - p++; - } - - return s; -} - +void skel_info_f(void); +void skel_generateragdoll_f(void); void PF_Common_RegisterCvars(void) { Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs); @@ -51,6 +27,9 @@ void PF_Common_RegisterCvars(void) Cvar_Register (&pr_tempstringsize, cvargroup_progs); Cvar_Register (&pr_enable_uriget, cvargroup_progs); + Cmd_AddCommand("skel_info", skel_info_f); + Cmd_AddCommand("skel_generateragdoll", skel_generateragdoll_f); + WPhys_Init(); } @@ -83,6 +62,7 @@ char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_g } return out; } +//tag warnings/errors for easier debugging. int PR_Printf (const char *fmt, ...) { va_list argptr; @@ -953,7 +933,9 @@ void QCBUILTIN PF_registercvar (pubprogfuncs_t *prinst, struct globalvars_s *pr_ //memory stuff void QCBUILTIN PF_memalloc (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - void *ptr = prinst->AddressableAlloc(prinst, G_INT(OFS_PARM0)); + int size = G_INT(OFS_PARM0); + void *ptr = prinst->AddressableAlloc(prinst, size); + memset(ptr, 0, size); G_INT(OFS_RETURN) = (char*)ptr - prinst->stringtable; } void QCBUILTIN PF_memfree (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -977,7 +959,7 @@ void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_global } memcpy(prinst->stringtable + dst, prinst->stringtable + src, size); } -void QCBUILTIN PF_memset (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_memfill8 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int dst = G_INT(OFS_PARM0); int val = G_INT(OFS_PARM1); @@ -989,8 +971,177 @@ void QCBUILTIN PF_memset (pubprogfuncs_t *prinst, struct globalvars_s *pr_global } memset(prinst->stringtable + dst, val, size); } + +void QCBUILTIN PF_memgetval (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + //read 32 bits from a pointer. + int dst = G_INT(OFS_PARM0); + float ofs = G_FLOAT(OFS_PARM1); + int size = 4; + if (ofs != (float)(int)ofs) + PR_BIError(prinst, "PF_memgetval: non-integer offset\n"); + dst += ofs; + if (dst & 3 || dst < 0 || dst+size >= prinst->stringtablesize) + { + PR_BIError(prinst, "PF_memgetval: invalid dest\n"); + return; + } + G_INT(OFS_RETURN) = *(int*)(prinst->stringtable + dst); +} + +void QCBUILTIN PF_memsetval (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + //write 32 bits to a pointer. + int dst = G_INT(OFS_PARM0); + float ofs = G_FLOAT(OFS_PARM1); + int val = G_INT(OFS_PARM2); + int size = 4; + if (ofs != (float)(int)ofs) + PR_BIError(prinst, "PF_memsetval: non-integer offset\n"); + dst += ofs; + if (dst & 3 || dst < 0 || dst+size >= prinst->stringtablesize) + { + PR_BIError(prinst, "PF_memsetval: invalid dest\n"); + return; + } + *(int*)(prinst->stringtable + dst) = val; +} + +void QCBUILTIN PF_memptradd (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + //convienience function. needed for: ptr = &ptr[5]; or ptr += 5; + int dst = G_INT(OFS_PARM0); + float ofs = G_FLOAT(OFS_PARM1); + if (ofs != (float)(int)ofs) + PR_BIError(prinst, "PF_memptradd: non-integer offset\n"); + if ((int)ofs & 3) + PR_BIError(prinst, "PF_memptradd: offset is not 32-bit aligned.\n"); //means pointers can internally be expressed as 16.16 with 18-bit segments/allocations. + + G_INT(OFS_RETURN) = dst + ofs; +} //memory stuff //////////////////////////////////////////////////// +//hash table stuff +#define MAX_QC_HASHTABLES 256 + +#define FIRST_QC_HASHTABLE_INDEX 1 + +typedef struct +{ + pubprogfuncs_t *prinst; + hashtable_t tab; + void *bucketmem; +} pf_hashtab_t; +typedef struct +{ + bucket_t buck; + char *name; + vec3_t data; +} pf_hashentry_t; +pf_hashtab_t pf_hashtab[MAX_QC_HASHTABLES]; + +void QCBUILTIN PF_hash_getkey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int tab = G_FLOAT(OFS_PARM0) - FIRST_QC_HASHTABLE_INDEX; + int idx = G_FLOAT(OFS_PARM1); + pf_hashentry_t *ent = NULL; + G_INT(OFS_RETURN) = 0; + if (tab >= 0 && tab < MAX_QC_HASHTABLES && pf_hashtab[tab].prinst) + { + ent = Hash_GetIdx(&pf_hashtab[tab].tab, idx); + if (ent) + RETURN_TSTRING(ent->name); + } +} +void QCBUILTIN PF_hash_delete (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int tab = G_FLOAT(OFS_PARM0) - FIRST_QC_HASHTABLE_INDEX; + char *name = PR_GetStringOfs(prinst, OFS_PARM1); + pf_hashentry_t *ent = NULL; + memset(G_VECTOR(OFS_RETURN), 0, sizeof(vec3_t)); + if (tab >= 0 && tab < MAX_QC_HASHTABLES && pf_hashtab[tab].prinst) + { + ent = Hash_Get(&pf_hashtab[tab].tab, name); + if (ent) + { + memcpy(G_VECTOR(OFS_RETURN), ent->data, sizeof(vec3_t)); + Hash_RemoveData(&pf_hashtab[tab].tab, name, ent); + BZ_Free(ent); + } + } + else + PR_BIError(prinst, "PF_hash_get: invalid hash table\n"); +} +void QCBUILTIN PF_hash_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int tab = G_FLOAT(OFS_PARM0) - FIRST_QC_HASHTABLE_INDEX; + char *name = PR_GetStringOfs(prinst, OFS_PARM1); + pf_hashentry_t *ent = NULL; + if (tab >= 0 && tab < MAX_QC_HASHTABLES && pf_hashtab[tab].prinst) + ent = Hash_Get(&pf_hashtab[tab].tab, name); + else + PR_BIError(prinst, "PF_hash_get: invalid hash table\n"); + if (ent) + memcpy(G_VECTOR(OFS_RETURN), ent->data, sizeof(vec3_t)); + else + memcpy(G_VECTOR(OFS_RETURN), G_VECTOR(OFS_PARM2), sizeof(vec3_t)); +} +void QCBUILTIN PF_hash_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int tab = G_FLOAT(OFS_PARM0) - FIRST_QC_HASHTABLE_INDEX; + char *name = PR_GetStringOfs(prinst, OFS_PARM1); + void *data = G_VECTOR(OFS_PARM2); + pf_hashentry_t *ent = NULL; + if (tab >= 0 && tab < MAX_QC_HASHTABLES && pf_hashtab[tab].prinst) + { + int nlen = strlen(name); + ent = BZ_Malloc(sizeof(*ent) + nlen + 1); + ent->name = (char*)(ent+1); + memcpy(ent->name, name, nlen+1); + memcpy(ent->data, data, sizeof(vec3_t)); + Hash_Add(&pf_hashtab[tab].tab, ent->name, ent, &ent->buck); + } + else + PR_BIError(prinst, "PF_hash_add: invalid hash table\n"); +} +static void PF_hash_destroytab_enum(void *ctx, void *ent) +{ + BZ_Free(ent); +} +void QCBUILTIN PF_hash_destroytab (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int tab = G_FLOAT(OFS_PARM0) - FIRST_QC_HASHTABLE_INDEX; + pf_hashentry_t *ent = NULL; + if (tab >= 0 && tab < MAX_QC_HASHTABLES && pf_hashtab[tab].prinst) + { + pf_hashtab[tab].prinst = NULL; + Hash_Enumerate(&pf_hashtab[tab].tab, PF_hash_destroytab_enum, NULL); + Z_Free(pf_hashtab[tab].bucketmem); + } +} +void QCBUILTIN PF_hash_createtab (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + int numbuckets = G_FLOAT(OFS_PARM0); + if (numbuckets < 4) + numbuckets = 64; + for (i = 0; i < MAX_QC_HASHTABLES; i++) + { + if (!pf_hashtab[i].prinst) + { + pf_hashtab[i].prinst = prinst; + pf_hashtab[i].bucketmem = Z_Malloc(Hash_BytesForBuckets(numbuckets)); + Hash_InitTable(&pf_hashtab[i].tab, numbuckets, pf_hashtab[i].bucketmem); + G_FLOAT(OFS_RETURN) = i + FIRST_QC_HASHTABLE_INDEX; + return; + } + } + G_FLOAT(OFS_RETURN) = 0; + return; +} + +//hash table stuff +//////////////////////////////////////////////////// //File access #define MAX_QC_FILES 256 @@ -1234,9 +1385,19 @@ void QCBUILTIN PF_fgets (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals if (c == '\r' && pf_fopen_files[fnum].accessmode != FRIK_FILE_READNL) continue; - if (o == max) - break; - *o++ = c; + if (c == 0) + { //modified utf-8, woo. but don't double-encode other chars. + if (o+1 >= max) + break; + *o++ = 0xc0; + *o++ = 0x80; + } + else + { + if (o == max) + break; + *o++ = c; + } } *o = '\0'; @@ -1275,6 +1436,7 @@ static void PF_fwrite (pubprogfuncs_t *prinst, int fnum, char *msg, int len) break; case FRIK_FILE_APPEND: case FRIK_FILE_WRITE: + //UTF-8-FIXME: de-modify utf-8 if (pf_fopen_files[fnum].bufferlen < pf_fopen_files[fnum].ofs + len) { char *newbuf; @@ -1426,7 +1588,7 @@ void search_close_progs(pubprogfuncs_t *prinst, qboolean complain) prvm_nextsearchhandle = 0; //might as well. } -int search_enumerate(const char *name, int fsize, void *parm, struct searchpath_s *spath) +int QDECL search_enumerate(const char *name, int fsize, void *parm, struct searchpath_s *spath) { prvmsearch_t *s = parm; @@ -1717,9 +1879,18 @@ void QCBUILTIN PF_strncasecmp (pubprogfuncs_t *prinst, struct globalvars_s *pr_g { char *a = PR_GetStringOfs(prinst, OFS_PARM0); char *b = PR_GetStringOfs(prinst, OFS_PARM1); - float len = G_FLOAT(OFS_PARM2); + int len = G_FLOAT(OFS_PARM2); + int aofs = prinst->callargc>3?G_FLOAT(OFS_PARM3):0; - G_FLOAT(OFS_RETURN) = strnicmp(a, b, len); + if (VMUTF8) + { + aofs = unicode_byteofsfromcharofs(a, aofs); + len = unicode_byteofsfromcharofs(b, len); + } + else if (aofs < 0 || (aofs && aofs > strlen(a))) + aofs = strlen(a); + + G_FLOAT(OFS_RETURN) = strnicmp(a+aofs, b, len); } //FTE_STRINGS @@ -1738,9 +1909,18 @@ void QCBUILTIN PF_strncmp (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa { char *a = PR_GetStringOfs(prinst, OFS_PARM0); char *b = PR_GetStringOfs(prinst, OFS_PARM1); - float len = G_FLOAT(OFS_PARM2); + int len = G_FLOAT(OFS_PARM2); + int aofs = prinst->callargc>3?G_FLOAT(OFS_PARM3):0; - G_FLOAT(OFS_RETURN) = strncmp(a, b, len); + if (VMUTF8) + { + aofs = unicode_byteofsfromcharofs(a, aofs); + len = unicode_byteofsfromcharofs(b, len); + } + else if (aofs < 0 || (aofs && aofs > strlen(a))) + aofs = strlen(a); + + G_FLOAT(OFS_RETURN) = strncmp(a + aofs, b, len); } //uses qw style \key\value strings @@ -1777,6 +1957,8 @@ void QCBUILTIN PF_strpad (pubprogfuncs_t *prinst, struct globalvars_s *pr_global int pad = G_FLOAT(OFS_PARM0); char *src = PF_VarString(prinst, 1, pr_globals); + //UTF-8-FIXME: pad is chars not bytes... + if (pad < 0) { //pad left pad = -pad - strlen(src); @@ -1906,6 +2088,8 @@ void QCBUILTIN PF_strconv (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa unsigned char resbuf[8192]; unsigned char *result = resbuf; + //UTF-8-FIXME: cope with utf+^U etc + if (len >= MAXTEMPBUFFERLEN) len = MAXTEMPBUFFERLEN-1; @@ -1946,11 +2130,18 @@ void QCBUILTIN PF_strconv (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa void QCBUILTIN PF_chr2str (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int i; - - char string[16]; - for (i = 0; i < prinst->callargc; i++) - string[i] = G_FLOAT(OFS_PARM0 + i*3); - string[i] = '\0'; + char string[128], *s = string; + if (VMUTF8) + { + for (i = 0; i < prinst->callargc; i++) + s += unicode_encode(s, G_FLOAT(OFS_PARM0 + i*3), (string+sizeof(string)-1)-s); + } + else + { + for (i = 0; i < prinst->callargc; i++) + *s++ = G_FLOAT(OFS_PARM0 + i*3); + } + *s++ = '\0'; RETURN_TSTRING(string); } @@ -1961,13 +2152,22 @@ void QCBUILTIN PF_str2chr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa char *instr = PR_GetStringOfs(prinst, OFS_PARM0); int ofs = (prinst->callargc>1)?G_FLOAT(OFS_PARM1):0; - if (ofs < 0) - ofs = strlen(instr)+ofs; + if (VMUTF8) + { + if (ofs < 0) + ofs = unicode_charcount(instr, ~0)+ofs; + ofs = unicode_byteofsfromcharofs(instr, ofs); + } + else + { + if (ofs < 0) + ofs = strlen(instr)+ofs; + } if (ofs && (ofs < 0 || ofs > strlen(instr))) G_FLOAT(OFS_RETURN) = '\0'; else - G_FLOAT(OFS_RETURN) = instr[ofs]; + G_FLOAT(OFS_RETURN) = VMUTF8?unicode_decode(NULL, instr+ofs, NULL):instr[ofs]; } //FTE_STRINGS @@ -1979,6 +2179,9 @@ void QCBUILTIN PF_strstrofs (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo int firstofs = (prinst->callargc>2)?G_FLOAT(OFS_PARM2):0; + if (VMUTF8) + firstofs = unicode_byteofsfromcharofs(instr, firstofs); + if (firstofs && (firstofs < 0 || firstofs > strlen(instr))) { G_FLOAT(OFS_RETURN) = -1; @@ -1989,7 +2192,7 @@ void QCBUILTIN PF_strstrofs (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo if (!match) G_FLOAT(OFS_RETURN) = -1; else - G_FLOAT(OFS_RETURN) = match - instr; + G_FLOAT(OFS_RETURN) = VMUTF8?unicode_charofsfrombyteofs(instr, match-instr):(match - instr); } //float(string input) stof @@ -2168,7 +2371,12 @@ void QCBUILTIN PF_substring (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo start = G_FLOAT(OFS_PARM1); length = G_FLOAT(OFS_PARM2); - slen = strlen(s); + //UTF-8-FIXME: start+length are chars not bytes... + + if (VMUTF8) + slen = unicode_charcount(s, ~0); + else + slen = strlen(s); if (start < 0) start = slen+start; @@ -2186,12 +2394,17 @@ void QCBUILTIN PF_substring (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo return; } - s += start; slen -= start; - if (length > slen) length = slen; + if (VMUTF8) + { + start = unicode_byteofsfromcharofs(s, start); + length = unicode_byteofsfromcharofs(s+start, length); + } + s += start; + ((int *)pr_globals)[OFS_RETURN] = prinst->AllocTempString(prinst, &string, length+1); memcpy(string, s, length); @@ -2200,7 +2413,10 @@ void QCBUILTIN PF_substring (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo void QCBUILTIN PF_strlen(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - G_FLOAT(OFS_RETURN) = strlen(PR_GetStringOfs(prinst, OFS_PARM0)); + if (VMUTF8) + G_FLOAT(OFS_RETURN) = unicode_charcount(PR_GetStringOfs(prinst, OFS_PARM0), ~0); + else + G_FLOAT(OFS_RETURN) = strlen(PR_GetStringOfs(prinst, OFS_PARM0)); } //float(string input, string token) instr @@ -2270,6 +2486,7 @@ void QCBUILTIN PF_strireplace (pubprogfuncs_t *prinst, struct globalvars_s *pr_g { while (*subject && result < resultbuf + sizeof(resultbuf) - replacelen - 2) { + //UTF-8-FIXME: case insensitivity is awkward... if (!strnicmp(subject, search, searchlen)) { subject += searchlen; @@ -2329,8 +2546,7 @@ void QCBUILTIN PF_strtolower (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl char *in = PR_GetStringOfs(prinst, OFS_PARM0); char result[8192]; - Q_strncpyz(result, in, sizeof(result)); - strtolower(result); + unicode_strtolower(in, result, sizeof(result)); RETURN_TSTRING(result); } @@ -2341,8 +2557,7 @@ void QCBUILTIN PF_strtoupper (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl char *in = PR_GetStringOfs(prinst, OFS_PARM0); char result[8192]; - Q_strncpyz(result, in, sizeof(result)); - strtoupper(result); + unicode_strtoupper(in, result, sizeof(result)); RETURN_TSTRING(result); } @@ -2352,6 +2567,7 @@ void QCBUILTIN PF_strftime (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob { char *in = PF_VarString(prinst, 1, pr_globals); char result[8192]; + char uresult[8192]; time_t ctime; struct tm *tm; @@ -2363,9 +2579,9 @@ void QCBUILTIN PF_strftime (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob else tm = gmtime(&ctime); strftime(result, sizeof(result), in, tm); - strtoupper(result); + unicode_strtoupper(result, uresult, sizeof(uresult)); - RETURN_TSTRING(result); + RETURN_TSTRING(uresult); } //String functions @@ -2840,7 +3056,7 @@ void QCBUILTIN PF_netaddress_resolve(pubprogfuncs_t *prinst, struct globalvars_s netadr_t adr; char result[256]; if (NET_StringToAdr(address, defaultport, &adr)) - RETURN_TSTRING(NET_AdrToString (result, sizeof(result), adr)); + RETURN_TSTRING(NET_AdrToString (result, sizeof(result), &adr)); else RETURN_TSTRING(""); } @@ -3731,13 +3947,23 @@ noflags: nolength: // now s points to the final directive char and is no longer changed - if(isfloat < 0) + if (*s == 'p' || *s == 'P') { - if(*s == 'i') - isfloat = 0; - else - isfloat = 1; + //%p is slightly different from %x. + //always 8-bytes wide with 0 padding, always ints. + flags |= PRINTF_ZEROPAD; + if (width < 0) width = 8; + if (isfloat < 0) isfloat = 0; } + else if (*s == 'i') + { + //%i defaults to ints, not floats. + if(isfloat < 0) isfloat = 0; + } + + //assume floats, not ints. + if(isfloat < 0) + isfloat = 1; if(thisarg < 0) thisarg = argpos++; @@ -3757,7 +3983,12 @@ nolength: *f++ = '.'; *f++ = '*'; } - *f++ = *s; + if (*s == 'p') + *f++ = 'x'; + else if (*s == 'P') + *f++ = 'X'; + else + *f++ = *s; *f++ = 0; if(width < 0) // not set @@ -3772,7 +4003,7 @@ nolength: Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg))); o += strlen(o); break; - case 'o': case 'u': case 'x': case 'X': + case 'o': case 'u': case 'x': case 'X': case 'p': case 'P': if(precision < 0) // not set Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg))); else @@ -3803,6 +4034,7 @@ nolength: o += strlen(o); break; case 'c': + //UTF-8-FIXME: figure it out yourself // if(flags & PRINTF_ALTERNATE) { if(precision < 0) // not set @@ -3824,6 +4056,7 @@ nolength: } */ break; case 's': + //UTF-8-FIXME: figure it out yourself // if(flags & PRINTF_ALTERNATE) { if(precision < 0) // not set @@ -4220,7 +4453,7 @@ lh_extension_t QSG_Extensions[] = { {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, {"FTE_GFX_QUAKE3SHADERS"}, {"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}}, - {"FTE_MEMALLOC", 4, NULL, {"memalloc", "memfree", "memcpy", "memset"}}, + {"FTE_MEMALLOC", 4, NULL, {"memalloc", "memfree", "memcpy", "memfill8"}}, #ifndef NOMEDIA {"FTE_MEDIA_AVI"}, //playfilm supports avi files. {"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files. @@ -4235,7 +4468,8 @@ lh_extension_t QSG_Extensions[] = { {"FTE_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested. #endif {"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}}, - {"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}}, + {"FTE_QC_HASHTABLES", 6, NULL, {"hash_createtab", "hash_destroytab", "hash_add", "hash_get", "hash_delete", "hash_getkey"}}, + {"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}}, {"FTE_QC_PAUSED"}, {"FTE_QC_INTCONV", 4, NULL, {"stoi", "itos", "stoh", "htos"}}, {"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}}, //includes the SV_ParseConnectionlessPacket event. diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 3e7226a48..e010faaf6 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -84,8 +84,8 @@ char *PF_TempStr(pubprogfuncs_t *prinst); //returns a tempstring which can be fi extern cvar_t pr_tempstringsize; extern cvar_t pr_tempstringcount; -int MP_TranslateFTEtoDPCodes(int code); -int MP_TranslateDPtoFTECodes(int code); +int MP_TranslateFTEtoQCCodes(int code); +int MP_TranslateQCtoFTECodes(int code); //pr_cmds.c builtins that need to be moved to a common. void VARGS PR_BIError(pubprogfuncs_t *progfuncs, char *format, ...) LIKEPRINTF(2); @@ -379,10 +379,20 @@ void QCBUILTIN PF_bufstr_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_g void QCBUILTIN PF_bufstr_free (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_buf_cvarlist (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); -void QCBUILTIN PF_memalloc (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); -void QCBUILTIN PF_memfree (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); -void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); -void QCBUILTIN PF_memset (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_hash_createtab (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_hash_destroytab (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_hash_add (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_hash_get (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_hash_delete (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_hash_getkey (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); + +void QCBUILTIN PF_memalloc (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_memfree (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_memfill8 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_memgetval (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_memsetval (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_memptradd (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_soundlength (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_calltimeofday (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/common/q3common.c b/engine/common/q3common.c index bf24277d9..bc0171638 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(const char *match, int size, void *args, void *spath) +static int QDECL VMEnum(const char *match, int size, void *args, void *spath) { char *check; int newlen; @@ -210,13 +210,13 @@ static int VMEnum(const char *match, int size, void *args, void *spath) return true; } -static int IfFound(const char *match, int size, void *args, void *spath) +static int QDECL IfFound(const char *match, int size, void *args, void *spath) { *(qboolean*)args = true; return true; } -static int VMEnumMods(const char *match, int size, void *args, void *spath) +static int QDECL VMEnumMods(const char *match, int size, void *args, void *spath) { char *check; char desc[1024]; @@ -312,7 +312,7 @@ int VM_GetFileList(char *path, char *ext, char *output, int buffersize) #define MAX_VMQ3_CVARS 256 //can be blindly increased cvar_t *q3cvlist[MAX_VMQ3_CVARS]; -int VMQ3_Cvar_Register(vmcvar_t *v, char *name, char *defval, int flags) +int VMQ3_Cvar_Register(q3vmcvar_t *v, char *name, char *defval, int flags) { int i; int fteflags = 0; @@ -343,7 +343,7 @@ int VMQ3_Cvar_Register(vmcvar_t *v, char *name, char *defval, int flags) return 0; } -int VMQ3_Cvar_Update(vmcvar_t *v) +int VMQ3_Cvar_Update(q3vmcvar_t *v) { cvar_t *c; int i; @@ -597,7 +597,7 @@ qboolean Netchan_ProcessQ3 (netchan_t *chan) if (chan->drop_count > 0)// && (net_showdrop->integer || net_showpackets->integer)) { - Con_DPrintf("%s:Dropped %i packets at %i\n", NET_AdrToString(adr, sizeof(adr), chan->remote_address), chan->drop_count, sequence); + Con_DPrintf("%s:Dropped %i packets at %i\n", NET_AdrToString(adr, sizeof(adr), &chan->remote_address), chan->drop_count, sequence); } if (!fragment) @@ -619,7 +619,7 @@ qboolean Netchan_ProcessQ3 (netchan_t *chan) { // if(net_showdrop->integer || net_showpackets->integer) { - Con_Printf("%s:Dropped a message fragment\n", NET_AdrToString(adr, sizeof(adr), chan->remote_address)); + Con_Printf("%s:Dropped a message fragment\n", NET_AdrToString(adr, sizeof(adr), &chan->remote_address)); } return false; } @@ -646,7 +646,7 @@ qboolean Netchan_ProcessQ3 (netchan_t *chan) // Check if assembled message fits in buffer if (chan->in_fragment_length > net_message.maxsize) { - Con_Printf("%s:fragmentLength %i > net_message.maxsize\n", NET_AdrToString(adr, sizeof(adr), chan->remote_address), chan->in_fragment_length); + Con_Printf("%s:fragmentLength %i > net_message.maxsize\n", NET_AdrToString(adr, sizeof(adr), &chan->remote_address), chan->in_fragment_length); return false; } @@ -711,7 +711,7 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) SZ_Write( &send, chan->reliable_buf + chan->reliable_start, fragmentLength ); // Send the datagram - NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address ); + NET_SendPacket( chan->sock, send.cursize, send.data, &chan->remote_address ); // if( net_showpackets->integer ) // { @@ -750,7 +750,7 @@ void Netchan_TransmitQ3( netchan_t *chan, int length, const qbyte *data ) // Check for message overflow if( length > MAX_OVERALLMSGLEN ) { - Con_Printf( "%s: outgoing message overflow\n", NET_AdrToString( adr, sizeof(adr), chan->remote_address ) ); + Con_Printf( "%s: outgoing message overflow\n", NET_AdrToString( adr, sizeof(adr), &chan->remote_address ) ); return; } @@ -765,7 +765,7 @@ void Netchan_TransmitQ3( netchan_t *chan, int length, const qbyte *data ) Netchan_TransmitNextFragment( chan ); if( chan->reliable_length ) { - Con_Printf( "%s: unsent fragments\n", NET_AdrToString( adr, sizeof(adr), chan->remote_address ) ); + Con_Printf( "%s: unsent fragments\n", NET_AdrToString( adr, sizeof(adr), &chan->remote_address ) ); return; } /*drop the outgoing packet if we fragmented*/ @@ -800,7 +800,7 @@ void Netchan_TransmitQ3( netchan_t *chan, int length, const qbyte *data ) SZ_Write( &send, data, length ); // Send the datagram - NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address ); + NET_SendPacket( chan->sock, send.cursize, send.data, &chan->remote_address ); /* if( net_showpackets->integer ) { diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 931bc9be6..ab802fe47 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -66,7 +66,8 @@ struct vm_s { qintptr_t (EXPORT_FN *vmMain)(qintptr_t command, qintptr_t arg0, qintptr_t arg1, qintptr_t arg2, qintptr_t arg3, qintptr_t arg4, qintptr_t arg5, qintptr_t arg6); }; -dllhandle_t *QVM_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall) +//plugins come from the quake root dir, not game dirs. +dllhandle_t *QVM_LoadDLL(const char *name, qboolean binroot, void **vmMain, sys_calldll_t syscall) { void (EXPORT_FN *dllEntry)(sys_calldll_t syscall); char dllname_arch[MAX_OSPATH]; //id compatible @@ -80,54 +81,44 @@ dllhandle_t *QVM_LoadDLL(const char *name, void **vmMain, sys_calldll_t syscall) {NULL, NULL}, }; -#ifdef _WIN32 - snprintf(dllname_arch, sizeof(dllname_arch), "%sx86.dll", name); - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.dll", name); -#elif defined(__amd64__) - snprintf(dllname_arch, sizeof(dllname_arch), "%samd.so", name); - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.so", name); -#elif defined(_M_IX86) || defined(__i386__) - snprintf(dllname_arch, sizeof(dllname_arch), "%sx86.so", name); - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.so", name); -#elif defined(__powerpc__) - snprintf(dllname_arch, sizeof(dllname_arch), "%sppc.so", name); - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.so", name); -#elif defined(__ppc__) - snprintf(dllname_arch, sizeof(dllname_arch), "%sppc.so", name); - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.so", name); -#else - snprintf(dllname_arch, sizeof(dllname_arch), "%sunk.so", name); - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s.so", name); -#endif + snprintf(dllname_arch, sizeof(dllname_arch), "%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name); + snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s" ARCH_DL_POSTFIX, name); hVM=NULL; { char fname[MAX_OSPATH]; char *gpath; - // run through the search paths - gpath = NULL; - while (1) + + if (binroot) { - gpath = COM_NextPath (gpath); - if (!gpath) - return NULL; // couldn't find one anywhere - - snprintf (fname, sizeof(fname), "%s/%s", gpath, dllname_arch); - - Con_DPrintf("Loading native: %s\n", fname); - hVM = Sys_LoadLibrary(fname, funcs); - if (hVM) + if (!hVM && FS_NativePath(dllname_arch, FS_BINARYPATH, fname, sizeof(fname))) + hVM = Sys_LoadLibrary(fname, funcs); + if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname))) + hVM = Sys_LoadLibrary(fname, funcs); + } + else + { + // run through the search paths + gpath = NULL; + while (!hVM) { - break; - } + gpath = COM_NextPath (gpath); + if (!gpath) + break; // couldn't find one anywhere - snprintf (fname, sizeof(fname), "%s/%s", gpath, dllname_anycpu); + if (!hVM) + { + snprintf (fname, sizeof(fname), "%s/%s", gpath, dllname_arch); + Con_DPrintf("Loading native: %s\n", fname); + hVM = Sys_LoadLibrary(fname, funcs); + } - Con_DPrintf("Loading native: %s\n", fname); - hVM = Sys_LoadLibrary(fname, funcs); - if (hVM) - { - break; + if (!hVM) + { + snprintf (fname, sizeof(fname), "%s/%s", gpath, dllname_anycpu); + Con_DPrintf("Loading native: %s\n", fname); + hVM = Sys_LoadLibrary(fname, funcs); + } } } } @@ -909,8 +900,6 @@ void VM_PrintInfo(vm_t *vm) { qvm_t *qvm; - if(!vm->name[0]) - return; Con_Printf("%s (%p): ", vm->name, vm->hInst); switch(vm->type) @@ -958,7 +947,7 @@ vm_t *VM_Create(vm_t *vm, const char *name, sys_calldll_t syscalldll, sys_callqv { if (!COM_CheckParm("-nodlls") && !COM_CheckParm("-nosos")) //:) { - if((vm->hInst=QVM_LoadDLL(name, (void**)&vm->vmMain, syscalldll))) + if((vm->hInst=QVM_LoadDLL(name, !syscallqvm, (void**)&vm->vmMain, syscalldll))) { Con_DPrintf("Creating native machine \"%s\"\n", name); vm->type=VM_NATIVE; diff --git a/engine/common/sys.h b/engine/common/sys.h index 79b6a0db8..2df3757e2 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -62,6 +62,8 @@ qboolean LibZ_Init(void); qboolean LibJPEG_Init(void); qboolean LibPNG_Init(void); +void Sys_RunFile(const char *fname, int nlen); + unsigned int Sys_Milliseconds (void); double Sys_DoubleTime (void); qboolean Sys_RandomBytes(qbyte *string, int len); @@ -83,13 +85,17 @@ void Sys_ServerActivity(void); void Sys_SendKeyEvents (void); // Perform Key_Event () callbacks until the input que is empty -int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath); +int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath); void Sys_Vibrate(int count); qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate); #ifdef MULTITHREAD +#if defined(_WIN32) && defined(_DEBUG) +void Sys_SetThreadName(unsigned int dwThreadID, char *threadName); +#endif + void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize); void Sys_WaitOnThread(void *thread); void Sys_DetachThread(void *thread); diff --git a/engine/common/sys_win_threads.c b/engine/common/sys_win_threads.c index afda8c44e..0e54e1c2a 100644 --- a/engine/common/sys_win_threads.c +++ b/engine/common/sys_win_threads.c @@ -63,7 +63,7 @@ typedef struct tagTHREADNAME_INFO DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) -void SetThreadName(DWORD dwThreadID, char *threadName) +void Sys_SetThreadName(unsigned int dwThreadID, char *threadName) { THREADNAME_INFO info; info.dwType = 0x1000; @@ -105,7 +105,7 @@ void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority } #ifdef _DEBUG - SetThreadName(tid, name); + Sys_SetThreadName(tid, name); #endif return (void *)handle; diff --git a/engine/common/vm.h b/engine/common/vm.h index 028d6e00b..30055951d 100644 --- a/engine/common/vm.h +++ b/engine/common/vm.h @@ -70,7 +70,7 @@ qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags); void Plug_Command_f(void); int Plug_ConnectionlessClientPacket(char *buffer, int size); void Plug_DrawReloadImages(void); -void Plug_Init(void); +void Plug_Initialise(qboolean fromgamedir); void Plug_Shutdown(void); qboolean Plug_Menu_Event(int eventtype, int param); void Plug_ResChanged(void); @@ -134,8 +134,8 @@ typedef struct { float value; int integer; char string[256]; -} vmcvar_t; -int VMQ3_Cvar_Register(vmcvar_t *v, char *name, char *defval, int flags); -int VMQ3_Cvar_Update(vmcvar_t *v); +} q3vmcvar_t; +int VMQ3_Cvar_Register(q3vmcvar_t *v, char *name, char *defval, int flags); +int VMQ3_Cvar_Update(q3vmcvar_t *v); #endif diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index c1ba3fca5..9f4f917fe 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -145,11 +145,10 @@ struct { int curvertexvbo; void *curvertexpointer; -#ifdef FTE_TARGET_WEB int streamvbo[64]; int streamebo[64]; + int streamvao[64]; int streamid; -#endif int pendingtexcoordparts[SHADER_TMU_MAX]; int pendingtexcoordvbo[SHADER_TMU_MAX]; @@ -673,7 +672,14 @@ static void BE_EnableShaderAttributes(unsigned int progattrmask, int usevao) if (shaderstate.currentvao) { bitstochange = shaderstate.sourcevbo->vaodynamic&progattrmask; +#if 0 bitstoendisable = 0; +#else + bitstoendisable = shaderstate.sourcevbo->vaoenabled^progattrmask; + if (bitstoendisable) + bitstochange |= bitstoendisable; + shaderstate.sourcevbo->vaoenabled = progattrmask; +#endif if (bitstochange & (1u<vao); - availbits = - (1u<vao; qglBindVertexArray(vbo->vao); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, shaderstate.sourcevbo->indicies.gl.vbo); - BE_ApplyAttributes(availbits, availbits); + BE_ApplyAttributes(vaostatic, vaodynamic|vaostatic); GL_SelectVBO(shaderstate.sourcevbo->coord.gl.vbo); + vbo->vaoenabled = vaodynamic|vaostatic; vbo->vaodynamic = vaodynamic; shaderstate.curvertexpointer = NULL; @@ -1262,7 +1259,14 @@ void GLBE_Init(void) shaderstate.curentity = &r_worldentity; be_maxpasses = gl_mtexarbable; gl_stencilbits = 0; - qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits); + if (gl_config.glversion >= 3.0 && gl_config.nofixedfunc) + { + //docs say this line should be okay in gl3+. nvidia do not seem to agree. GL_STENCIL_BITS is depricated however. so for now, just assume. + //qglGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER_EXT, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &gl_stencilbits); + gl_stencilbits = 8; + } + else + qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits); for (i = 0; i < FTABLE_SIZE; i++) { t = (double)i / (double)FTABLE_SIZE; @@ -1325,14 +1329,14 @@ void GLBE_Init(void) R_InitFlashblends(); -#ifdef FTE_TARGET_WEB //only do this where we have to. - if (qglBufferDataARB) + if (qglBufferDataARB && gl_config.nofixedfunc) { qglGenBuffersARB(sizeof(shaderstate.streamvbo)/sizeof(shaderstate.streamvbo[0]), shaderstate.streamvbo); qglGenBuffersARB(sizeof(shaderstate.streamebo)/sizeof(shaderstate.streamebo[0]), shaderstate.streamebo); + if (qglGenVertexArrays) + qglGenVertexArrays(sizeof(shaderstate.streamvao)/sizeof(shaderstate.streamvao[0]), shaderstate.streamvao); } -#endif } //end tables @@ -3683,13 +3687,14 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m) int i; *vbo = &shaderstate.dummyvbo; -#ifdef FTE_TARGET_WEB //this code is shit shit shit. if (shaderstate.streamvbo[0]) { //use a local. can't use a static, that crashes the compiler due to memory use, so lets eat the malloc or stack or whatever because we really don't have a choice. - char buffer[65536 * 33 * sizeof(float)]; + static char *buffer; int len = 0; + if (!buffer) + buffer = malloc(65536 * 33 * sizeof(float)); //we're not doing vao... but just in case someone added that as an extension... GL_DeselectVAO(); @@ -3702,6 +3707,14 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m) //but we really do not have a choice. This is the only way to 'stream' without dropping down to <1fps. //although arguably we should build our entire hud+2d stuff into a single vbo each frame... meh. At least this keeps the memory use in the driver's 64bit memory space instead of the browser's 32bit one... shaderstate.streamid = (shaderstate.streamid + 1) & (sizeof(shaderstate.streamvbo)/sizeof(shaderstate.streamvbo[0]) - 1); + shaderstate.dummyvbo.vao = shaderstate.streamvao[shaderstate.streamid]; + shaderstate.dummyvbo.vaodynamic = ~0; + shaderstate.dummyvbo.vaoenabled = 0; + if (shaderstate.dummyvbo.vao) + { + qglBindVertexArray(shaderstate.dummyvbo.vao); + shaderstate.currentvao = shaderstate.dummyvbo.vao; + } GL_SelectVBO(shaderstate.streamvbo[shaderstate.streamid]); GL_SelectEBO(shaderstate.streamebo[shaderstate.streamid]); @@ -3766,7 +3779,6 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m) shaderstate.dummyvbo.indicies.gl.vbo = shaderstate.streamebo[shaderstate.streamid]; } else -#endif { //client memory. may be slower. will probably be faster. shaderstate.dummyvbo.coord.gl.addr = m->xyz_array; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index b95dee372..02924dd0a 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -681,7 +681,7 @@ static hmsection_t *Terr_LoadSection(heightmap_t *hm, hmsection_t *s, int sx, in #endif diskimage = NULL; - len = FS_LoadFile(Terr_DiskSectionName(hm, sx, sy), (void**)&diskimage); + len = -1;//FS_LoadFile(Terr_DiskSectionName(hm, sx, sy), (void**)&diskimage); /*queue the file for download if we don't have it yet*/ if (len < 0) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 48dc6e004..7284cf5e7 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -2459,15 +2459,22 @@ static void RMod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxind int sortid; int sty; vbo_t vbo; - int styles = MAXLIGHTMAPS; + int styles = mod->lightmaps.surfstyles; vbo.indicies.dummy = Hunk_AllocName(sizeof(index_t) * maxindicies, "indexdata"); vbo.coord.dummy = Hunk_AllocName((sizeof(vecV_t)+sizeof(vec2_t)*(1+styles)+sizeof(vec3_t)*3+sizeof(vec4_t))* maxverts, "vertdata"); vbo.texcoord.dummy = (vecV_t*)vbo.coord.dummy + maxverts; - vbo.lmcoord[0].dummy = (vec2_t*)vbo.texcoord.dummy + maxverts; - for (sty = 1; sty < styles; sty++) + sty = 0; + if (styles) + { + vbo.lmcoord[0].dummy = (vec2_t*)vbo.texcoord.dummy + maxverts; + sty = 1; + } + for (; sty < styles; sty++) vbo.lmcoord[sty].dummy = (vec2_t*)vbo.lmcoord[sty-1].dummy + maxverts; - vbo.normals.dummy = (vec2_t*)vbo.lmcoord[styles-1].dummy + maxverts; + for (; sty < MAXLIGHTMAPS; sty++) + vbo.lmcoord[sty].dummy = NULL; + vbo.normals.dummy = styles?((vec2_t*)vbo.lmcoord[styles-1].dummy + maxverts):((vec2_t*)vbo.texcoord.dummy + maxverts); vbo.svector.dummy = (vec3_t*)vbo.normals.dummy + maxverts; vbo.tvector.dummy = (vec3_t*)vbo.svector.dummy + maxverts; vbo.colours.dummy = (vec3_t*)vbo.tvector.dummy + maxverts; @@ -2494,10 +2501,13 @@ static void RMod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxind //set up the arrays. the arrangement is required for the backend to optimise vbos mesh->xyz_array = (vecV_t*)vbo.coord.dummy + mesh->vbofirstvert; mesh->st_array = (vec2_t*)vbo.texcoord.dummy + mesh->vbofirstvert; - for (sty = 0; sty < styles; sty++) - mesh->lmst_array[sty] = (vec2_t*)vbo.lmcoord[sty].dummy + mesh->vbofirstvert; - for ( ; sty < MAXLIGHTMAPS; sty++) - mesh->lmst_array[sty] = NULL; + for (sty = 0; sty < MAXLIGHTMAPS; sty++) + { + if (vbo.lmcoord[sty].dummy) + mesh->lmst_array[sty] = (vec2_t*)vbo.lmcoord[sty].dummy + mesh->vbofirstvert; + else + mesh->lmst_array[sty] = NULL; + } mesh->normals_array = (vec3_t*)vbo.normals.dummy + mesh->vbofirstvert; mesh->snormals_array = (vec3_t*)vbo.svector.dummy + mesh->vbofirstvert; mesh->tnormals_array = (vec3_t*)vbo.tvector.dummy + mesh->vbofirstvert; @@ -2893,7 +2903,10 @@ void RMod_Batches_Build(mesh_t *meshlist, model_t *mod, void (*build)(model_t *m RMod_Batches_AllocLightmaps(mod); if (!build) + { build = RModQ1_Batches_BuildQ1Q2Poly; + mod->lightmaps.surfstyles = 1; + } RMod_Batches_BuildModelMeshes(mod, numverts, numindicies, build, buildcookie); if (BE_GenBrushModelVBO) @@ -4690,7 +4703,7 @@ typedef struct { short xpos; short ypos; } doomimage_t; -static int FindDoomSprites(const char *name, int size, void *param, void *spath) +static int QDECL FindDoomSprites(const char *name, int size, void *param, void *spath) { if (*(int *)param + strlen(name)+1 > 16000) Sys_Error("Too many doom sprites\n"); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index c2b970715..563b6c5b0 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -257,6 +257,7 @@ typedef struct vbo_s int vao; unsigned int vaodynamic; /*mask of the attributes that are dynamic*/ + unsigned int vaoenabled; /*mask of the attributes *currently* enabled. renderer may change this */ vboarray_t coord; vboarray_t coord2; vboarray_t texcoord; @@ -942,11 +943,12 @@ typedef struct model_s batch_t *batches[SHADER_SORT_COUNT]; struct { - int first; - int count; - int width; - int height; - qboolean deluxemapping; + int first; //once built... + int count; //num lightmaps + int width; //x size of lightmaps + int height; //y size of lightmaps + int surfstyles; //numbers of style per surface. + qboolean deluxemapping; //lightmaps are interleaved with deluxemap data (lightmap indicies should only be even values) } lightmaps; unsigned checksum; diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 60248d5a2..70b893ee6 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -57,12 +57,13 @@ void GLBE_ClearVBO(vbo_t *vbo) BZ_Free(vbo); } -void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic); +void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic, unsigned int vaostatic); static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int elementsize, unsigned int vaodynamic) { unsigned int vbos[2]; int s; + unsigned int vaostatic = 0; if (!qglGenBuffersARB) return false; @@ -75,16 +76,19 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int { vbo->indicies.gl.vbo = vbos[1]; vbo->indicies.gl.addr = (index_t*)((char*)vbo->indicies.gl.addr - (char*)edata); + vaostatic |= VATTR_LEG_ELEMENTS; } if (vbo->coord.gl.addr) { vbo->coord.gl.vbo = vbos[0]; vbo->coord.gl.addr = (vecV_t*)((char*)vbo->coord.gl.addr - (char*)vdata); + vaostatic |= VATTR_VERTEX1; } if (vbo->texcoord.gl.addr) { vbo->texcoord.gl.vbo = vbos[0]; vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata); + vaostatic |= VATTR_TEXCOORD; } for (s = 0; s < MAXLIGHTMAPS; s++) { @@ -92,30 +96,41 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int { vbo->lmcoord[s].gl.vbo = vbos[0]; vbo->lmcoord[s].gl.addr = (vec2_t*)((char*)vbo->lmcoord[s].gl.addr - (char*)vdata); + switch(s) + { + default: vaostatic |= VATTR_LMCOORD; break; + case 1: vaostatic |= VATTR_LMCOORD2; break; + case 2: vaostatic |= VATTR_LMCOORD3; break; + case 3: vaostatic |= VATTR_LMCOORD4; break; + } } } if (vbo->normals.gl.addr) { vbo->normals.gl.vbo = vbos[0]; vbo->normals.gl.addr = (vec3_t*)((char*)vbo->normals.gl.addr - (char*)vdata); + vaostatic |= VATTR_NORMALS; } if (vbo->svector.gl.addr) { vbo->svector.gl.vbo = vbos[0]; vbo->svector.gl.addr = (vec3_t*)((char*)vbo->svector.gl.addr - (char*)vdata); + vaostatic |= VATTR_SNORMALS; } if (vbo->tvector.gl.addr) { vbo->tvector.gl.vbo = vbos[0]; vbo->tvector.gl.addr = (vec3_t*)((char*)vbo->tvector.gl.addr - (char*)vdata); + vaostatic |= VATTR_TNORMALS; } if (vbo->colours.gl.addr) { vbo->colours.gl.vbo = vbos[0]; vbo->colours.gl.addr = (vec4_t*)((char*)vbo->colours.gl.addr - (char*)vdata); + vaostatic |= VATTR_COLOUR; } - GLBE_SetupVAO(vbo, vaodynamic); + GLBE_SetupVAO(vbo, vaodynamic, vaostatic); qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vsize, vdata, GL_STATIC_DRAW_ARB); if (elementsize>0) @@ -126,6 +141,7 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int return true; } +//allocates an aligned buffer. caller needs to make sure there's enough space. void *allocbuf(char **p, int elements, int elementsize) { void *ret; @@ -136,7 +152,7 @@ void *allocbuf(char **p, int elements, int elementsize) return ret; } -void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) +void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch, int lightmaps) { unsigned int maxvboverts; unsigned int maxvboelements; @@ -160,6 +176,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch vec4_t *colours; index_t *indicies; batch_t *batch; + int vbosize; vbo = Z_Malloc(sizeof(*vbo)); @@ -186,7 +203,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch pervertsize = sizeof(vecV_t)+ //coord sizeof(vec2_t)+ //tex - sizeof(vec2_t)*MAXLIGHTMAPS+ //lm + sizeof(vec2_t)*lightmaps+ //lm sizeof(vec3_t)+ //normal sizeof(vec3_t)+ //sdir sizeof(vec3_t)+ //tdir @@ -198,12 +215,17 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch vbo->coord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vecV_t)); vbo->texcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); - for (s = 0; s < MAXLIGHTMAPS; s++) + for (s = 0; s < lightmaps; s++) vbo->lmcoord[s].gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); + for (; s < MAXLIGHTMAPS; s++) + vbo->lmcoord[s].gl.addr = NULL; vbo->normals.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); vbo->svector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); vbo->tvector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); vbo->colours.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec4_t)); + vbosize = (char*)p - (char*)vbo->coord.gl.addr; + if ((char*)p - (char*)vbo->vertdata > (maxvboverts+1)*pervertsize) + Sys_Error("GLBE_GenBatchVBOs: aligned overflow"); vbo->indicies.gl.addr = allocbuf(&p, maxvboelements, sizeof(index_t)); coord = vbo->coord.gl.addr; @@ -246,7 +268,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch texcoord[vcount+v][0] = m->st_array[v][0]; texcoord[vcount+v][1] = m->st_array[v][1]; } - for (s = 0; s < MAXLIGHTMAPS; s++) + for (s = 0; s < lightmaps; s++) { if (m->lmst_array[s]) { @@ -284,7 +306,7 @@ void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch } } - if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t), 0)) + if (GL_BuildVBO(vbo, vbo->coord.gl.addr, vbosize/*vcount*pervertsize*/, indicies, ecount*sizeof(index_t), 0)) { BZ_Free(vbo->vertdata); vbo->vertdata = NULL; @@ -319,7 +341,7 @@ void GLBE_GenBrushModelVBO(model_t *mod) //firstmesh got reused as the number of verticies in each batch if (vcount + cvcount > MAX_INDICIES) { - GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch, mod->lightmaps.surfstyles); fbatch = batch; vcount = 0; } @@ -327,7 +349,7 @@ void GLBE_GenBrushModelVBO(model_t *mod) vcount += cvcount; } - GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch, mod->lightmaps.surfstyles); } #if 0 diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 1b160f168..881f91bdf 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -2979,7 +2979,7 @@ void Shader_Free (shader_t *shader) -int Shader_InitCallback (const char *name, int size, void *param, void *spath) +int QDECL Shader_InitCallback (const char *name, int size, void *param, void *spath) { strcpy(shaderbuf+shaderbuflen, name); Shader_MakeCache(shaderbuf+shaderbuflen); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 7fd71411f..99a712aea 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -172,6 +172,7 @@ void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id); void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); +void (APIENTRY *qglGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params); void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax); /* @@ -464,6 +465,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) #define GL_CONTEXT_PROFILE_MASK 0x9126 #define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_CONTEXT_FLAGS 0x821E +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 qglGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); if (!profile) @@ -474,8 +477,14 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) else gl_config.nofixedfunc = !(profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT); } - else if (gl_config.glversion == 3.1) - gl_config.nofixedfunc = !GL_CheckExtension("GL_ARB_compatibility"); + else if (gl_config.glversion >= 3.0) + { + GLint flags = 0; + qglGetIntegerv(GL_CONTEXT_FLAGS, &flags); + gl_config.nofixedfunc = !!(flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT); + if (gl_config.glversion >= 3.0999) + gl_config.nofixedfunc = !GL_CheckExtension("GL_ARB_compatibility"); + } else gl_config.nofixedfunc = false; } @@ -870,7 +879,22 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) } #ifndef GL_STATIC - if (GL_CheckExtension("GL_EXT_framebuffer_object")) + if (GL_CheckExtension("GL_ARB_framebuffer_object")) + { + gl_config.ext_framebuffer_objects = true; + qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffers"); + qglDeleteFramebuffersEXT = (void *)getglext("glDeleteFramebuffers"); + qglBindFramebufferEXT = (void *)getglext("glBindFramebuffer"); + qglGenRenderbuffersEXT = (void *)getglext("glGenRenderbuffers"); + qglDeleteRenderbuffersEXT = (void *)getglext("glDeleteRenderbuffers"); + qglBindRenderbufferEXT = (void *)getglext("glBindRenderbuffer"); + qglRenderbufferStorageEXT = (void *)getglext("glRenderbufferStorage"); + qglFramebufferTexture2DEXT = (void *)getglext("glFramebufferTexture2D"); + qglFramebufferRenderbufferEXT = (void *)getglext("glFramebufferRenderbuffer"); + qglCheckFramebufferStatusEXT = (void *)getglext("glCheckFramebufferStatus"); + qglGetFramebufferAttachmentParameteriv = (void *)getglext("glGetFramebufferAttachmentParameteriv"); + } + else if (GL_CheckExtension("GL_EXT_framebuffer_object")) { gl_config.ext_framebuffer_objects = true; qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffersEXT"); @@ -883,6 +907,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglFramebufferTexture2DEXT = (void *)getglext("glFramebufferTexture2DEXT"); qglFramebufferRenderbufferEXT = (void *)getglext("glFramebufferRenderbufferEXT"); qglCheckFramebufferStatusEXT = (void *)getglext("glCheckFramebufferStatusEXT"); + qglGetFramebufferAttachmentParameteriv = (void *)getglext("glGetFramebufferAttachmentParameterivEXT"); } /* //I don't think we care about the differences, so this code should be safe, but I have no way to test that theory right now else if (GL_CheckExtension("GL_OES_framebuffer_object")) diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index 15540d0e0..f55ab0147 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -537,89 +537,89 @@ static int XLateKey(XKeyEvent *ev, unsigned int *unicode) switch(keysym) { - case XK_KP_Page_Up: - case XK_Page_Up: key = K_PGUP; break; + case XK_KP_Page_Up: key = K_KP_PGUP; break; + case XK_Page_Up: key = K_PGUP; break; - case XK_KP_Page_Down: - case XK_Page_Down: key = K_PGDN; break; + case XK_KP_Page_Down: key = K_KP_PGDN; break; + case XK_Page_Down: key = K_PGDN; break; - case XK_KP_Home: - case XK_Home: key = K_HOME; break; + case XK_KP_Home: key = K_KP_HOME; break; + case XK_Home: key = K_HOME; break; - case XK_KP_End: - case XK_End: key = K_END; break; + case XK_KP_End: key = K_KP_END; break; + case XK_End: key = K_END; break; - case XK_KP_Left: - case XK_Left: key = K_LEFTARROW; break; + case XK_KP_Left: key = K_KP_LEFTARROW; break; + case XK_Left: key = K_LEFTARROW; break; - case XK_KP_Right: - case XK_Right: key = K_RIGHTARROW; break; + case XK_KP_Right: key = K_KP_RIGHTARROW; break; + case XK_Right: key = K_RIGHTARROW; break; - case XK_KP_Down: - case XK_Down: key = K_DOWNARROW; break; + case XK_KP_Down: key = K_KP_DOWNARROW; break; + case XK_Down: key = K_DOWNARROW; break; - case XK_KP_Up: - case XK_Up: key = K_UPARROW; break; + case XK_KP_Up: key = K_KP_UPARROW; break; + case XK_Up: key = K_UPARROW; break; - case XK_Escape: key = K_ESCAPE; break; + case XK_Escape: key = K_ESCAPE; break; - case XK_KP_Enter: - case XK_Return: key = K_ENTER; break; + case XK_KP_Enter: key = K_KP_ENTER; break; + case XK_Return: key = K_ENTER; break; - case XK_Tab: key = K_TAB; break; + case XK_Tab: key = K_TAB; break; - case XK_F1: key = K_F1; break; + case XK_F1: key = K_F1; break; - case XK_F2: key = K_F2; break; + case XK_F2: key = K_F2; break; - case XK_F3: key = K_F3; break; + case XK_F3: key = K_F3; break; - case XK_F4: key = K_F4; break; + case XK_F4: key = K_F4; break; - case XK_F5: key = K_F5; break; + case XK_F5: key = K_F5; break; - case XK_F6: key = K_F6; break; + case XK_F6: key = K_F6; break; - case XK_F7: key = K_F7; break; + case XK_F7: key = K_F7; break; - case XK_F8: key = K_F8; break; + case XK_F8: key = K_F8; break; - case XK_F9: key = K_F9; break; + case XK_F9: key = K_F9; break; - case XK_F10: key = K_F10; break; + case XK_F10: key = K_F10; break; - case XK_F11: key = K_F11; break; + case XK_F11: key = K_F11; break; - case XK_F12: key = K_F12; break; + case XK_F12: key = K_F12; break; - case XK_BackSpace: key = K_BACKSPACE; break; + case XK_BackSpace: key = K_BACKSPACE; break; - case XK_KP_Delete: - case XK_Delete: key = K_DEL; break; + case XK_KP_Delete: key = K_KP_DEL; break; + case XK_Delete: key = K_DEL; break; - case XK_Pause: key = K_PAUSE; break; + case XK_Pause: key = K_PAUSE; break; - case XK_Shift_L: - case XK_Shift_R: key = K_SHIFT; break; + case XK_Shift_L: key = K_LSHIFT; break; + case XK_Shift_R: key = K_RSHIFT; break; - case XK_Execute: - case XK_Control_L: - case XK_Control_R: key = K_CTRL; break; + case XK_Execute: key = K_LCTRL; break; + case XK_Control_L: key = K_LCTRL; break; + case XK_Control_R: key = K_RCTRL; break; - case XK_Alt_L: - case XK_Meta_L: - case XK_Alt_R: - case XK_Meta_R: key = K_ALT; break; + case XK_Alt_L: key = K_LALT; break; + case XK_Meta_L: key = K_LALT; break; + case XK_Alt_R: key = K_RALT; break; + case XK_Meta_R: key = K_RALT; break; - case XK_KP_Begin: key = '5'; break; + case XK_KP_Begin: key = K_KP_5; break; - case XK_KP_Insert: - case XK_Insert:key = K_INS; break; + case XK_KP_Insert: key = K_KP_INS; break; + case XK_Insert: key = K_INS; break; - case XK_KP_Multiply: key = '*'; break; - case XK_KP_Add: key = '+'; break; - case XK_KP_Subtract: key = '-'; break; - case XK_KP_Divide: key = '/'; break; + case XK_KP_Multiply: key = K_KP_STAR; break; + case XK_KP_Add: key = K_KP_PLUS; break; + case XK_KP_Subtract: key = K_KP_MINUS; break; + case XK_KP_Divide: key = K_KP_SLASH; break; #if 0 case 0x021: key = '1';break;/* [!] */ diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index f18fafe3b..8c1479d36 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -1875,6 +1875,12 @@ LONG WINAPI GLMainWndProc ( switch (uMsg) { + case WM_COPYDATA: + { + COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lParam; + Sys_RunFile(cds->lpData, cds->cbData); + } + break; case WM_KILLFOCUS: GLAppActivate(FALSE, Minimized); if (modestate == MS_FULLDIB) diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 1f84c29fd..6edda12e7 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -675,6 +675,7 @@ extern void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internal extern void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId, GLint level); extern void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); extern GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); +extern void (APIENTRY *qglGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params); //glslang - arb_shader_objects diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index 52fbf17fa..05ed898cf 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -698,6 +698,10 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); #define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 #endif +#ifndef GL_ARB_framebuffer_object +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#endif + #ifndef GL_VERSION_3_0 #define GL_MAJOR_VERSION 0x821B #define GL_MINOR_VERSION 0x821C diff --git a/engine/http/ftpserver.c b/engine/http/ftpserver.c index c2f5de66f..79d2d0e78 100644 --- a/engine/http/ftpserver.c +++ b/engine/http/ftpserver.c @@ -134,7 +134,7 @@ void FTP_ServerShutdown(void) } //we ought to filter this to remove duplicates. -static int SendFileNameTo(const char *rawname, int size, void *param, struct searchpath_s *spath) +static int QDECL SendFileNameTo(const char *rawname, int size, void *param, struct searchpath_s *spath) { int socket = *(int*)param; // int i; @@ -263,7 +263,7 @@ iwboolean FTP_SVRemoteSocketToString (int socket, char *s, int slen) } SockadrToNetadr(&addr, &na); - NET_AdrToString(s, slen, na); + NET_AdrToString(s, slen, &na); // if (((struct sockaddr_in*)&addr)->sin_family == AF_INET6) // { @@ -711,8 +711,18 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl) if (!(*resource == '/')) { - memmove(resource+strlen(cl->path), resource, strlen(resource)+1); - memcpy(resource, cl->path, strlen(cl->path)); + int plen = strlen(cl->path); + if (plen && cl->path[plen-1] != '/') + { + memmove(resource+plen+1, resource, strlen(resource)+1); + memcpy(resource, cl->path, plen); + resource[plen] = '/'; + } + else + { + memmove(resource+plen, resource, strlen(resource)+1); + memcpy(resource, cl->path, plen); + } } if (*resource == '/') { diff --git a/engine/http/httpclient.c b/engine/http/httpclient.c index 908efdb27..5d5b6f32d 100644 --- a/engine/http/httpclient.c +++ b/engine/http/httpclient.c @@ -822,6 +822,12 @@ struct dl_download *DL_Create(const char *url) Q_strncpyz(newdl->url, url, sizeof(newdl->url)); newdl->poll = HTTPDL_Decide; + if (!newdl->poll(newdl)) + { + free(newdl); + newdl = NULL; + } + return newdl; } static struct dl_download *showndownload; diff --git a/engine/http/httpserver.c b/engine/http/httpserver.c index 595076545..80a1471ec 100644 --- a/engine/http/httpserver.c +++ b/engine/http/httpserver.c @@ -567,7 +567,7 @@ qboolean HTTP_ServerPoll(qboolean httpserverwanted, int portnum) //loop while tr #ifndef WEBSVONLY SockadrToNetadr(&from, &na); - IWebPrintf("New http connection from %s\n", NET_AdrToString(buf, sizeof(buf), na)); + IWebPrintf("New http connection from %s\n", NET_AdrToString(buf, sizeof(buf), &na)); #endif cl = IWebMalloc(sizeof(HTTP_active_connections_t)); diff --git a/engine/http/webgen.c b/engine/http/webgen.c index d874b52b3..6b85fadc5 100644 --- a/engine/http/webgen.c +++ b/engine/http/webgen.c @@ -333,7 +333,7 @@ typedef struct { int pos; } vfsgen_t; -int VFSGen_ReadBytes(vfsfile_t *f, void *buffer, int bytes) +int QDECL VFSGen_ReadBytes(vfsfile_t *f, void *buffer, int bytes) { vfsgen_t *g = (vfsgen_t*)f; if (bytes + g->pos >= g->buffer->len) @@ -349,13 +349,13 @@ int VFSGen_ReadBytes(vfsfile_t *f, void *buffer, int bytes) return bytes; } -int VFSGen_WriteBytes(vfsfile_t *f, const void *buffer, int bytes) +int QDECL VFSGen_WriteBytes(vfsfile_t *f, const void *buffer, int bytes) { Sys_Error("VFSGen_WriteBytes: Readonly\n"); return 0; } -qboolean VFSGen_Seek(vfsfile_t *f, unsigned long newpos) +qboolean QDECL VFSGen_Seek(vfsfile_t *f, unsigned long newpos) { vfsgen_t *g = (vfsgen_t*)f; if (newpos < 0 || newpos >= g->buffer->len) @@ -366,19 +366,19 @@ qboolean VFSGen_Seek(vfsfile_t *f, unsigned long newpos) return true; } -unsigned long VFSGen_Tell(vfsfile_t *f) +unsigned long QDECL VFSGen_Tell(vfsfile_t *f) { vfsgen_t *g = (vfsgen_t*)f; return g->pos; } -unsigned long VFSGen_GetLen(vfsfile_t *f) +unsigned long QDECL VFSGen_GetLen(vfsfile_t *f) { vfsgen_t *g = (vfsgen_t*)f; return g->buffer->len; } -void VFSGen_Close(vfsfile_t *f) +void QDECL VFSGen_Close(vfsfile_t *f) { int fnum; vfsgen_t *g = (vfsgen_t*)f; diff --git a/engine/qclib/hash.c b/engine/qclib/hash.c index 1ad5229d5..3e44ece08 100644 --- a/engine/qclib/hash.c +++ b/engine/qclib/hash.c @@ -15,6 +15,28 @@ void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem) table->bucket = (bucket_t **)mem; } +void *Hash_Enumerate(hashtable_t *table, void (*callback) (void *ctx, void *data), void *ctx) +{ + unsigned int bucknum; + bucket_t *buck; + void *data; + + for (bucknum = 0; bucknum < table->numbuckets; bucknum++) + { + buck = table->bucket[bucknum]; + + while(buck) + { + data = buck->data; + buck = buck->next; + + //now that we don't care about backlinks etc, we can call the callback and it can safely nuke it (Hash_RemoveData or even destroy the bucket if the hash table is going to die). + callback(ctx, data); + } + } + return NULL; +} + unsigned int Hash_Key(const char *name, unsigned int modulus) { //fixme: optimize. unsigned int key; @@ -37,6 +59,26 @@ unsigned int Hash_KeyInsensative(const char *name, unsigned int modulus) return (key%modulus); } +void *Hash_GetIdx(hashtable_t *table, unsigned int idx) +{ + unsigned int bucknum; + bucket_t *buck; + + for (bucknum = 0; bucknum < table->numbuckets; bucknum++) + { + buck = table->bucket[bucknum]; + + while(buck) + { + if (!idx--) + return buck->data; + + buck = buck->next; + } + } + return NULL; +} + void *Hash_Get(hashtable_t *table, const char *name) { unsigned int bucknum = Hash_Key(name, table->numbuckets); diff --git a/engine/qclib/hash.h b/engine/qclib/hash.h index 4344abf02..a084cc32e 100644 --- a/engine/qclib/hash.h +++ b/engine/qclib/hash.h @@ -22,7 +22,9 @@ typedef struct hashtable_s { } hashtable_t; void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem); //mem must be 0 filled. (memset(mem, 0, size)) +void *Hash_Enumerate(hashtable_t *table, void (*callback) (void *ctx, void *data), void *ctx); unsigned int Hash_Key(const char *name, unsigned int modulus); +void *Hash_GetIdx(hashtable_t *table, unsigned int idx); void *Hash_Get(hashtable_t *table, const char *name); void *Hash_GetInsensative(hashtable_t *table, const char *name); void *Hash_GetInsensativeBucket(hashtable_t *table, const char *name); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 5712fdc71..764b9997e 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -131,6 +131,7 @@ void *PRAddressableExtend(progfuncs_t *progfuncs, int ammount) } prinst.addressableused += ammount; + progfuncs->funcs.stringtablesize = prinst.addressableused; #ifdef _WIN32 if (!VirtualAlloc (prinst.addressablehunk, prinst.addressableused, MEM_COMMIT, PAGE_READWRITE)) @@ -420,6 +421,7 @@ void PRAddressableFlush(progfuncs_t *progfuncs, size_t totalammount) if (!prinst.addressablehunk) Sys_Error("Out of memory\n"); prinst.addressablesize = totalammount; + progfuncs->funcs.stringtablemaxsize = totalammount; } int PDECL PR_InitEnts(pubprogfuncs_t *ppf, int max_ents) @@ -1065,6 +1067,7 @@ pubprogfuncs_t deffuncs = { 0, //string table(pointer base address) 0, //string table size + 0, //max size 0, //field adjust(aditional field offset) PR_ForkStack, diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index b48a0f2a7..cb3aa7cac 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -130,6 +130,7 @@ struct pubprogfuncs_s char *stringtable; //qc strings are all relative. add to a qc string. this is required for support of frikqcc progs that strip string immediates. int stringtablesize; + int stringtablemaxsize; int fieldadjust; //FrikQCC style arrays can cause problems due to field remapping. This causes us to leave gaps but offsets identical. struct qcthread_s *(PDECL *Fork) (pubprogfuncs_t *prinst); //returns a pointer to a thread which can be resumed via RunThread. diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index e4e131bb3..626588368 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -1770,7 +1770,7 @@ qboolean PR_GameCodePacket(char *s) { if (cl->state == cs_free) continue; - if (!NET_CompareAdr (net_from, cl->netchan.remote_address)) + if (!NET_CompareAdr (&net_from, &cl->netchan.remote_address)) continue; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); break; @@ -1778,7 +1778,7 @@ qboolean PR_GameCodePacket(char *s) - G_INT(OFS_PARM0) = PR_TempString(svprogfuncs, NET_AdrToString (adr, sizeof(adr), net_from)); + G_INT(OFS_PARM0) = PR_TempString(svprogfuncs, NET_AdrToString (adr, sizeof(adr), &net_from)); G_INT(OFS_PARM1) = PR_TempString(svprogfuncs, s); PR_ExecuteProgram (svprogfuncs, gfuncs.ParseConnectionlessPacket); @@ -5282,13 +5282,13 @@ char *PF_infokey_Internal (int entnum, char *key) { value = ov; if (!strcmp(key, "ip")) - NET_BaseAdrToString (ov, sizeof(ov), svs.clients[entnum-1].netchan.remote_address); + NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address); else if (!strcmp(key, "realip")) { if (svs.clients[entnum-1].realip_status) - NET_BaseAdrToString (ov, sizeof(ov), svs.clients[entnum-1].realip); + NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].realip); else //FIXME: should we report the spoofable/proxy address if the real ip is not known? - NET_BaseAdrToString (ov, sizeof(ov), svs.clients[entnum-1].netchan.remote_address); + NET_BaseAdrToString (ov, sizeof(ov), &svs.clients[entnum-1].netchan.remote_address); } else if (!strcmp(key, "csqcactive")) sprintf(ov, "%d", svs.clients[entnum-1].csqcactive); @@ -6623,7 +6623,7 @@ static void QCBUILTIN PF_h2advanceweaponframe (pubprogfuncs_t *prinst, struct gl G_FLOAT(OFS_RETURN) = state; } -char *SV_CheckRejectConnection(netadr_t adr, char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, char *guid) +char *SV_CheckRejectConnection(netadr_t *adr, char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, char *guid) { char addrstr[256]; char clfeatures[4096], *bp; @@ -6671,6 +6671,10 @@ char *SV_CheckRejectConnection(netadr_t adr, char *uinfo, unsigned int protocol, Info_SetValueForKey(clfeatures, "maxentities", "32767", sizeof(clfeatures)); else if (protocol == SCP_DARKPLACES6 || protocol == SCP_DARKPLACES7) Info_SetValueForKey(clfeatures, "maxentities", "32767", sizeof(clfeatures)); + else if (pext1 & PEXT_ENTITYDBL2) + Info_SetValueForKey(clfeatures, "maxentities", "2048", sizeof(clfeatures)); + else if (pext1 & PEXT_ENTITYDBL) + Info_SetValueForKey(clfeatures, "maxentities", "1024", sizeof(clfeatures)); else if (protocol == SCP_NETQUAKE) Info_SetValueForKey(clfeatures, "maxentities", "600", sizeof(clfeatures)); else //if (protocol == SCP_QUAKEWORLD) @@ -7118,108 +7122,108 @@ void SV_RegisterH2CustomTents(void) if (progstype == PROG_H2) { - h2customtents[ce_rain] = SV_CustomTEnt_Register("ce_rain", CTE_PERSISTANT|CTE_CUSTOMVELOCITY|CTE_ISBEAM|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_fountain] = SV_CustomTEnt_Register("ce_fountain", CTE_PERSISTANT|CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_quake] = SV_CustomTEnt_Register("ce_quake", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_rain] = SV_CustomTEnt_Register("h2part.ce_rain", CTE_PERSISTANT|CTE_CUSTOMVELOCITY|CTE_ISBEAM|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_fountain] = SV_CustomTEnt_Register("h2part.ce_fountain", CTE_PERSISTANT|CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_quake] = SV_CustomTEnt_Register("h2part.ce_quake", 0, NULL, 0, NULL, 0, 0, NULL); // ce_white_smoke (special) - h2customtents[ce_bluespark] = SV_CustomTEnt_Register("ce_bluespark", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_yellowspark] = SV_CustomTEnt_Register("ce_yellowspark", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_sm_circle_exp] = SV_CustomTEnt_Register("ce_sm_circle_exp", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_bg_circle_exp] = SV_CustomTEnt_Register("ce_bg_circle_exp", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_sm_white_flash] = SV_CustomTEnt_Register("ce_sm_white_flash", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_white_flash] = SV_CustomTEnt_Register("ce_white_flash", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_yellowred_flash] = SV_CustomTEnt_Register("ce_yellowred_flash", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_blue_flash] = SV_CustomTEnt_Register("ce_blue_flash", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_sm_blue_flash] = SV_CustomTEnt_Register("ce_sm_blue_flash", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_red_flash] = SV_CustomTEnt_Register("ce_red_flash", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_sm_explosion] = SV_CustomTEnt_Register("ce_sm_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_lg_explosion] = SV_CustomTEnt_Register("ce_lg_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_floor_explosion] = SV_CustomTEnt_Register("ce_floor_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_rider_death] = SV_CustomTEnt_Register("ce_rider_death", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_blue_explosion] = SV_CustomTEnt_Register("ce_blue_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bluespark] = SV_CustomTEnt_Register("h2part.ce_bluespark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_yellowspark] = SV_CustomTEnt_Register("h2part.ce_yellowspark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_circle_exp] = SV_CustomTEnt_Register("h2part.ce_sm_circle_exp", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bg_circle_exp] = SV_CustomTEnt_Register("h2part.ce_bg_circle_exp", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_white_flash] = SV_CustomTEnt_Register("h2part.ce_sm_white_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_flash] = SV_CustomTEnt_Register("h2part.ce_white_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_yellowred_flash] = SV_CustomTEnt_Register("h2part.ce_yellowred_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_blue_flash] = SV_CustomTEnt_Register("h2part.ce_blue_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_blue_flash] = SV_CustomTEnt_Register("h2part.ce_sm_blue_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_red_flash] = SV_CustomTEnt_Register("h2part.ce_red_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_explosion] = SV_CustomTEnt_Register("h2part.ce_sm_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_lg_explosion] = SV_CustomTEnt_Register("h2part.ce_lg_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_floor_explosion] = SV_CustomTEnt_Register("h2part.ce_floor_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_rider_death] = SV_CustomTEnt_Register("h2part.ce_rider_death", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_blue_explosion] = SV_CustomTEnt_Register("h2part.ce_blue_explosion", 0, NULL, 0, NULL, 0, 0, NULL); // ce_green_smoke (special) // ce_grey_smoke (special) - h2customtents[ce_red_smoke] = SV_CustomTEnt_Register("ce_red_smoke", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_slow_white_smoke] = SV_CustomTEnt_Register("ce_slow_white_smoke", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_redspark] = SV_CustomTEnt_Register("ce_redspark", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_greenspark] = SV_CustomTEnt_Register("ce_greenspark", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_telesmk1] = SV_CustomTEnt_Register("ce_telesmk1", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_telesmk2] = SV_CustomTEnt_Register("ce_telesmk2", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_icehit] = SV_CustomTEnt_Register("ce_icehit", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_medusa_hit] = SV_CustomTEnt_Register("ce_medusa_hit", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_mezzo_reflect] = SV_CustomTEnt_Register("ce_mezzo_reflect", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_floor_explosion2] = SV_CustomTEnt_Register("ce_floor_explosion2", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_xbow_explosion] = SV_CustomTEnt_Register("ce_xbow_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_new_explosion] = SV_CustomTEnt_Register("ce_new_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_magic_missile_explosion] = SV_CustomTEnt_Register("ce_magic_missile_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_ghost] = SV_CustomTEnt_Register("ce_ghost", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_bone_explosion] = SV_CustomTEnt_Register("ce_bone_explosion", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_redcloud] = SV_CustomTEnt_Register("ce_redcloud", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_teleporterpuffs] = SV_CustomTEnt_Register("ce_teleporterpuffs", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_teleporterbody] = SV_CustomTEnt_Register("ce_teleporterbody", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_boneshard] = SV_CustomTEnt_Register("ce_boneshard", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_boneshrapnel] = SV_CustomTEnt_Register("ce_boneshrapnel", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_flamestream] = SV_CustomTEnt_Register("ce_flamestream", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_snow] = SV_CustomTEnt_Register("ce_snow", CTE_PERSISTANT|CTE_CUSTOMVELOCITY|CTE_ISBEAM|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_gravitywell] = SV_CustomTEnt_Register("ce_gravitywell", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_bldrn_expl] = SV_CustomTEnt_Register("ce_bldrn_expl", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_acid_muzzfl] = SV_CustomTEnt_Register("ce_acid_muzzfl", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_acid_hit] = SV_CustomTEnt_Register("ce_acid_hit", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_firewall_small] = SV_CustomTEnt_Register("ce_firewall_small", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_firewall_medium] = SV_CustomTEnt_Register("ce_firewall_medium", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_firewall_large] = SV_CustomTEnt_Register("ce_firewall_large", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_lball_expl] = SV_CustomTEnt_Register("ce_lball_expl", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_acid_splat] = SV_CustomTEnt_Register("ce_acid_splat", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_acid_expl] = SV_CustomTEnt_Register("ce_acid_expl", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_fboom] = SV_CustomTEnt_Register("ce_fboom", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_red_smoke] = SV_CustomTEnt_Register("h2part.ce_red_smoke", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_slow_white_smoke] = SV_CustomTEnt_Register("h2part.ce_slow_white_smoke", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_redspark] = SV_CustomTEnt_Register("h2part.ce_redspark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_greenspark] = SV_CustomTEnt_Register("h2part.ce_greenspark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_telesmk1] = SV_CustomTEnt_Register("h2part.ce_telesmk1", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_telesmk2] = SV_CustomTEnt_Register("h2part.ce_telesmk2", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_icehit] = SV_CustomTEnt_Register("h2part.ce_icehit", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_medusa_hit] = SV_CustomTEnt_Register("h2part.ce_medusa_hit", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_mezzo_reflect] = SV_CustomTEnt_Register("h2part.ce_mezzo_reflect", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_floor_explosion2] = SV_CustomTEnt_Register("h2part.ce_floor_explosion2", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_xbow_explosion] = SV_CustomTEnt_Register("h2part.ce_xbow_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_new_explosion] = SV_CustomTEnt_Register("h2part.ce_new_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_magic_missile_explosion] = SV_CustomTEnt_Register("h2part.ce_magic_missile_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_ghost] = SV_CustomTEnt_Register("h2part.ce_ghost", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bone_explosion] = SV_CustomTEnt_Register("h2part.ce_bone_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_redcloud] = SV_CustomTEnt_Register("h2part.ce_redcloud", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_teleporterpuffs] = SV_CustomTEnt_Register("h2part.ce_teleporterpuffs", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_teleporterbody] = SV_CustomTEnt_Register("h2part.ce_teleporterbody", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_boneshard] = SV_CustomTEnt_Register("h2part.ce_boneshard", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_boneshrapnel] = SV_CustomTEnt_Register("h2part.ce_boneshrapnel", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_flamestream] = SV_CustomTEnt_Register("h2part.ce_flamestream", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_snow] = SV_CustomTEnt_Register("h2part.ce_snow", CTE_PERSISTANT|CTE_CUSTOMVELOCITY|CTE_ISBEAM|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_gravitywell] = SV_CustomTEnt_Register("h2part.ce_gravitywell", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bldrn_expl] = SV_CustomTEnt_Register("h2part.ce_bldrn_expl", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_muzzfl] = SV_CustomTEnt_Register("h2part.ce_acid_muzzfl", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_hit] = SV_CustomTEnt_Register("h2part.ce_acid_hit", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_firewall_small] = SV_CustomTEnt_Register("h2part.ce_firewall_small", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_firewall_medium] = SV_CustomTEnt_Register("h2part.ce_firewall_medium", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_firewall_large] = SV_CustomTEnt_Register("h2part.ce_firewall_large", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_lball_expl] = SV_CustomTEnt_Register("h2part.ce_lball_expl", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_splat] = SV_CustomTEnt_Register("h2part.ce_acid_splat", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_expl] = SV_CustomTEnt_Register("h2part.ce_acid_expl", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_fboom] = SV_CustomTEnt_Register("h2part.ce_fboom", 0, NULL, 0, NULL, 0, 0, NULL); // ce_chunk (special) - h2customtents[ce_bomb] = SV_CustomTEnt_Register("ce_bomb", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_brn_bounce] = SV_CustomTEnt_Register("ce_brn_bounce", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_lshock] = SV_CustomTEnt_Register("ce_lshock", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_flamewall] = SV_CustomTEnt_Register("ce_flamewall", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_flamewall2] = SV_CustomTEnt_Register("ce_flamewall2", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_floor_explosion3] = SV_CustomTEnt_Register("ce_floor_explosion3", 0, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_onfire] = SV_CustomTEnt_Register("ce_onfire", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bomb] = SV_CustomTEnt_Register("h2part.ce_bomb", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_brn_bounce] = SV_CustomTEnt_Register("h2part.ce_brn_bounce", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_lshock] = SV_CustomTEnt_Register("h2part.ce_lshock", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_flamewall] = SV_CustomTEnt_Register("h2part.ce_flamewall", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_flamewall2] = SV_CustomTEnt_Register("h2part.ce_flamewall2", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_floor_explosion3] = SV_CustomTEnt_Register("h2part.ce_floor_explosion3", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_onfire] = SV_CustomTEnt_Register("h2part.ce_onfire", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_teleporterbody_1] = SV_CustomTEnt_Register("ce_teleporterbody_1", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_white_smoke_05] = SV_CustomTEnt_Register("ce_white_smoke_05", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_white_smoke_10] = SV_CustomTEnt_Register("ce_white_smoke_10", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_white_smoke_15] = SV_CustomTEnt_Register("ce_white_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_white_smoke_20] = SV_CustomTEnt_Register("ce_white_smoke_20", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_white_smoke_50] = SV_CustomTEnt_Register("ce_white_smoke_50", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_green_smoke_05] = SV_CustomTEnt_Register("ce_green_smoke_05", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_green_smoke_10] = SV_CustomTEnt_Register("ce_green_smoke_10", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_green_smoke_15] = SV_CustomTEnt_Register("ce_green_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_green_smoke_20] = SV_CustomTEnt_Register("ce_green_smoke_20", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_grey_smoke_15] = SV_CustomTEnt_Register("ce_grey_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_grey_smoke_100] = SV_CustomTEnt_Register("ce_grey_smoke_100", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_teleporterbody_1] = SV_CustomTEnt_Register("h2part.ce_teleporterbody_1", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_05] = SV_CustomTEnt_Register("h2part.ce_white_smoke_05", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_10] = SV_CustomTEnt_Register("h2part.ce_white_smoke_10", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_15] = SV_CustomTEnt_Register("h2part.ce_white_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_20] = SV_CustomTEnt_Register("h2part.ce_white_smoke_20", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_50] = SV_CustomTEnt_Register("h2part.ce_white_smoke_50", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_05] = SV_CustomTEnt_Register("h2part.ce_green_smoke_05", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_10] = SV_CustomTEnt_Register("h2part.ce_green_smoke_10", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_15] = SV_CustomTEnt_Register("h2part.ce_green_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_20] = SV_CustomTEnt_Register("h2part.ce_green_smoke_20", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_grey_smoke_15] = SV_CustomTEnt_Register("h2part.ce_grey_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_grey_smoke_100] = SV_CustomTEnt_Register("h2part.ce_grey_smoke_100", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_1] = SV_CustomTEnt_Register("ce_chunk_greystone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_2] = SV_CustomTEnt_Register("ce_chunk_wood", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_3] = SV_CustomTEnt_Register("ce_chunk_metal", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_4] = SV_CustomTEnt_Register("ce_chunk_flesh", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_5] = SV_CustomTEnt_Register("ce_chunk_fire", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_6] = SV_CustomTEnt_Register("ce_chunk_clay", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_7] = SV_CustomTEnt_Register("ce_chunk_leaves", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_8] = SV_CustomTEnt_Register("ce_chunk_hay", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_9] = SV_CustomTEnt_Register("ce_chunk_brownstone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_10] = SV_CustomTEnt_Register("ce_chunk_cloth", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_11] = SV_CustomTEnt_Register("ce_chunk_wood_leaf", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_12] = SV_CustomTEnt_Register("ce_chunk_wood_metal", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_13] = SV_CustomTEnt_Register("ce_chunk_wood_stone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_14] = SV_CustomTEnt_Register("ce_chunk_metal_stone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_15] = SV_CustomTEnt_Register("ce_chunk_metal_cloth", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_16] = SV_CustomTEnt_Register("ce_chunk_webs", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_17] = SV_CustomTEnt_Register("ce_chunk_glass", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_18] = SV_CustomTEnt_Register("ce_chunk_ice", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_19] = SV_CustomTEnt_Register("ce_chunk_clearglass", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_20] = SV_CustomTEnt_Register("ce_chunk_redglass", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_21] = SV_CustomTEnt_Register("ce_chunk_acid", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_22] = SV_CustomTEnt_Register("ce_chunk_meteor", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_23] = SV_CustomTEnt_Register("ce_chunk_greenflesh", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); - h2customtents[ce_chunk_24] = SV_CustomTEnt_Register("ce_chunk_bone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_1] = SV_CustomTEnt_Register("h2part.ce_chunk_greystone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_2] = SV_CustomTEnt_Register("h2part.ce_chunk_wood", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_3] = SV_CustomTEnt_Register("h2part.ce_chunk_metal", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_4] = SV_CustomTEnt_Register("h2part.ce_chunk_flesh", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_5] = SV_CustomTEnt_Register("h2part.ce_chunk_fire", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_6] = SV_CustomTEnt_Register("h2part.ce_chunk_clay", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_7] = SV_CustomTEnt_Register("h2part.ce_chunk_leaves", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_8] = SV_CustomTEnt_Register("h2part.ce_chunk_hay", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_9] = SV_CustomTEnt_Register("h2part.ce_chunk_brownstone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_10] = SV_CustomTEnt_Register("h2part.ce_chunk_cloth", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_11] = SV_CustomTEnt_Register("h2part.ce_chunk_wood_leaf", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_12] = SV_CustomTEnt_Register("h2part.ce_chunk_wood_metal", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_13] = SV_CustomTEnt_Register("h2part.ce_chunk_wood_stone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_14] = SV_CustomTEnt_Register("h2part.ce_chunk_metal_stone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_15] = SV_CustomTEnt_Register("h2part.ce_chunk_metal_cloth", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_16] = SV_CustomTEnt_Register("h2part.ce_chunk_webs", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_17] = SV_CustomTEnt_Register("h2part.ce_chunk_glass", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_18] = SV_CustomTEnt_Register("h2part.ce_chunk_ice", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_19] = SV_CustomTEnt_Register("h2part.ce_chunk_clearglass", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_20] = SV_CustomTEnt_Register("h2part.ce_chunk_redglass", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_21] = SV_CustomTEnt_Register("h2part.ce_chunk_acid", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_22] = SV_CustomTEnt_Register("h2part.ce_chunk_meteor", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_23] = SV_CustomTEnt_Register("h2part.ce_chunk_greenflesh", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_chunk_24] = SV_CustomTEnt_Register("h2part.ce_chunk_bone", CTE_CUSTOMVELOCITY|CTE_CUSTOMCOUNT, NULL, 0, NULL, 0, 0, NULL); } } static void QCBUILTIN PF_h2starteffect(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -8870,7 +8874,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) - pr_global_struct->input_timelength = ucmd->msec/1000.0f; + pr_global_struct->input_timelength = ucmd->msec/1000.0f * sv.gamespeed; pr_global_struct->input_impulse = ucmd->impulse; //precision inaccuracies. :( #define ANGLE2SHORT(x) (x) * (65536/360.0) @@ -8956,7 +8960,7 @@ static void QCBUILTIN PF_SendPacket(pubprogfuncs_t *prinst, struct globalvars_s char *contents = PF_VarString(prinst, 1, pr_globals); NET_StringToAdr(address, 0, &to); - NET_SendPacket(NS_SERVER, strlen(contents), contents, to); + NET_SendPacket(NS_SERVER, strlen(contents), contents, &to); } @@ -9361,9 +9365,9 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"strpad", PF_strpad, 0, 0, 0, 225, "string(float pad, string str1, ...)"}, //will be moved {"infoadd", PF_infoadd, 0, 0, 0, 226, "string(string old, string key, string value)"}, {"infoget", PF_infoget, 0, 0, 0, 227, "string(string info, string key)"}, - {"strncmp", PF_strncmp, 0, 0, 0, 228, "float(string s1, string s2, float len)"}, + {"strncmp", PF_strncmp, 0, 0, 0, 228, "float(string s1, string s2, float len, optional float s1ofs)"}, {"strcasecmp", PF_strcasecmp, 0, 0, 0, 229, "float(string s1, string s2)"}, - {"strncasecmp", PF_strncasecmp, 0, 0, 0, 230, "float(string s1, string s2, float len)"}, + {"strncasecmp", PF_strncasecmp, 0, 0, 0, 230, "float(string s1, string s2, float len, optional float s1ofs)"}, //END FTE_STRINGS //FTE_CALLTIMEOFDAY @@ -9433,8 +9437,13 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"skel_set_bone_world",PF_skel_set_bone_world,0,0, 0, 283, "void(entity ent, float bonenum, vector org, optional vector angorfwd, optional vector right, optional vector up)"}, {"frametoname", PF_frametoname, 0, 0, 0, 284, "string(float modidx, float framenum)"}, {"skintoname", PF_skintoname, 0, 0, 0, 285, "string(float modidx, float skin)"}, - -// {"cvar_setlatch", PF_cvar_setlatch, 0, 0, 0, 284, "void(string cvarname, optional string value)"}, //72 +// {"cvar_setlatch", PF_cvar_setlatch, 0, 0, 0, 286, "void(string cvarname, optional string value)"}, + {"hash_createtab", PF_hash_createtab, 0, 0, 0, 287, "float(float tabsize)"}, + {"hash_destroytab", PF_hash_destroytab, 0, 0, 0, 288, "void(float table)"}, + {"hash_add", PF_hash_add, 0, 0, 0, 289, "void(float table, string name, __variant value)"}, //adds the given key with the given value to the table. value will NOT be strzoned or anything fancy like that, so don't pass temp strings there. Its okay to pass temp strings for 'name' though. + {"hash_get", PF_hash_get, 0, 0, 0, 290, "__variant(float table, string name, __variant default)"}, //looks up the specified key name. returns default if key was not found. + {"hash_delete", PF_hash_delete, 0, 0, 0, 291, "__variant(float table, string name)"}, //removes the named key. returns its value. + {"hash_getkey", PF_hash_getkey, 0, 0, 0, 292, "string(float table, float idx)"}, //gets some random key name. add+delete can change return values of this. suggested use is: while((n = hash_getkey(t,0))) strunzone(hash_delete(t,n)); {"clearscene", PF_Fixme, 0, 0, 0, 300, "void()"},// (EXT_CSQC) @@ -9541,7 +9550,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"memalloc", PF_memalloc, 0, 0, 0, 384, "__variant*(int size)"}, {"memfree", PF_memfree, 0, 0, 0, 385, "void(__variant *ptr)"}, {"memcpy", PF_memcpy, 0, 0, 0, 386, "void(__variant *dst, __variant *src, int size)"}, - {"memset", PF_memset, 0, 0, 0, 387, "void(__variant *dst, int val, int size)"}, + {"memfill8", PF_memfill8, 0, 0, 0, 387, "void(__variant *dst, int val, int size)"}, + {"memgetval", PF_memgetval, 0, 0, 0, 388, "__variant(__variant *dst, float ofs)"}, + {"memsetval", PF_memsetval, 0, 0, 0, 389, "void(__variant *dst, float ofs, __variant val)"}, + {"memptradd", PF_memptradd, 0, 0, 0, 390, "__variant*(__variant *base, float ofs)"}, //end fte extras diff --git a/engine/server/server.h b/engine/server/server.h index c0d32e708..7bd153de1 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -927,7 +927,7 @@ extern vfsfile_t *sv_fraglogfile; //=========================================================== void SV_AddDebugPolygons(void); -char *SV_CheckRejectConnection(netadr_t adr, char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, char *guid); +char *SV_CheckRejectConnection(netadr_t *adr, char *uinfo, unsigned int protocol, unsigned int pext1, unsigned int pext2, char *guid); // // sv_main.c diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 3c390d2c7..6f1049951 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -374,7 +374,7 @@ void SV_Give_f (void) } } -int ShowMapList (const char *name, int flags, void *parm, struct searchpath_s *spath) +int QDECL ShowMapList (const char *name, int flags, void *parm, struct searchpath_s *spath) { if (name[5] == 'b' && name[6] == '_') //skip box models return true; @@ -769,7 +769,7 @@ void SV_BanName_f (void) { bannedips_t *nb; - if (NET_IsLoopBackAddress(cl->netchan.remote_address)) + if (NET_IsLoopBackAddress(&cl->netchan.remote_address)) { Con_Printf("You're not allowed to ban loopback!\n"); continue; @@ -797,7 +797,7 @@ void SV_BanName_f (void) Con_TPrintf (STL_USERDOESNTEXIST, Cmd_Argv(1)); } -void SV_KickBanIP(netadr_t banadr, netadr_t banmask, char *reason) +void SV_KickBanIP(netadr_t *banadr, netadr_t *banmask, char *reason) { qboolean shouldkick; client_t *cl; @@ -818,10 +818,10 @@ void SV_KickBanIP(netadr_t banadr, netadr_t banmask, char *reason) shouldkick = false; - if (NET_CompareAdrMasked(cl->netchan.remote_address, banadr, banmask)) + if (NET_CompareAdrMasked(&cl->netchan.remote_address, banadr, banmask)) shouldkick = true; else if (cl->realip_status >= 1) - if (NET_CompareAdrMasked(cl->realip, banadr, banmask)) + if (NET_CompareAdrMasked(&cl->realip, banadr, banmask)) shouldkick = true; if (shouldkick) @@ -839,8 +839,8 @@ void SV_KickBanIP(netadr_t banadr, netadr_t banmask, char *reason) // add IP and mask to ban list nb = Z_Malloc(sizeof(bannedips_t)+reasonsize); nb->next = svs.bannedips; - nb->adr = banadr; - nb->adrmask = banmask; + nb->adr = *banadr; + nb->adrmask = *banmask; svs.bannedips = nb; if (reasonsize) Q_strcpy(nb->reason, reason); @@ -864,7 +864,7 @@ void SV_BanIP_f (void) return; } - if (NET_IsLoopBackAddress(banadr)) + if (NET_IsLoopBackAddress(&banadr)) { Con_Printf("You're not allowed to ban loopback!\n"); return; @@ -873,7 +873,7 @@ void SV_BanIP_f (void) if (Cmd_Argc() > 2) reason = Cmd_Argv(2); - SV_KickBanIP(banadr, banmask, reason); + SV_KickBanIP(&banadr, &banmask, reason); } void SV_BanClientIP_f (void) @@ -885,7 +885,7 @@ void SV_BanClientIP_f (void) while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum))) { - if (NET_IsLoopBackAddress(cl->netchan.remote_address)) + if (NET_IsLoopBackAddress(&cl->netchan.remote_address)) { Con_Printf("You're not allowed to ban loopback!\n"); continue; @@ -895,13 +895,13 @@ void SV_BanClientIP_f (void) { memset(&banmask.address, 0xff, sizeof(banmask.address)); banmask.type = cl->netchan.remote_address.type; - SV_KickBanIP(cl->realip, banmask, reason); + SV_KickBanIP(&cl->realip, &banmask, reason); } else { memset(&banmask.address, 0xff, sizeof(banmask.address)); banmask.type = cl->netchan.remote_address.type; - SV_KickBanIP(cl->netchan.remote_address, banmask, reason); + SV_KickBanIP(&cl->netchan.remote_address, &banmask, reason); } } } @@ -927,7 +927,7 @@ void SV_FilterIP_f (void) return; } - if (NET_IsLoopBackAddress(banadr)) + if (NET_IsLoopBackAddress(&banadr)) { Con_Printf("You're not allowed to filter loopback!\n"); return; @@ -936,7 +936,7 @@ void SV_FilterIP_f (void) nb = svs.bannedips; while (nb) { - if (NET_CompareAdr(nb->adr, banadr) && NET_CompareAdr(nb->adrmask, banmask)) + if (NET_CompareAdr(&nb->adr, &banadr) && NET_CompareAdr(&nb->adrmask, &banmask)) { Con_Printf("%s is already banned\n", Cmd_Argv(1)); break; @@ -950,7 +950,7 @@ void SV_FilterIP_f (void) if (cl->state<=cs_zombie) continue; - if (filterban.value && NET_CompareAdrMasked(cl->netchan.remote_address, banadr, banmask)) + if (filterban.value && NET_CompareAdrMasked(&cl->netchan.remote_address, &banadr, &banmask)) SV_DropClient (cl); } @@ -973,9 +973,9 @@ void SV_BanList_f (void) while (nb) { if (nb->reason[0]) - Con_Printf("%s, %s\n", NET_AdrToStringMasked(adr, sizeof(adr), nb->adr, nb->adrmask), nb->reason); + Con_Printf("%s, %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask), nb->reason); else - Con_Printf("%s\n", NET_AdrToStringMasked(adr, sizeof(adr), nb->adr, nb->adrmask)); + Con_Printf("%s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask)); bancount++; nb = nb->next; } @@ -991,7 +991,7 @@ void SV_FilterList_f (void) while (nb) { - Con_Printf("%s\n", NET_AdrToStringMasked(adr, sizeof(adr), nb->adr, nb->adrmask)); + Con_Printf("%s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask)); filtercount++; nb = nb->next; } @@ -1025,10 +1025,10 @@ void SV_Unban_f (void) while (nb) { nbnext = nb->next; - if (all || (NET_CompareAdr(nb->adr, unbanadr) && NET_CompareAdr(nb->adrmask, unbanmask))) + if (all || (NET_CompareAdr(&nb->adr, &unbanadr) && NET_CompareAdr(&nb->adrmask, &unbanmask))) { if (!all) - Con_Printf("unbanned %s\n", NET_AdrToStringMasked(adr, sizeof(adr), nb->adr, nb->adrmask)); + Con_Printf("unbanned %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask)); if (svs.bannedips == nb) svs.bannedips = nbnext; Z_Free(nb); @@ -1067,10 +1067,10 @@ void SV_Unfilter_f (void) while (nb) { nbnext = nb->next; - if (all || (NET_CompareAdr(nb->adr, unbanadr) && NET_CompareAdr(nb->adrmask, unbanmask))) + if (all || (NET_CompareAdr(&nb->adr, &unbanadr) && NET_CompareAdr(&nb->adrmask, &unbanmask))) { if (!all) - Con_Printf("unfiltered %s\n", NET_AdrToStringMasked(adr, sizeof(adr), nb->adr, nb->adrmask)); + Con_Printf("unfiltered %s\n", NET_AdrToStringMasked(adr, sizeof(adr), &nb->adr, &nb->adrmask)); if (svs.bannedips == nb) svs.bannedips = nbnext; Z_Free(nb); @@ -1108,9 +1108,9 @@ void SV_WriteIP_f (void) else s = "addip"; if (bi->reason[0]) - s = va("%s %s \"%s\"\n", s, NET_AdrToStringMasked(adr, sizeof(adr), bi->adr, bi->adrmask), bi->reason); + s = va("%s %s \"%s\"\n", s, NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask), bi->reason); else - s = va("%s %s\n", s, NET_AdrToStringMasked(adr, sizeof(adr), bi->adr, bi->adrmask)); + s = va("%s %s\n", s, NET_AdrToStringMasked(adr, sizeof(adr), &bi->adr, &bi->adrmask)); VFS_WRITE(f, s, strlen(s)); bi = bi->next; } @@ -1453,7 +1453,7 @@ void SV_Status_f (void) else Con_Printf ("current map : %s\n", sv.name); - Con_Printf("entities : %i/%i\n", sv.world.num_edicts, sv.world.max_edicts); + Con_Printf("entities : %i/%i (mem: %i/%i)\n", sv.world.num_edicts, sv.world.max_edicts, sv.world.progs->stringtablesize, sv.world.progs->stringtablemaxsize); if (svs.gametype == GT_PROGS) { int count = 0; @@ -1500,7 +1500,7 @@ void SV_Status_f (void) else if (cl->protocol == SCP_BAD) s = "bot"; else - s = NET_BaseAdrToString (adr, sizeof(adr), cl->netchan.remote_address); + s = NET_BaseAdrToString (adr, sizeof(adr), &cl->netchan.remote_address); Con_Printf (" %-16.16s", s); if (cl->state == cs_connected) { @@ -1533,7 +1533,7 @@ void SV_Status_f (void) else if (cl->protocol == SCP_BAD) s = "bot"; else - s = NET_BaseAdrToString (adr, sizeof(adr), cl->netchan.remote_address); + s = NET_BaseAdrToString (adr, sizeof(adr), &cl->netchan.remote_address); Con_Printf ("%s", s); l = 16 - strlen(s); for (j=0 ; jcontroller && drop->controller != drop) @@ -554,9 +556,9 @@ void SV_DropClient (client_t *drop) if (!drop->redirect && drop->state > cs_zombie) { if (drop->spectator) - Con_Printf ("Spectator %s removed\n",drop->name); + Con_Printf ("Spectator \"%s\" removed\n",drop->name); else - Con_Printf ("Client %s removed\n",drop->name); + Con_Printf ("Client \"%s\" removed\n",drop->name); } if (drop->download) @@ -627,6 +629,25 @@ void SV_DropClient (client_t *drop) drop->csqcentsequence = NULL; drop->csqcactive = false; + memset(&termmsg, 0, sizeof(termmsg)); + termmsg.data = termbuf; + termmsg.maxsize = sizeof(termbuf); + termmsg.cursize = 0; + if (ISQWCLIENT(drop) || ISNQCLIENT(drop)) + { + MSG_WriteByte(&termmsg, svc_disconnect); + } + else if (ISQ2CLIENT(drop)) + { + MSG_WriteByte(&termmsg, svcq2_disconnect); + } + else if (ISQ3CLIENT(drop)) + { + } + //send twice, to cover packetloss a little. + Netchan_Transmit (&drop->netchan, termmsg.cursize, termmsg.data, 10000); + Netchan_Transmit (&drop->netchan, termmsg.cursize, termmsg.data, 10000); + if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) //gamecode should do it all for us. { // send notification to all remaining clients @@ -1153,7 +1174,7 @@ void SVC_GetInfo (char *challenge, int fullstatus) } } - NET_SendPacket (NS_SERVER, resp-response, response, net_from); + NET_SendPacket (NS_SERVER, resp-response, response, &net_from); } #endif @@ -1181,7 +1202,7 @@ void SVC_InfoQ2 (void) snprintf (string, sizeof(string), "%16s %8s %2i/%2i\n", hostname.string, sv.name, count, (int)maxclients.value); } - Netchan_OutOfBandPrint (NS_SERVER, net_from, "info\n%s", string); + Netchan_OutOfBandPrint (NS_SERVER, &net_from, "info\n%s", string); } #endif @@ -1238,16 +1259,16 @@ void SVC_Log (void) if (seq == svs.logsequence-1 || !sv_fraglogfile) { // they already have this data, or we aren't logging frags data[0] = A2A_NACK; - NET_SendPacket (NS_SERVER, 1, data, net_from); + NET_SendPacket (NS_SERVER, 1, data, &net_from); return; } - Con_DPrintf ("sending log %i to %s\n", svs.logsequence-1, NET_AdrToString(adr, sizeof(adr), net_from)); + Con_DPrintf ("sending log %i to %s\n", svs.logsequence-1, NET_AdrToString(adr, sizeof(adr), &net_from)); sprintf (data, "stdlog %i\n", svs.logsequence-1); strcat (data, (char *)svs.log_buf[((svs.logsequence-1)&1)]); - NET_SendPacket (NS_SERVER, strlen(data)+1, data, net_from); + NET_SendPacket (NS_SERVER, strlen(data)+1, data, &net_from); } /* @@ -1263,7 +1284,7 @@ void SVC_Ping (void) data = A2A_ACK; - NET_SendPacket (NS_SERVER, 1, &data, net_from); + NET_SendPacket (NS_SERVER, 1, &data, &net_from); } //from net_from @@ -1279,7 +1300,7 @@ int SV_NewChallenge (void) // see if we already have a challenge for this ip for (i = 0 ; i < MAX_CHALLENGES ; i++) { - if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr)) + if (NET_CompareBaseAdr (&net_from, &svs.challenges[i].adr)) return svs.challenges[i].challenge; if (svs.challenges[i].time < oldestTime) { @@ -1325,7 +1346,7 @@ void SVC_GetChallenge (void) // see if we already have a challenge for this ip for (i = 0 ; i < MAX_CHALLENGES ; i++) { - if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr)) + if (NET_CompareBaseAdr (&net_from, &svs.challenges[i].adr)) break; if (svs.challenges[i].time < oldestTime) { @@ -1420,13 +1441,13 @@ void SVC_GetChallenge (void) #endif } if (sv_listen_qw.value || (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM)) - Netchan_OutOfBand(NS_SERVER, net_from, over-buf, buf); + Netchan_OutOfBand(NS_SERVER, &net_from, over-buf, buf); if (sv_listen_dp.value && (sv_listen_nq.value || sv_bigcoords.value || !sv_listen_qw.value)) { //dp (protocol6 upwards) can respond to this (and fte won't get confused because the challenge will be wrong) buf = va("challenge "DISTRIBUTION"%i", svs.challenges[i].challenge); - Netchan_OutOfBand(NS_SERVER, net_from, strlen(buf)+1, buf); + Netchan_OutOfBand(NS_SERVER, &net_from, strlen(buf)+1, buf); } #ifdef Q3SERVER if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) @@ -1434,7 +1455,7 @@ void SVC_GetChallenge (void) if (sv_listen_q3.value) { buf = va("challengeResponse %i", svs.challenges[i].challenge); - Netchan_OutOfBand(NS_SERVER, net_from, strlen(buf), buf); + Netchan_OutOfBand(NS_SERVER, &net_from, strlen(buf), buf); } } #endif @@ -1469,7 +1490,7 @@ void SV_GetNewSpawnParms(client_t *cl) } } -void VARGS SV_OutOfBandPrintf (int q2, netadr_t adr, char *format, ...) +void VARGS SV_OutOfBandPrintf (int q2, netadr_t *adr, char *format, ...) { va_list argptr; char string[8192]; @@ -1491,7 +1512,7 @@ void VARGS SV_OutOfBandPrintf (int q2, netadr_t adr, char *format, ...) Netchan_OutOfBand (NS_SERVER, adr, strlen(string), (qbyte *)string); } -void VARGS SV_OutOfBandTPrintf (int q2, netadr_t adr, int language, translation_t text, ...) +void VARGS SV_OutOfBandTPrintf (int q2, netadr_t *adr, int language, translation_t text, ...) { va_list argptr; char string[8192]; @@ -1519,7 +1540,7 @@ qboolean SV_ChallengePasses(int challenge) int i; for (i=0 ; istate == cs_free) continue; - if (NET_CompareBaseAdr (adr, cl->netchan.remote_address) + if (NET_CompareBaseAdr (&adr, &cl->netchan.remote_address) && ( cl->netchan.qport == qport || adr.port == cl->netchan.remote_address.port )) { if (cl->state == cs_connected) { if (cl->protocol != protocol) - Con_Printf("%s: diff prot connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + Con_Printf("%s: diff prot connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr)); else - Con_Printf("%s:dup connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + Con_Printf("%s:dup connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr)); SV_DropClient(cl); /* @@ -2137,12 +2158,12 @@ client_t *SVC_DirectConnect(void) } else if (cl->state == cs_zombie) { - Con_Printf ("%s:reconnect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + Con_Printf ("%s:reconnect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr)); SV_DropClient (cl); } else { - Con_Printf ("%s:reconnect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + Con_Printf ("%s:reconnect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr)); // SV_DropClient (cl); } break; @@ -2268,14 +2289,14 @@ client_t *SVC_DirectConnect(void) if (!svprogfuncs) { SV_RejectMessage (protocol, "\nserver is full\n\n"); - Con_Printf ("%s:full connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + Con_Printf ("%s:full connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr)); } else { if (spectator && spectators >= maxspectators.ival) { SV_RejectMessage (protocol, "\nserver is full (%i of %i spectators)\n\n", spectators, maxspectators.ival); - Con_Printf ("%s:full connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + Con_Printf ("%s:full connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr)); } else if (!spectator && clients >= maxclients.ival) SV_RejectMessage (protocol, "\nserver is full (%i of %i players)\n\n", clients, maxclients.ival); @@ -2329,7 +2350,7 @@ client_t *SVC_DirectConnect(void) temp.edict = ent; { - char *reject = SV_CheckRejectConnection(adr, userinfo[0], protocol, protextsupported, protextsupported2, guid); + char *reject = SV_CheckRejectConnection(&adr, userinfo[0], protocol, protextsupported, protextsupported2, guid); if (reject) { SV_RejectMessage(protocol, "%s", reject); @@ -2381,7 +2402,7 @@ client_t *SVC_DirectConnect(void) } newcl->zquake_extensions &= SUPPORTED_Z_EXTENSIONS; - Netchan_Setup (NS_SERVER, &newcl->netchan, adr, qport); + Netchan_Setup (NS_SERVER, &newcl->netchan, &adr, qport); if (huffcrc) newcl->netchan.compress = true; @@ -2506,13 +2527,13 @@ client_t *SVC_DirectConnect(void) else //measure this guy in minuites. s = va(langtext(STL_SHORTGREETING, newcl->language), newcl->name, (int)(rs.timeonserver/60)); - SV_OutOfBandPrintf (protocol == SCP_QUAKE2, adr, s); + SV_OutOfBandPrintf (protocol == SCP_QUAKE2, &adr, s); } else if (!cl->istobeloaded) { SV_GetNewSpawnParms(newcl); - SV_OutOfBandTPrintf (protocol == SCP_QUAKE2, adr, newcl->language, STL_FIRSTGREETING, newcl->name, (int)rs.timeonserver); + SV_OutOfBandTPrintf (protocol == SCP_QUAKE2, &adr, newcl->language, STL_FIRSTGREETING, newcl->name, (int)rs.timeonserver); } //else loaded players already have their initial parms set } @@ -2693,7 +2714,7 @@ void SVC_RemoteCommand (void) char *br = SV_BannedReason(&net_from); if (br) { - Con_Printf ("Rcon from banned ip %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + Con_Printf ("Rcon from banned ip %s\n", NET_AdrToString (adr, sizeof(adr), &net_from)); return; } } @@ -2728,7 +2749,7 @@ void SVC_RemoteCommand (void) Con_Printf ("Rcon from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), net_message.data+4); + , NET_AdrToString (adr, sizeof(adr), &net_from), net_message.data+4); SV_BeginRedirect (RD_PACKET, LANGDEFAULT); @@ -2741,7 +2762,7 @@ void SVC_RemoteCommand (void) Con_Printf("Rcon was too long\n"); SV_EndRedirect (); Con_Printf ("Rcon from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), "Was too long - possible buffer overflow attempt"); + , NET_AdrToString (adr, sizeof(adr), &net_from), "Was too long - possible buffer overflow attempt"); return; } strcat (remaining, Cmd_Argv(i) ); @@ -2758,7 +2779,7 @@ void SVC_RemoteCommand (void) #endif Con_Printf ("Bad rcon from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), net_message.data+4); + , NET_AdrToString (adr, sizeof(adr), &net_from), net_message.data+4); SV_BeginRedirect (RD_PACKET, LANGDEFAULT); @@ -2769,7 +2790,7 @@ void SVC_RemoteCommand (void) { Con_Printf ("Rcon from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), net_message.data+4); + , NET_AdrToString (adr, sizeof(adr), &net_from), net_message.data+4); SV_BeginRedirect (RD_PACKET, LANGDEFAULT); @@ -2782,7 +2803,7 @@ void SVC_RemoteCommand (void) Con_Printf("Rcon was too long\n"); SV_EndRedirect (); Con_Printf ("Rcon from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), "Was too long - possible buffer overflow attempt"); + , NET_AdrToString (adr, sizeof(adr), &net_from), "Was too long - possible buffer overflow attempt"); return; } strcat (remaining, Cmd_Argv(i) ); @@ -2822,10 +2843,10 @@ void SVC_RealIP (void) if (svs.clients[slotnum].realip_status) return; - if (NET_AddressSmellsFunny(net_from)) + if (NET_AddressSmellsFunny(&net_from)) { - Con_Printf("funny realip address: %s, ", NET_AdrToString(adr, sizeof(adr), net_from)); - Con_Printf("proxy address: %s\n", NET_AdrToString(adr, sizeof(adr), svs.clients[slotnum].netchan.remote_address)); + Con_Printf("funny realip address: %s, ", NET_AdrToString(adr, sizeof(adr), &net_from)); + Con_Printf("proxy address: %s\n", NET_AdrToString(adr, sizeof(adr), &svs.clients[slotnum].netchan.remote_address)); return; } @@ -2854,7 +2875,7 @@ void SVC_ACK (void) { if (svs.clients[slotnum].state) { - if (svs.clients[slotnum].realip_status == 1 && NET_CompareAdr(svs.clients[slotnum].realip, net_from)) + if (svs.clients[slotnum].realip_status == 1 && NET_CompareAdr(&svs.clients[slotnum].realip, &net_from)) { if (!*Cmd_Argv(1)) svs.clients[slotnum].realip_status = 2; @@ -2865,13 +2886,13 @@ void SVC_ACK (void) } else { - Netchan_OutOfBandPrint(NS_SERVER, net_from, "realip not accepted. Please stop hacking.\n"); + Netchan_OutOfBandPrint(NS_SERVER, &net_from, "realip not accepted. Please stop hacking.\n"); } return; } } } - Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from)); } //returns false to block replies @@ -2915,7 +2936,7 @@ qboolean SV_ConnectionlessPacket (void) if (net_message.cursize >= MAX_QWMSGLEN) //add a null term in message space { - Con_Printf("Oversized packet from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + Con_Printf("Oversized packet from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from)); net_message.cursize=MAX_QWMSGLEN-1; } net_message.data[net_message.cursize] = '\0'; //terminate it properly. Just in case. @@ -2973,7 +2994,7 @@ qboolean SV_ConnectionlessPacket (void) #endif if (secure.value) //FIXME: possible problem for nq clients when enabled { - Netchan_OutOfBandPrint (NS_SERVER, net_from, "%c\nThis server requires client validation.\nPlease use the "DISTRIBUTION" validation program\n", A2C_PRINT); + Netchan_OutOfBandPrint (NS_SERVER, &net_from, "%c\nThis server requires client validation.\nPlease use the "DISTRIBUTION" validation program\n", A2C_PRINT); } else { @@ -3012,8 +3033,7 @@ qboolean SV_ConnectionlessPacket (void) unsigned int ct = Sys_Milliseconds(); if (ct - lt > 5*1000) { - Con_Printf ("bad connectionless packet from %s: \"%s\"\n" - , NET_AdrToString (adr, sizeof(adr), net_from), c); + Con_Printf ("bad connectionless packet from %s: \"%s\"\n", NET_AdrToString (adr, sizeof(adr), &net_from), c); lt = ct; } } @@ -3099,7 +3119,7 @@ qboolean SVNQ_ConnectionlessPacket(void) SZ_Clear(&sb); MSG_WriteLong(&sb, BigLong(NETFLAG_ACK | 8)); MSG_WriteLong(&sb, sequence); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); /*resend the cmd request, cos if they didn't send it then it must have gotten dropped. @@ -3114,7 +3134,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteString(&sb, va("cmd challengeconnect %i %i\n", SV_NewChallenge(), 1/*MOD_PROQUAKE*/)); *(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); return true; } @@ -3139,7 +3159,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteByte(&sb, CCREP_REJECT); MSG_WriteString(&sb, "Incorrect game\n"); *(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); return false; //not our game. } if (MSG_ReadByte() != NET_PROTOCOL_VERSION) @@ -3149,7 +3169,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteByte(&sb, CCREP_REJECT); MSG_WriteString(&sb, "Incorrect version\n"); *(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); return false; //not our version... } mod = MSG_ReadByte(); @@ -3174,7 +3194,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteByte(&sb, 1/*MOD_PROQUAKE*/); MSG_WriteByte(&sb, 10 * 3.50/*MOD_PROQUAKE_VERSION*/); *(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); SZ_Clear(&sb); @@ -3185,7 +3205,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteString(&sb, va("cmd challengeconnect %i %i %i %i %i\n", SV_NewChallenge(), mod, modver, flags, passwd)); *(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); /*don't worry about repeating, the nop case above will recover it*/ } else @@ -3208,7 +3228,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteLong (&sb, 0); MSG_WriteByte (&sb, CCREP_SERVER_INFO); if (NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0)) - MSG_WriteString (&sb, NET_AdrToString (buffer2, sizeof(buffer2), localaddr)); + MSG_WriteString (&sb, NET_AdrToString (buffer2, sizeof(buffer2), &localaddr)); else MSG_WriteString (&sb, "unknown"); active = 0; @@ -3221,7 +3241,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteByte (&sb, maxclients.value); MSG_WriteByte (&sb, NET_PROTOCOL_VERSION); *(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); return true; case CCREQ_PLAYER_INFO: /*one request per player, ouch ouch ouch, what will it make of 32 players, I wonder*/ @@ -3249,7 +3269,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteString (&sb, ""); /*player's address, leave blank, don't spam that info as it can result in personal attacks exploits*/ } *(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); return true; case CCREQ_RULE_INFO: /*lol, nq is evil*/ @@ -3289,7 +3309,7 @@ qboolean SVNQ_ConnectionlessPacket(void) MSG_WriteString (&sb, rval); } *(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from); return true; } return false; @@ -3337,7 +3357,7 @@ bannedips_t *SV_GetBannedAddressEntry (netadr_t *a) bannedips_t *banip; for (banip = svs.bannedips; banip; banip=banip->next) { - if (NET_CompareAdrMasked(*a, banip->adr, banip->adrmask)) + if (NET_CompareAdrMasked(a, &banip->adr, &banip->adrmask)) return banip; } return NULL; @@ -3353,12 +3373,12 @@ char *SV_BannedReason (netadr_t *a) char *reason = filterban.value?NULL:""; //"" = banned with no explicit reason bannedips_t *banip; - if (NET_IsLoopBackAddress(*a)) + if (NET_IsLoopBackAddress(a)) return NULL; // never filter loopback for (banip = svs.bannedips; banip; banip=banip->next) { - if (NET_CompareAdrMasked(*a, banip->adr, banip->adrmask)) + if (NET_CompareAdrMasked(a, &banip->adr, &banip->adrmask)) { switch(banip->type) { @@ -3386,7 +3406,7 @@ void SV_OpenRoute_f(void) sprintf(data, "\xff\xff\xff\xff%c", S2C_CONNECTION); - Netchan_OutOfBandPrint(NS_SERVER, to, "hello"); + Netchan_OutOfBandPrint(NS_SERVER, &to, "hello"); // NET_SendPacket (strlen(data)+1, data, to); } @@ -3489,9 +3509,9 @@ qboolean SV_ReadPackets (float *delay) if (banreason) { if (*banreason) - Netchan_OutOfBandPrint(NS_SERVER, net_from, "%cYou are banned: %s\n", A2C_PRINT, banreason); + Netchan_OutOfBandPrint(NS_SERVER, &net_from, "%cYou are banned: %s\n", A2C_PRINT, banreason); else - Netchan_OutOfBandPrint(NS_SERVER, net_from, "%cYou are banned\n", A2C_PRINT); + Netchan_OutOfBandPrint(NS_SERVER, &net_from, "%cYou are banned\n", A2C_PRINT); continue; } @@ -3523,7 +3543,7 @@ qboolean SV_ReadPackets (float *delay) { if (cl->state == cs_free) continue; - if (!NET_CompareBaseAdr (net_from, cl->netchan.remote_address)) + if (!NET_CompareBaseAdr (&net_from, &cl->netchan.remote_address)) continue; #ifdef NQPROT if (ISNQCLIENT(cl) && cl->netchan.remote_address.port == net_from.port) @@ -4395,7 +4415,7 @@ void Master_Heartbeat (void) string[0] = A2A_PING; string[1] = 0; if (sv.state) - NET_SendPacket (NS_SERVER, 2, string, sv_masterlist[i].adr); + NET_SendPacket (NS_SERVER, 2, string, &sv_masterlist[i].adr); break; default: break; @@ -4426,20 +4446,20 @@ void Master_Heartbeat (void) } if (sv_reportheartbeats.value) - Con_Printf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr), sv_masterlist[i].cv.string); + Con_Printf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), &sv_masterlist[i].adr), sv_masterlist[i].cv.string); - NET_SendPacket (NS_SERVER, strlen(string), string, sv_masterlist[i].adr); + NET_SendPacket (NS_SERVER, strlen(string), string, &sv_masterlist[i].adr); } break; case MP_DARKPLACES: if (sv_listen_dp.value || sv_listen_nq.value) //set listen to 1 to allow qw connections, 2 to allow nq connections too. { if (sv_reportheartbeats.value) - Con_Printf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), sv_masterlist[i].adr), sv_masterlist[i].cv.string); + Con_Printf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), &sv_masterlist[i].adr), sv_masterlist[i].cv.string); { char *str = "\377\377\377\377heartbeat DarkPlaces\x0A"; - NET_SendPacket (NS_SERVER, strlen(str), str, sv_masterlist[i].adr); + NET_SendPacket (NS_SERVER, strlen(str), str, &sv_masterlist[i].adr); } } break; @@ -4517,9 +4537,9 @@ void Master_Shutdown (void) { case MP_QUAKEWORLD: if (sv_reportheartbeats.value) - Con_Printf ("Sending shutdown 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); + NET_SendPacket (NS_SERVER, strlen(string), string, &sv_masterlist[i].adr); break; //dp has no shutdown default: @@ -4934,7 +4954,7 @@ void SV_Init (quakeparms_t *parms) PM_Init (); #ifdef PLUGINS - Plug_Init(); + Plug_Initialise(true); #endif Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); diff --git a/engine/server/sv_master.c b/engine/server/sv_master.c index 91e2a2279..bafada9d2 100644 --- a/engine/server/sv_master.c +++ b/engine/server/sv_master.c @@ -95,7 +95,7 @@ void SVM_Heartbeat(netadr_t *adr, int numclients, float validuntil) for (server = svm.firstserver; server; server = server->next) { - if (NET_CompareAdr(server->adr , *adr)) + if (NET_CompareAdr(&server->adr, adr)) break; } if (!server) //not found diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index d2104be06..2c85a6d86 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -683,7 +683,7 @@ typedef struct #define SORT_NO 0 #define SORT_BY_DATE 1 -int Sys_listdirFound(const char *fname, int fsize, void *uptr, struct searchpath_s *spath) +int QDECL Sys_listdirFound(const char *fname, int fsize, void *uptr, struct searchpath_s *spath) { file_t *f; dir_t *dir = uptr; @@ -2417,7 +2417,7 @@ void SV_MVDStream_Poll(void) } SockadrToNetadr(&addr, &na); - ip = NET_AdrToString(adrbuf, sizeof(adrbuf), na); + ip = NET_AdrToString(adrbuf, sizeof(adrbuf), &na); Con_Printf("MVD streaming client attempting to connect from %s\n", ip); SV_MVD_InitPendingStream(client, ip); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 81d3272c7..a97de6f24 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -69,7 +69,7 @@ void SV_FlushRedirect (void) send[4] = A2C_PRINT; memcpy (send+5, outputbuf, strlen(outputbuf)+1); - NET_SendPacket (NS_SERVER, strlen(send)+1, send, net_from); + NET_SendPacket (NS_SERVER, strlen(send)+1, send, &net_from); } else if (sv_redirected == RD_CLIENT) { diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index 7cd83e36b..b0512d444 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -661,7 +661,32 @@ static void Friendly_Crash_Handler(int sig) fd = open("crash.log", O_WRONLY|O_CREAT|O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (fd != -1) { - write(fd, "Crash Log:\n", 11); + time_t rawtime; + struct tm * timeinfo; + char tbuffer [80]; + + time (&rawtime); + timeinfo = localtime (&rawtime); + strftime (buffer, sizeof(buffer), "Time: %Y-%m-%d %H:%M:%S\n",timeinfo); + write(fd, buffer, strlen(buffer)); + + Q_snprintf(buffer, sizeof(buffer), "Binary: "__DATE__" "__TIME__"\n"); + write(fd, buffer, strlen(buffer)); + Q_snprintf(buffer, sizeof(buffer), "Ver: %i.%02i%s\n", FTE_VER_MAJOR, FTE_VER_MINOR +#ifdef OFFICIAL_RELEASE + " (official)"); +#else + ""); +#endif + write(fd, buffer, strlen(buffer)); +#ifdef SVNREVISION + if (strcmp(STRINGIFY(SVNREVISION), "-")) + { + Q_snprintf(buffer, sizeof(buffer), "Revision: %s\n", SVNREVISION); + write(fd, buffer, strlen(buffer)); + } +#endif + size = backtrace(array, 10); backtrace_symbols_fd(array, size, fd); write(fd, "\n", 1); @@ -696,7 +721,7 @@ int main(int argc, char *argv[]) parms.argv = com_argv; #ifdef __linux__ - if (COM_CheckParm("-dumpstack")) + if (!COM_CheckParm("-nodumpstack")) { signal(SIGILL, Friendly_Crash_Handler); signal(SIGFPE, Friendly_Crash_Handler); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 5f74e1f76..d516fd926 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -176,7 +176,7 @@ qboolean SV_CheckRealIP(client_t *client, qboolean force) if (client->realip_status == 1) { msg = va("\xff\xff\xff\xff%c %i", A2A_PING, client->realip_ping); - NET_SendPacket(NS_SERVER, strlen(msg), msg, client->realip); + NET_SendPacket(NS_SERVER, strlen(msg), msg, &client->realip); } else { @@ -2025,7 +2025,7 @@ void SV_NextChunkedDownload(unsigned int chunknum, int ezpercent, int ezfilenum) if (msg == &msg_oob) { - Netchan_OutOfBand(NS_SERVER, host_client->netchan.remote_address, msg_oob.cursize, msg_oob.data); + Netchan_OutOfBand(NS_SERVER, &host_client->netchan.remote_address, msg_oob.cursize, msg_oob.data); Netchan_Block(&host_client->netchan, msg_oob.cursize, SV_RateForClient(host_client)); } } @@ -2128,7 +2128,7 @@ void SV_NextDownload_f (void) } -void VARGS OutofBandPrintf(netadr_t where, char *fmt, ...) +void VARGS OutofBandPrintf(netadr_t *where, char *fmt, ...) { va_list argptr; char send[1024]; @@ -2184,7 +2184,7 @@ void SV_NextUpload (void) } Con_Printf("Receiving %s from %d...\n", host_client->uploadfn, host_client->userid); if (host_client->remote_snap) - OutofBandPrintf(host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid); + OutofBandPrintf(&host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid); } VFS_WRITE (host_client->upload, net_message.data + msg_readcount, size); @@ -2210,7 +2210,7 @@ void SV_NextUpload (void) p++; else p = host_client->uploadfn; - OutofBandPrintf(host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n", + OutofBandPrintf(&host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n", host_client->uploadfn, p); } *host_client->uploadfn = 0; //don't let it get overwritten again @@ -5063,7 +5063,7 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC) host_client = oldhost; SV_EndRedirect (); Con_Printf ("cmd from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), "Was too long - possible buffer overflow attempt"); + , NET_AdrToString (adr, sizeof(adr), &net_from), "Was too long - possible buffer overflow attempt"); return; } strcat (remaining, Cmd_Argv(i) ); @@ -5475,7 +5475,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) { SV_BroadcastTPrintf(PRINT_HIGH, STL_SPEEDCHEATKICKED, - host_client->name, NET_AdrToString(adr, sizeof(adr), host_client->netchan.remote_address)); + host_client->name, NET_AdrToString(adr, sizeof(adr), &host_client->netchan.remote_address)); host_client->drop = true; //drop later } } diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 432d12082..112c427c4 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -707,10 +707,10 @@ static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn, case G_CVAR_REGISTER:// ( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ); if (arg[0]) - VALIDATEPOINTER(arg[0], sizeof(vmcvar_t)); + VALIDATEPOINTER(arg[0], sizeof(q3vmcvar_t)); return VMQ3_Cvar_Register(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3])); case G_CVAR_UPDATE:// ( vmCvar_t *vmCvar ); - VALIDATEPOINTER(arg[0], sizeof(vmcvar_t)); + VALIDATEPOINTER(arg[0], sizeof(q3vmcvar_t)); return VMQ3_Cvar_Update(VM_POINTER(arg[0])); case G_CVAR_SET:// ( const char *var_name, const char *value ); @@ -2670,12 +2670,12 @@ client_t *SVQ3_FindEmptyPlayerSlot(void) } return NULL; } -client_t *SVQ3_FindExistingPlayerByIP(netadr_t na, int qport) +client_t *SVQ3_FindExistingPlayerByIP(netadr_t *na, int qport) { int i; for (i = 0; i < sv.allocated_client_slots; i++) { - if (svs.clients[i].state && NET_CompareAdr(svs.clients[i].netchan.remote_address, na)) + if (svs.clients[i].state && NET_CompareAdr(&svs.clients[i].netchan.remote_address, na)) return &svs.clients[i]; } return NULL; @@ -3091,7 +3091,7 @@ qboolean SVQ3_HandleClient(void) continue; if (svs.clients[i].netchan.qport != qport) continue; - if (!NET_CompareBaseAdr(svs.clients[i].netchan.remote_address, net_from)) + if (!NET_CompareBaseAdr(&svs.clients[i].netchan.remote_address, &net_from)) continue; if (!ISQ3CLIENT(&svs.clients[i])) continue; @@ -3132,7 +3132,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and qport = atoi(Info_ValueForKey(userinfo, "qport")); challenge = atoi(Info_ValueForKey(userinfo, "challenge")); - cl = SVQ3_FindExistingPlayerByIP(net_from, qport); //use a duplicate first. + cl = SVQ3_FindExistingPlayerByIP(&net_from, qport); //use a duplicate first. if (!cl) cl = SVQ3_FindEmptyPlayerSlot(); @@ -3157,7 +3157,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and cls.challenge = challenge = 500; #endif Q_strncpyz(cl->userinfo, userinfo, sizeof(cl->userinfo)); - reason = NET_AdrToString(adr, sizeof(adr), net_from); + reason = NET_AdrToString(adr, sizeof(adr), &net_from); Info_SetValueForStarKey(cl->userinfo, "ip", reason, sizeof(cl->userinfo)); ret = VM_Call(q3gamevm, GAME_CLIENT_CONNECT, (int)(cl-svs.clients), false, false); @@ -3172,7 +3172,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and { Con_Printf("%s\n", reason); reason = va("\377\377\377\377print\n%s", reason); - NET_SendPacket (NS_SERVER, strlen(reason), reason, net_from); + NET_SendPacket (NS_SERVER, strlen(reason), reason, &net_from); return; } @@ -3181,7 +3181,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and cl->name = cl->namebuf; cl->team = cl->teambuf; SV_ExtractFromUserinfo(cl, true); - Netchan_Setup(NS_SERVER, &cl->netchan, net_from, qport); + Netchan_Setup(NS_SERVER, &cl->netchan, &net_from, qport); cl->netchan.outgoing_sequence = 1; cl->challenge = challenge; @@ -3189,7 +3189,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and cl->gamestatesequence = -1; - NET_SendPacket (NS_SERVER, 19, "\377\377\377\377connectResponse", net_from); + NET_SendPacket (NS_SERVER, 19, "\377\377\377\377connectResponse", &net_from); Huff_PreferedCompressionCRC();