------------------------------------------------------------------------

r4187 | acceptthis | 2013-02-04 04:52:32 +0000 (Mon, 04 Feb 2013) | 9 lines

fix particle effect index insanity.
.modelflags support.
fix laggy mvds issue.
replacementdeltas works in mvds.
fix issues with not knowing which mvd is currently being recorded.
input line now permanently functions as utf-8.
cope with double-chevron links in the input line.
Add support for ^{xxxx}, but don't generate it. can only cope with 16bit anyway.
fix skins issues.
------------------------------------------------------------------------


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4185 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-03-12 22:44:00 +00:00
parent 80ab34a8f2
commit 630af9dc7c
41 changed files with 952 additions and 393 deletions

View File

@ -256,7 +256,7 @@ int readdemobytes(int *readpos, void *data, int len)
endofdemo = true;
return 0;
}
len = demobuffersize;
// len = demobuffersize;
return 0;
}
memcpy(data, demobuffer+*readpos, len);
@ -503,6 +503,7 @@ readnext:
demo_flushbytes(demopos);
demopos = 0;
}
// read the time from the packet
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
@ -521,6 +522,7 @@ readnext:
Con_DPrintf("Not enough buffered\n");
demotime = olddemotime;
nextdemotime = demotime;
return 0;
}
else
{
@ -596,8 +598,11 @@ readnext:
{
if ((msecsadded || cls.netchan.incoming_sequence < 2) && olddemotime != demotime)
{
cls.netchan.incoming_sequence++;
cls.netchan.incoming_acknowledged++;
if (!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))
{
cls.netchan.incoming_sequence++;
cls.netchan.incoming_acknowledged++;
}
cls.netchan.frame_latency = 0;
cls.netchan.last_received = realtime; // just to happy timeout check
}
@ -607,18 +612,21 @@ readnext:
Host_Error ("CL_GetDemoMessage: cls.state != ca_active");
// get the msg type
if (!readdemobytes (&demopos, &c, sizeof(c)))
if (readdemobytes (&demopos, &c, sizeof(c)) != sizeof(c))
{
Con_DPrintf("Not enough buffered\n");
olddemotime = demtime+1;
return 0;
}
// Con_Printf("demo packet %x\n", (int)c);
switch (c&7)
{
case dem_cmd :
/* if (cls.demoplayback == DPB_MVD)
if (cls.demoplayback == DPB_MVD)
{
Con_Printf("mvd demos/qtv streams should not contain dem_cmd\n");
olddemotime = demtime+1;
CL_StopPlayback ();
/*
unsigned short samps;
unsigned char bits;
unsigned char rateid;
@ -653,11 +661,11 @@ readnext:
}
}
}
*/
return 0;
}
else
{*/
{
// user sent input
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
pcmd = &cl.frames[i].cmd[0];
@ -691,7 +699,7 @@ readnext:
cl.playerview[0].viewangles[i] = LittleFloat (f);
}
goto readnext;
/* }*/
}
break;
case dem_read:
@ -755,9 +763,17 @@ readit:
break;
case dem_set :
readdemobytes (&demopos, &i, 4);
cls.netchan.outgoing_sequence = LittleLong(i);
readdemobytes (&demopos, &i, 4);
if (readdemobytes (&demopos, &j, 4) != 4)
{
olddemotime = demtime;
return 0;
}
if (readdemobytes (&demopos, &i, 4) != 4)
{
olddemotime = demtime;
return 0;
}
cls.netchan.outgoing_sequence = LittleLong(j);
cls.netchan.incoming_sequence = LittleLong(i);
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
@ -1307,7 +1323,7 @@ void CL_Record_f (void)
continue;
#ifdef PEXT_LIGHTSTYLECOL
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7)
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7 && *cl_lightstyle[i].map)
{
MSG_WriteByte (&buf, svcfte_lightstylecol);
MSG_WriteByte (&buf, (unsigned char)i);
@ -1766,7 +1782,7 @@ void CL_QTVPoll (void)
if (*colon)
Con_Printf("streaming \"%s\" from qtv\n", colon);
else
Con_Printf("qtv connection established to %s\n", colon);
Con_Printf("qtv connection established to %s\n", qtvhostname);
streamavailable = true;
}

View File

@ -726,8 +726,13 @@ void CLFTE_ParseEntities(void)
// Con_Printf("CL: Dropped %i\n", i);
// }
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
cls.netchan.incoming_sequence++;
cls.netchan.incoming_acknowledged++;
}
#ifdef NQPROT
if (cls.protocol == CP_NETQUAKE)
else if (cls.protocol == CP_NETQUAKE)
{
int i;
for (i = 0; i < MAX_SPLITS; i++)
@ -740,12 +745,15 @@ void CLFTE_ParseEntities(void)
if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0]))
cl.numackframes--;
cl.ackframes[cl.numackframes++] = cls.netchan.incoming_sequence;
if (!cl.validsequence)
cl.ackframes[cl.numackframes++] = -1;
else
cl.ackframes[cl.numackframes++] = cls.netchan.incoming_sequence;
cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime;
if (cl.validsequence != cls.netchan.incoming_sequence-1)
Con_Printf("CLIENT: Dropped a frame\n");
// if (cl.validsequence != cls.netchan.incoming_sequence-1)
// Con_Printf("CLIENT: Dropped a frame\n");
}
#endif
@ -2977,7 +2985,7 @@ void CL_TransitionEntities (void)
packnew = &cl.frames[newf].packet_entities;
packold = &cl.frames[oldf].packet_entities;
// Con_Printf("%f %f %f\n", packold->servertime, servertime, packnew->servertime);
// Con_Printf("%f %f %f (%i)\n", packold->servertime, servertime, packnew->servertime, newff);
// Con_Printf("%f %f %f\n", cl.oldgametime, servertime, cl.gametime);
CL_TransitionPacketEntities(newff, packnew, packold, servertime);
@ -3053,6 +3061,7 @@ void CL_LinkPacketEntities (void)
static int flickertime;
static int flicker;
int trailef;
int modelflags;
pack = cl.currentpackentities;
if (!pack)
@ -3189,6 +3198,14 @@ void CL_LinkPacketEntities (void)
Con_DPrintf("Bad modelindex (%i)\n", state->modelindex);
continue;
}
//DP extension. .modelflags (which is sent in the high parts of effects) allows to specify exactly the q1-compatible flags.
//the extra bit allows for setting to 0.
//note that hexen2 has additional flags which cannot be expressed.
if (state->effects & 0xff800000)
modelflags = state->effects>>24;
else
modelflags = model->flags;
if (cl.model_precache_vwep[0])
{
@ -3276,7 +3293,7 @@ void CL_LinkPacketEntities (void)
#endif
// rotate binary objects locally
if (model && model->flags & MF_ROTATE)
if (modelflags & MF_ROTATE)
{
angles[0] = 0;
angles[1] = autorotate;
@ -3337,10 +3354,10 @@ void CL_LinkPacketEntities (void)
CL_AddVWeapModel (ent, model2);
// add automatic particle trails
if (!model || (!(model->flags&~MF_ROTATE) && model->particletrail<0 && model->particleeffect<0 && state->u.q1.traileffectnum==0))
if (!model || (!(modelflags&~MF_ROTATE) && model->particletrail<0 && model->particleeffect<0 && state->u.q1.traileffectnum==0))
continue;
if (!cls.allow_anyparticles && !(model->flags & ~MF_ROTATE))
if (!cls.allow_anyparticles && !(modelflags & ~MF_ROTATE))
continue;
if (le->isnew)
@ -3387,7 +3404,7 @@ void CL_LinkPacketEntities (void)
dclr[1] = 1.0;
dclr[2] = 0.25;
if (model->flags & MF_ROCKET)
if (modelflags & MF_ROCKET)
{
#ifdef warningmsg
#pragma warningmsg("Replace this flag on load for hexen2 models")
@ -3398,17 +3415,17 @@ void CL_LinkPacketEntities (void)
rad += r_lightflicker.value?((flicker + state->number)&31):0;
}
}
else if (model->flags & MFH2_FIREBALL)
else if (modelflags & MFH2_FIREBALL)
{
rad = 120 - (rand() % 20);
}
else if (model->flags & MFH2_ACIDBALL)
else if (modelflags & MFH2_ACIDBALL)
{
rad = 120 - (rand() % 20);
dclr[0] = 0.1;
dclr[1] = 0.2;
}
else if (model->flags & MFH2_SPIT)
else if (modelflags & MFH2_SPIT)
{
// as far as I can tell this effect inverses the light...
dclr[0] = -dclr[0];
@ -3423,7 +3440,7 @@ void CL_LinkPacketEntities (void)
memcpy(dl->axis, ent->axis, sizeof(dl->axis));
VectorCopy (ent->origin, dl->origin);
dl->die = (float)cl.time;
if (model->flags & MF_ROCKET)
if (modelflags & MF_ROCKET)
dl->origin[2] += 1; // is this even necessary
dl->radius = rad * r_rocketlight.value;
VectorCopy(dclr, dl->color);

View File

@ -102,6 +102,8 @@ void CL_SplitA_f(void)
char *c, *args;
c = Cmd_Argv(0);
args = COM_Parse(Cmd_Args());
if (!args)
return;
while(*args == ' ' || *args == '\t')
args++;
tmp = con_splitmodifier;

View File

@ -140,7 +140,7 @@ cvar_t cl_gunangley = SCVAR("cl_gunangley", "0");
cvar_t cl_gunanglez = SCVAR("cl_gunanglez", "0");
cvar_t cl_download_csprogs = CVARFD("cl_download_csprogs", "1", CVAR_NOTFROMSERVER, "Download updated client gamecode if available.");
cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "0", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files.");
cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "2", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files. 2 allows redirection only to named packages files.");
cvar_t cl_download_mapsrc = CVARD("cl_download_mapsrc", "", "Specifies an http location prefix for map downloads. EG: \"http://bigfoot.morphos-team.net/misc/quakemaps/\"");
cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Download and load packages as needed (does not affect games which do not use this package). 2=Do download and install permanently (use with caution!)");
cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining.");
@ -2900,7 +2900,7 @@ void CL_Download_f (void)
if (Cmd_IsInsecure()) //mark server specified downloads.
{
if (!strnicmp(url, "game", 4) || !stricmp(url, "progs.dat") || !stricmp(url, "menu.dat") || !stricmp(url, "csprogs.dat") || !stricmp(url, "qwprogs.dat") || strstr(url, "..") || strstr(url, ".dll") || strstr(url, ".so"))
if (!strnicmp(url, "game", 4) || !stricmp(url, "progs.dat") || !stricmp(url, "menu.dat") || !stricmp(url, "csprogs.dat") || !stricmp(url, "qwprogs.dat") || strstr(url, "..") || strstr(url, ".qvm") || strstr(url, ".dll") || strstr(url, ".so"))
{ //yes, I know the user can use a different progs from the one that is specified. If you leave it blank there will be no problem. (server isn't allowed to stuff progs cvar)
Con_Printf("Ignoring stuffed download of \"%s\" due to possible security risk\n", url);
return;
@ -2941,18 +2941,27 @@ void CL_DownloadSize_f(void)
}
}
else if (!strcmp(size, "r"))
{
{ //'download this file instead'
int allow = cl_download_redirection.ival;
redirection = Cmd_Argv(3);
dl = CL_DownloadFailed(rname, false);
if (cl_download_redirection.ival)
if (allow == 2)
{
char *ext = COM_FileExtension(redirection);
if (!strcmp(ext, "pak") || !strcmp(ext, "pk3") || !strcmp(ext, "pk4"))
allow = true;
else
allow = false;
}
if (allow)
{
Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", rname, redirection);
CL_CheckOrEnqueDownloadFile(redirection, NULL, dl->flags);
}
else
Con_Printf("Download of \"%s\" redirected to \"%s\". Prevented by allow_download_redirection.\n", rname, redirection);
Con_Printf("Download of \"%s\" redirected to \"%s\". Prevented by cl_download_redirection.\n", rname, redirection);
}
else
{
@ -3111,10 +3120,18 @@ void CL_Init (void)
extern void CL_SayTeam_f (void);
extern cvar_t baseskin;
extern cvar_t noskins;
char *ver;
cls.state = ca_disconnected;
Info_SetValueForStarKey (cls.userinfo[0], "*ver", version_string(), sizeof(cls.userinfo[0]));
#ifdef SVNREVISION
if (strcmp(SVNREVISION, "-"))
ver = va("%s v%i.%02i %s", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR, SVNREVISION);
else
#endif
ver = va("%s v%i.%02i", DISTRIBUTION, FTE_VER_MAJOR, FTE_VER_MINOR);
Info_SetValueForStarKey (cls.userinfo[0], "*ver", ver, sizeof(cls.userinfo[0]));
Info_SetValueForStarKey (cls.userinfo[1], "*ss", "1", sizeof(cls.userinfo[1]));
Info_SetValueForStarKey (cls.userinfo[2], "*ss", "1", sizeof(cls.userinfo[2]));
Info_SetValueForStarKey (cls.userinfo[3], "*ss", "1", sizeof(cls.userinfo[3]));
@ -3159,6 +3176,7 @@ void CL_Init (void)
Cvar_Register (&cl_anglespeedkey, cl_inputgroup);
Cvar_Register (&cl_shownet, cl_screengroup);
Cvar_Register (&cl_sbar, cl_screengroup);
Cvar_Register (&cl_pure, cl_screengroup);
Cvar_Register (&cl_hudswap, cl_screengroup);
Cvar_Register (&cl_maxfps, cl_screengroup);
Cvar_Register (&cl_idlefps, cl_screengroup);

View File

@ -678,7 +678,7 @@ void CL_DownloadFinished(void)
break;
}
}
for (i = 0; i < MAX_CSQCMODELS; i++) //go and load this model now.
for (i = 0; i < MAX_CSMODELS; i++) //go and load this model now.
{
if (!strcmp(cl.model_csqcname[i], filename))
{
@ -1186,7 +1186,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload)
endstage();
}
for (i=1 ; i<MAX_CSQCMODELS ; i++)
for (i=1 ; i<MAX_CSMODELS ; i++)
{
if (!cl.model_csqcname[i][0])
continue;
@ -4900,7 +4900,23 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags)
while ((t = strchr(msg, '{')))
{
u = strchr(msg, '}');
int c;
if (t > msg && t[-1] == '^')
{
for (c = 1; t-c > msg; c++)
{
if (t[-c] == '^')
break;
}
if (c & 1)
{
*t = '\0';
Q_strncatz(fullchatmessage, va("%s{", msg), sizeof(fullchatmessage));
msg = t+1;
continue;
}
}
u = strchr(t, '}');
if (u)
{
*t = 0;
@ -5143,10 +5159,10 @@ void CL_ParsePrecache(void)
{
int i, code = (unsigned short)MSG_ReadShort();
char *s = MSG_ReadString();
i = code & 0x1fff;
switch(code & 0xe000)
i = code & ~PC_TYPE;
switch(code & PC_TYPE)
{
case 0x0000:
case PC_MODEL:
if (i >= 1 && i < MAX_MODELS)
{
model_t *model;
@ -5162,9 +5178,9 @@ void CL_ParsePrecache(void)
else
Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_MODELS);
break;
case 0x4000:
case PC_UNUSED:
break;
case 0x8000:
case PC_SOUND:
if (i >= 1 && i < MAX_SOUNDS)
{
sfx_t *sfx;
@ -5179,10 +5195,17 @@ void CL_ParsePrecache(void)
else
Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_SOUNDS);
break;
case 0xC000:
if (i >= 1 && i < 1024)
case PC_PARTICLE:
if (i >= 1 && i < MAX_SSPARTICLESPRE)
{
if (cl.particle_ssname[i])
free(cl.particle_ssname[i]);
cl.particle_ssname[i] = strdup(s);
cl.particle_ssprecache[i] = 1+P_FindParticleType(s);
cl.particle_ssprecaches = true;
}
else
Con_Printf("svc_precache: particle index %i outside range %i...%i\n", i, 1, MAX_SSPARTICLESPRE);
break;
}
}

View File

@ -639,7 +639,7 @@ void CL_CalcClientTime(void)
{
float oldst = realtime;
if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD)
if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD && !(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))
{
extern float nextdemotime, olddemotime, demtime;
float f;

View File

@ -1879,6 +1879,23 @@ void CL_RefreshCustomTEnts(void)
int i;
for (i = 0; i < sizeof(customtenttype)/sizeof(customtenttype[0]); i++)
customtenttype[i].particleeffecttype = (!*customtenttype[i].name)?-1:P_FindParticleType(customtenttype[i].name);
if (cl.particle_ssprecaches)
{
for (i = 0; i <= MAX_SSPARTICLESPRE; i++)
{
if (cl.particle_ssname[i])
cl.particle_ssprecache[i] = 1+P_FindParticleType(cl.particle_ssname[i]);
}
}
if (cl.particle_csprecaches)
{
for (i = 0; i <= MAX_CSPARTICLESPRE; i++)
{
if (cl.particle_csname[i])
cl.particle_csprecache[i] = 1+P_FindParticleType(cl.particle_csname[i]);
}
}
}
void CL_ClearCustomTEnts(void)
{
@ -1897,18 +1914,26 @@ void CL_ClearCustomTEnts(void)
}
}
int CL_TranslateParticleFromServer(int sveffect)
int CL_TranslateParticleFromServer(int qceffect)
{
if (cl.maxparticleprecaches)
if (cl.particle_ssprecaches && qceffect >= 0 && qceffect < MAX_SSPARTICLESPRE)
{
/*proper precaches*/
return cl.particle_precache[sveffect].num;
return cl.particle_ssprecache[qceffect]-1;
}
else if (-qceffect >= 0 && -qceffect < MAX_CSPARTICLESPRE)
{
qceffect = -qceffect;
return cl.particle_csprecache[qceffect]-1;
}
else
{
return -1;
// else
// {
/*server and client must share an identical effectinfo list file (just "effect $name\n" lines)*/
return P_FindParticleType(COM_Effectinfo_ForNumber(sveffect));
}
// return P_FindParticleType(COM_Effectinfo_ForNumber(qceffect));
// }
}
void CL_ParseTrailParticles(void)

View File

@ -630,24 +630,22 @@ typedef struct
char model_name_vwep[MAX_VWEP_MODELS][MAX_QPATH];
char model_name[MAX_MODELS][MAX_QPATH];
char sound_name[MAX_SOUNDS][MAX_QPATH];
char *particle_ssname[MAX_SSPARTICLESPRE];
char image_name[Q2MAX_IMAGES][MAX_QPATH];
struct model_s *model_precache_vwep[MAX_VWEP_MODELS];
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS];
int particle_ssprecache[MAX_SSPARTICLESPRE]; //these are actually 1-based, so 0 can be used to lazy-init them. I cheat.
char model_csqcname[MAX_CSQCMODELS][MAX_QPATH];
struct model_s *model_csqcprecache[MAX_CSQCMODELS];
char model_csqcname[MAX_CSMODELS][MAX_QPATH];
struct model_s *model_csqcprecache[MAX_CSMODELS];
char *particle_csname[MAX_CSPARTICLESPRE];
int particle_csprecache[MAX_CSPARTICLESPRE]; //these are actually 1-based, so we can be lazy and do a simple negate.
qboolean model_precaches_added;
struct
{
int num;
char *name;
} *particle_precache;
unsigned int maxparticleprecaches;
qboolean particle_ssprecaches; //says to not try to do any dp-compat hacks.
qboolean particle_csprecaches; //says to not try to do any dp-compat hacks.
//used for q2 sky/configstrings
char skyname[MAX_QPATH];

View File

@ -949,9 +949,10 @@ int Con_DrawInput (int left, int right, int y, qboolean selactive, int selsx, in
i = text[key_linepos];
text[key_linepos] = 0;
cursor = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), true);
cursor = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), PFS_KEEPMARKUP | PFS_FORCEUTF8);
text[key_linepos] = i;
endmtext = COM_ParseFunString(CON_WHITEMASK, text+key_linepos, cursor, ((char*)maskedtext)+sizeof(maskedtext) - (char*)(cursor+1), true);
endmtext = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext) - sizeof(maskedtext[0]), PFS_KEEPMARKUP | PFS_FORCEUTF8);
// endmtext = COM_ParseFunString(CON_WHITEMASK, text+key_linepos, cursor, ((char*)maskedtext)+sizeof(maskedtext) - (char*)(cursor+1), PFS_KEEPMARKUP | PFS_FORCEUTF8);
endmtext[1] = 0;
@ -1055,7 +1056,11 @@ int Con_DrawInput (int left, int right, int y, qboolean selactive, int selsx, in
{
cmd = Cmd_CompleteCommand (text+cmdstart, true, true, i, NULL);
if (!cmd)
{
if (i <= 2)
con_commandmatch = 0;
break;
}
end = COM_ParseFunString((COLOR_GREEN<<CON_FGSHIFT), va("%s\t", cmd), end, (maskedtext+sizeof(maskedtext)/sizeof(maskedtext[0])-1-end)*sizeof(maskedtext[0]), true);
}
@ -1549,6 +1554,8 @@ static int Con_DrawConsoleLines(conline_t *l, int sx, int ex, int y, int top, qb
selendoffset = (s+i+1) - (conchar_t*)(l+1);
else
selendoffset = 0;
if (selendoffset > linelength)
selendoffset = linelength;
}
if (y <= selsy)
{

View File

@ -352,6 +352,24 @@ void CompleteCommand (qboolean force)
void Con_ExecuteLine(console_t *con, char *line)
{
qboolean waschat = false;
char deutf8[1024];
extern cvar_t com_parseutf8;
if (com_parseutf8.ival <= 0)
{
unsigned int unicode;
int err;
int len = 0;
while(*line)
{
unicode = utf8_decode(&err, line, &line);
if (com_parseutf8.ival < 0)
len += iso88591_encode(deutf8+len, unicode, sizeof(deutf8)-1 - len);
else
len += qchar_encode(deutf8+len, unicode, sizeof(deutf8)-1 - len);
}
deutf8[len] = 0;
line = deutf8;
}
con_commandmatch=1;
Con_Footerf(false, "");
@ -754,14 +772,26 @@ void Key_ConsoleRelease(int key, int unicode)
}
}
//move the cursor one char to the left. cursor must be within the 'start' string.
unsigned char *utf_left(unsigned char *start, unsigned char *cursor)
//if the referenced (trailing) chevron is doubled up, then it doesn't act as part of any markup and should be ignored for such things.
static qboolean utf_specialchevron(unsigned char *start, unsigned char *chev)
{
extern cvar_t com_parseutf8;
int count = 0;
while (chev >= start)
{
if (*chev-- == '^')
count++;
else
break;
}
return count&1;
}
//move the cursor one char to the left. cursor must be within the 'start' string.
static unsigned char *utf_left(unsigned char *start, unsigned char *cursor)
{
// extern cvar_t com_parseutf8;
if (cursor == start)
return cursor;
if (com_parseutf8.ival>0)
if (1)//com_parseutf8.ival>0)
{
cursor--;
while ((*cursor & 0xc0) == 0x80 && cursor > start)
@ -770,14 +800,16 @@ unsigned char *utf_left(unsigned char *start, unsigned char *cursor)
else
cursor--;
if (*cursor == ']' && cursor > start && cursor[-1] == '^')
//FIXME: should verify that the ^ isn't doubled.
if (*cursor == ']' && cursor > start && utf_specialchevron(start, cursor-1))
{
//just stepped onto a link
unsigned char *linkstart;
linkstart = cursor-1;
while(linkstart >= start)
{
if (linkstart[0] == '^' && linkstart[1] == '[')
//FIXME: should verify that the ^ isn't doubled.
if (utf_specialchevron(start, linkstart) && linkstart[1] == '[')
return linkstart;
linkstart--;
}
@ -787,20 +819,19 @@ unsigned char *utf_left(unsigned char *start, unsigned char *cursor)
}
//move the cursor one char to the right.
unsigned char *utf_right(unsigned char *cursor)
static unsigned char *utf_right(unsigned char *start, unsigned char *cursor)
{
extern cvar_t com_parseutf8;
// extern cvar_t com_parseutf8;
if (*cursor == '^' && cursor[1] == '[')
//FIXME: should make sure this is not doubled.
if (utf_specialchevron(start, cursor) && cursor[1] == '[')
{
//just stepped over a link
char *linkend;
linkend = cursor+2;
while(*linkend)
{
if (linkend[0] == '^' && linkend[1] == '^')
linkend += 2;
else if (linkend[0] == '^' && linkend[1] == ']')
if (utf_specialchevron(start, linkend) && linkend[1] == ']')
return linkend+2;
else
linkend++;
@ -808,7 +839,7 @@ unsigned char *utf_right(unsigned char *cursor)
return linkend;
}
if (com_parseutf8.ival>0)
if (1)//com_parseutf8.ival>0)
{
int skip = 1;
//figure out the length of the char
@ -851,6 +882,7 @@ void Key_Console (unsigned int unicode, int key)
{
extern cvar_t com_parseutf8;
char *clipText;
char utf8[8];
if (con_current->redirect)
{
@ -914,6 +946,7 @@ void Key_Console (unsigned int unicode, int key)
if (con_current->linebuffered)
con_current->linebuffered(con_current, key_lines[oldl]+1);
con_commandmatch = 0;
return;
}
@ -954,7 +987,7 @@ void Key_Console (unsigned int unicode, int key)
{
if (key_lines[edit_line][key_linepos])
{
key_linepos = utf_right(key_lines[edit_line] + key_linepos) - key_lines[edit_line];
key_linepos = utf_right(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - key_lines[edit_line];
return;
}
else
@ -965,7 +998,7 @@ void Key_Console (unsigned int unicode, int key)
{
if (key_lines[edit_line][key_linepos])
{
int charlen = utf_right(key_lines[edit_line] + key_linepos) - (key_lines[edit_line] + key_linepos);
int charlen = utf_right(key_lines[edit_line]+1, key_lines[edit_line] + key_linepos) - (key_lines[edit_line] + key_linepos);
memmove(key_lines[edit_line]+key_linepos, key_lines[edit_line]+key_linepos+charlen, strlen(key_lines[edit_line]+key_linepos+charlen)+1);
return;
}
@ -981,6 +1014,8 @@ void Key_Console (unsigned int unicode, int key)
memmove(key_lines[edit_line]+key_linepos-charlen, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+1);
key_linepos -= charlen;
}
if (!key_lines[edit_line][1])
con_commandmatch = 0;
return;
}
@ -997,6 +1032,8 @@ void Key_Console (unsigned int unicode, int key)
key_linepos = Q_strlen(key_lines[edit_line]);
key_lines[edit_line][0] = ']';
if (!key_lines[edit_line][1])
con_commandmatch = 0;
return;
}
@ -1007,6 +1044,7 @@ void Key_Console (unsigned int unicode, int key)
key_lines[edit_line][0] = ']';
key_lines[edit_line][1] = '\0';
key_linepos=1;
con_commandmatch = 0;
return;
}
do
@ -1136,32 +1174,12 @@ void Key_Console (unsigned int unicode, int key)
unicode |= 0xe080; // red char
}
if (com_parseutf8.ival>0 && unicode > 127)
unicode = utf8_encode(utf8, unicode, sizeof(utf8)-1);
if (unicode)
{
char utf8[8];
int l = utf8_encode(utf8, unicode, sizeof(utf8)-1);
if (l)
{
utf8[l] = 0;
Key_ConsoleInsert(utf8);
return;
}
unicode = '?';
utf8[unicode] = 0;
Key_ConsoleInsert(utf8);
}
else if (unicode >= 0xe000 && unicode <= 0xe0ff && !com_parseutf8.ival)
unicode -= 0xe000; //text line is quake-safe
else if (unicode >= ((com_parseutf8.ival<0)?256:128))
{
unicode = '?'; //sorry, char cannot be expressed using this encoding.
}
if (strlen(key_lines[edit_line])+1 < MAXCMDLINE-1)
{
memmove(key_lines[edit_line]+key_linepos+1, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+1);
key_lines[edit_line][key_linepos] = unicode;
key_linepos++;
}
}
//============================================================================

View File

@ -1550,7 +1550,7 @@ void MasterInfo_Refresh(void)
//Master_AddMaster("telefrag.me:27000",MT_MASTERQW, "Telefrag.ME");
//Master_AddMaster("master.teamdamage.com:27000", MT_MASTERQW, "TeamDamage");
Master_AddMaster("master.quakeservers.net:27000", MT_MASTERQW, "QuakeServers.net");
Master_AddMaster("masterserver.exhale.de:27000", MT_MASTERQW, "team exhale");
// Master_AddMaster("masterserver.exhale.de:27000", MT_MASTERQW, "team exhale");
Master_AddMaster("qwmaster.fodquake.net:27000", MT_MASTERQW, "Fodquake master server.");
Master_AddMaster("qwmaster.ocrana.de:27000", MT_MASTERQW, "Ocrana2 master server.");
Master_AddMaster("255.255.255.255:27500", MT_BCASTQW, "Nearby QuakeWorld UDP servers.");
@ -1578,7 +1578,7 @@ void MasterInfo_Refresh(void)
//Master_AddMaster("master.planetgloom.com:27900",MT_MASTERQ2, "Planetgloom.com");
//Master_AddMaster("master.q2servers.com:27900", MT_MASTERQ2, "q2servers.com");
Master_AddMaster("netdome.biz:27900", MT_MASTERQ2, "Netdome.biz");
Master_AddMaster("masterserver.exhale.de:27900",MT_MASTERQ2, "team exhale");
// Master_AddMaster("masterserver.exhale.de:27900",MT_MASTERQ2, "team exhale");
Master_AddMaster("255.255.255.255:27910", MT_BCASTQ2, "Nearby Quake2 UDP servers.");
#ifdef USEIPX
Master_AddMaster("00000000:ffffffffffff:27910", MT_BCASTQ2, "Nearby Quake2 IPX servers.");
@ -1589,7 +1589,7 @@ void MasterInfo_Refresh(void)
{
//Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake3", MT_MASTERHTTPQW, "gameaholic's Q3 master");
Master_AddMaster("master.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master server.");
Master_AddMaster("masterserver.exhale.de:27950", MT_MASTERQ3, "team exhale");
// Master_AddMaster("masterserver.exhale.de:27950", MT_MASTERQ3, "team exhale");
//Master_AddMaster("master3.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master3 server.");
Master_AddMaster("255.255.255.255:27960", MT_BCASTQ3, "Nearby Quake3 UDP servers.");
}

View File

@ -559,7 +559,7 @@ static model_t *CSQC_GetModelForIndex(int index)
return NULL;
else if (index > 0 && index < MAX_MODELS)
return cl.model_precache[index];
else if (index < 0 && index > -MAX_CSQCMODELS)
else if (index < 0 && index > -MAX_CSMODELS)
{
if (!cl.model_csqcprecache[-index])
cl.model_csqcprecache[-index] = Mod_ForName(cl.model_csqcname[-index], false);
@ -1391,7 +1391,7 @@ static void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars
case VF_VIEWPORT:
r_refdef.vrect.x = p[0];
r_refdef.vrect.y = p[1];
p+=3;
p = G_VECTOR(OFS_PARM2);
r_refdef.vrect.width = p[0];
r_refdef.vrect.height = p[1];
break;
@ -1701,7 +1701,7 @@ static int FindModel(char *name, int *free)
if (!name || !*name)
return 0;
for (i = 1; i < MAX_CSQCMODELS; i++)
for (i = 1; i < MAX_CSMODELS; i++)
{
if (!*cl.model_csqcname[i])
{
@ -1726,7 +1726,7 @@ static void csqc_setmodel(pubprogfuncs_t *prinst, csqcedict_t *ent, int modelind
ent->v->modelindex = modelindex;
if (modelindex < 0)
{
if (modelindex <= -MAX_CSQCMODELS)
if (modelindex <= -MAX_CSMODELS)
return;
ent->v->model = PR_SetString(prinst, cl.model_csqcname[-modelindex]);
if (!cl.model_csqcprecache[-modelindex])
@ -1936,6 +1936,7 @@ static void QCBUILTIN PF_cs_pointparticles (pubprogfuncs_t *prinst, struct globa
if (prinst->callargc < 4)
count = 1;
effectnum = CL_TranslateParticleFromServer(effectnum);
P_RunParticleEffectType(org, vel, count, effectnum);
}
@ -1950,14 +1951,13 @@ static void QCBUILTIN PF_cs_trailparticles (pubprogfuncs_t *prinst, struct globa
{
efnum = G_FLOAT(OFS_PARM1);
ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
efnum = CL_TranslateParticleFromServer(efnum);
}
else
{
efnum = G_FLOAT(OFS_PARM0)-1;
ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1);
}
efnum = CL_TranslateParticleFromServer(efnum);
if (!ent->entnum) //world trails are non-state-based.
pe->ParticleTrail(start, end, efnum, 0, NULL);
@ -1967,8 +1967,35 @@ static void QCBUILTIN PF_cs_trailparticles (pubprogfuncs_t *prinst, struct globa
static void QCBUILTIN PF_cs_particleeffectnum (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int i;
char *effectname = PR_GetStringOfs(prinst, OFS_PARM0);
//use the server's index first.
for (i = 1; i < MAX_SSPARTICLESPRE && cl.particle_ssname[i]; i++)
{
if (!strcmp(cl.particle_ssname[i], effectname))
{
G_FLOAT(OFS_RETURN) = i;
return;
}
}
//use the server's index first.
for (i = 1; i < MAX_CSPARTICLESPRE && cl.particle_csname[i]; i++)
{
if (!strcmp(cl.particle_csname[i], effectname))
{
G_FLOAT(OFS_RETURN) = -i;
return;
}
}
if (i < MAX_CSPARTICLESPRE)
{
free(cl.particle_csname[i]);
cl.particle_csname[i] = NULL;
cl.particle_csprecache[i] = 1+P_FindParticleType(effectname);
if (cl.particle_csprecache[i])
cl.particle_csname[i] = strdup(effectname);
}
if (csqc_isdarkplaces)
{
//keep the effectinfo synced between server and client.
@ -1986,13 +2013,7 @@ static void QCBUILTIN PF_cs_particleeffectquery (pubprogfuncs_t *prinst, struct
qboolean body = G_FLOAT(OFS_PARM1);
char retstr[8192];
if (csqc_isdarkplaces)
{
//keep the effectinfo synced between server and client.
id = CL_TranslateParticleFromServer(id);
}
else
id = id - 1;
id = CL_TranslateParticleFromServer(id);
if (pe->ParticleQuery && pe->ParticleQuery(id, body, retstr, sizeof(retstr)))
{
@ -2370,7 +2391,7 @@ static void QCBUILTIN PF_cs_getplayerkey (pubprogfuncs_t *prinst, struct globalv
if (pnum < 0 || pnum >= cl.allocated_client_slots)
ret = "";
else if (!strcmp(keyname, "viewentity")) //compat with DP. Yes, I know this is in the wrong place.
else if (!strcmp(keyname, "viewentity")) //compat with DP. Yes, I know this is in the wrong place. This is an evil hack.
{
ret = buffer;
sprintf(ret, "%i", pnum+1);
@ -2389,6 +2410,11 @@ static void QCBUILTIN PF_cs_getplayerkey (pubprogfuncs_t *prinst, struct globalv
ret = buffer;
sprintf(ret, "%i", cl.players[pnum].frags);
}
else if (!strcmp(keyname, "userid"))
{
ret = buffer;
sprintf(ret, "%i", cl.players[pnum].userid);
}
else if (!strcmp(keyname, "pl")) //packet loss
{
CheckSendPings();
@ -4255,7 +4281,7 @@ static struct {
{"drawline", PF_CL_drawline, 315}, // #315 void(float width, vector pos1, vector pos2) drawline (EXT_CSQC)
{"iscachedpic", PF_CL_is_cached_pic, 316}, // #316 float(string name) iscachedpic (EXT_CSQC)
{"precache_pic", PF_CL_precache_pic, 317}, // #317 string(string name, float trywad) precache_pic (EXT_CSQC)
{"draw_getimagesize", PF_CL_drawgetimagesize, 318}, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
{"drawgetimagesize", PF_CL_drawgetimagesize, 318}, // #318 vector(string picname) draw_getimagesize (EXT_CSQC)
{"freepic", PF_CL_free_pic, 319}, // #319 void(string name) freepic (EXT_CSQC)
//320
{"drawcharacter", PF_CL_drawcharacter, 320}, // #320 float(vector position, float character, vector scale, vector rgb, float alpha [, float flag]) drawcharacter (EXT_CSQC, [EXT_CSQC_???])
@ -5085,7 +5111,7 @@ void CSQC_RendererRestarted(void)
csqc_world.worldmodel = cl.worldmodel;
for (i = 0; i < MAX_CSQCMODELS; i++)
for (i = 0; i < MAX_CSMODELS; i++)
{
cl.model_csqcprecache[i] = NULL;
}
@ -5303,6 +5329,8 @@ qboolean CSQC_DrawView(void)
float mintic = 0.01;
double clframetime = host_frametime;
csqc_resortfrags = true;
if (!csqcg.draw_function || !csqcprogs || !cl.worldmodel)
return false;
@ -5341,8 +5369,6 @@ qboolean CSQC_DrawView(void)
if (cl.worldmodel)
R_LessenStains();
csqc_resortfrags = true;
if (!cl.paused)
{
if (csqcg.clientcommandframe)

View File

@ -674,6 +674,10 @@ static void QCBUILTIN PF_menu_cvar (pubprogfuncs_t *prinst, struct globalvars_s
G_FLOAT(OFS_RETURN) = vid.width;
else if (!strcmp(str, "vid_conheight"))
G_FLOAT(OFS_RETURN) = vid.height;
else if (!strcmp(str, "vid_pixwidth"))
G_FLOAT(OFS_RETURN) = vid.pixelwidth;
else if (!strcmp(str, "vid_pixheight"))
G_FLOAT(OFS_RETURN) = vid.pixelheight;
else
{
str = RemapCvarNameFromDPToFTE(str);
@ -884,6 +888,7 @@ static void QCBUILTIN PF_Remove_ (pubprogfuncs_t *prinst, struct globalvars_s *p
if (ed->isfree)
{
Con_DPrintf("Tried removing free entity\n");
PR_StackTrace(prinst);
return;
}
@ -1899,11 +1904,36 @@ void MP_Reload_f(void)
M_Reinit();
}
void MP_Breakpoint_f(void)
{
int wasset;
int isset;
char *filename = Cmd_Argv(1);
int line = atoi(Cmd_Argv(2));
if (!menuprogs)
{
Con_Printf("Menu not running\n");
return;
}
wasset = menuprogs->ToggleBreak(menuprogs, filename, line, 3);
isset = menuprogs->ToggleBreak(menuprogs, filename, line, 2);
if (wasset == isset)
Con_Printf("Breakpoint was not valid\n");
else if (isset)
Con_Printf("Breakpoint has been set\n");
else
Con_Printf("Breakpoint has been cleared\n");
}
void MP_RegisterCvarsAndCmds(void)
{
Cmd_AddCommand("coredump_menuqc", MP_CoreDump_f);
Cmd_AddCommand("menu_restart", MP_Reload_f);
Cmd_AddCommand("menu_cmd", MP_GameCommand_f);
Cmd_AddCommand("breakpoint_menu", MP_Breakpoint_f);
Cvar_Register(&forceqmenu, MENUPROGSGROUP);
Cvar_Register(&pr_menuqc_coreonerror, MENUPROGSGROUP);

View File

@ -2710,7 +2710,7 @@ void Surf_BuildLightmaps (void)
break;
Surf_BuildModelLightmaps(m);
}
for (j=1 ; j<MAX_CSQCMODELS ; j++)
for (j=1 ; j<MAX_CSMODELS ; j++)
{
m = cl.model_csqcprecache[j];
if (!m)

View File

@ -1310,7 +1310,7 @@ TRACE(("dbg: R_ApplyRenderer: reloading ALL models\n"));
}
#ifdef CSQC_DAT
for (i=1 ; i<MAX_CSQCMODELS ; i++)
for (i=1 ; i<MAX_CSMODELS ; i++)
{
if (!cl.model_csqcname[i][0])
break;
@ -1356,7 +1356,7 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
cl_static_entities[i].ent.model = NULL;
if (cl_static_entities[i].mdlidx < 0)
{
if (cl_static_entities[i].mdlidx > -MAX_CSQCMODELS)
if (cl_static_entities[i].mdlidx > -MAX_CSMODELS)
cl_static_entities[i].ent.model = cl.model_csqcprecache[-cl_static_entities[i].mdlidx];
}
else

View File

@ -733,7 +733,13 @@ void Sys_mkdir (char *path)
qboolean Sys_remove (char *path)
{
remove (path);
if (remove (path) != 0)
{
int e = errno;
if (e == ENOENT)
return true; //return success if it doesn't already exist.
return false;
}
return true;
}

View File

@ -1281,7 +1281,7 @@ TP_ParseFunChars
Doesn't check for overflows, so strlen(s) should be < MAX_MACRO_STRING
==============
*/
static char *TP_ParseFunChars (char *s, qbool chat)
static char *TP_ParseFunChars (char *s)
{
static char buf[MAX_MACRO_STRING];
char *out = buf;
@ -1346,11 +1346,6 @@ static char *TP_ParseFunChars (char *s, qbool chat)
continue;
}
}
if (!chat && *s == '^' && s[1] && s[1] != ' ') {
*out++ = s[1] | CON_HIGHCHARSMASK;
s += 2;
continue;
}
skip:
*out++ = *s++;
}
@ -3453,7 +3448,7 @@ void CL_Say (qboolean team, char *extra)
suppress = false;
s = TP_ParseMacroString (Cmd_Args());
Q_strncpyz (text, TP_ParseFunChars (s, true), sizeof(text));
Q_strncpyz (text, TP_ParseFunChars (s), sizeof(text));
sendtext[0] = 0;
if (team && !cl.spectator && cl_fakename.string[0] &&
@ -3462,7 +3457,7 @@ void CL_Say (qboolean team, char *extra)
char buf[1024];
Cmd_ExpandString (cl_fakename.string, buf, sizeof(buf), Cmd_ExecLevel, true, true);
strcpy (buf, TP_ParseMacroString (buf));
Q_snprintfz (sendtext, sizeof(sendtext), "\x0d%s: ", TP_ParseFunChars(buf, true));
Q_snprintfz (sendtext, sizeof(sendtext), "\x0d%s: ", TP_ParseFunChars(buf));
}
strlcat (sendtext, text, sizeof(sendtext));

View File

@ -520,9 +520,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_STANDARDLIGHTSTYLES 64
#define MAX_MODELS 1024 // these are sent over the net as bytes
#define MAX_SOUNDS 1024 // so they cannot be blindly increased
#define MAX_SSPARTICLESPRE 1024 // precached particle effect names, for server-side pointparticles/trailparticles.
#define MAX_VWEP_MODELS 32
#define MAX_CSQCMODELS 256 // these live entirly clientside
#define MAX_CSMODELS 512 // these live entirly clientside
#define MAX_CSPARTICLESPRE 1024
#define SAVEGAME_COMMENT_LENGTH 39

View File

@ -2113,6 +2113,115 @@ unsigned int utf8_encode(void *out, unsigned int unicode, int maxlen)
return bcount;
}
unsigned int qchar_encode(char *out, unsigned int unicode, int maxlen)
{
static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if (((unicode >= 32 || unicode == '\n' || unicode == '\t' || unicode == '\r') && unicode < 128) || unicode >= 0xe000 && unicode <= 0xe0ff)
{ //quake compatible chars
if (maxlen < 1)
return 0;
*out++ = unicode;
return 1;
}
else if (unicode > 0xffff)
{ //chars longer than 16 bits
char *o = out;
if (maxlen < 11)
return 0;
*out++ = '^';
*out++ = '{';
if (unicode > 0xfffffff)
*out++ = hex[(unicode>>28)&15];
if (unicode > 0xffffff)
*out++ = hex[(unicode>>24)&15];
if (unicode > 0xfffff)
*out++ = hex[(unicode>>20)&15];
if (unicode > 0xffff)
*out++ = hex[(unicode>>16)&15];
if (unicode > 0xfff)
*out++ = hex[(unicode>>12)&15];
if (unicode > 0xff)
*out++ = hex[(unicode>>8)&15];
if (unicode > 0xf)
*out++ = hex[(unicode>>4)&15];
if (unicode > 0x0)
*out++ = hex[(unicode>>0)&15];
*out++ = '}';
return out - o;
}
else
{ //16bit chars
if (maxlen < 6)
return 0;
*out++ = '^';
*out++ = 'U';
*out++ = hex[(unicode>>12)&15];
*out++ = hex[(unicode>>8)&15];
*out++ = hex[(unicode>>4)&15];
*out++ = hex[(unicode>>0)&15];
return 6;
}
}
unsigned int iso88591_encode(char *out, unsigned int unicode, int maxlen)
{
static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if (unicode < 256)
{ //iso8859-1 compatible chars
if (maxlen < 1)
return 0;
*out++ = unicode;
return 1;
}
else if (unicode > 0xffff)
{ //chars longer than 16 bits
char *o = out;
if (maxlen < 11)
return 0;
*out++ = '^';
*out++ = '{';
if (unicode > 0xfffffff)
*out++ = hex[(unicode>>28)&15];
if (unicode > 0xffffff)
*out++ = hex[(unicode>>24)&15];
if (unicode > 0xfffff)
*out++ = hex[(unicode>>20)&15];
if (unicode > 0xffff)
*out++ = hex[(unicode>>16)&15];
if (unicode > 0xfff)
*out++ = hex[(unicode>>12)&15];
if (unicode > 0xff)
*out++ = hex[(unicode>>8)&15];
if (unicode > 0xf)
*out++ = hex[(unicode>>4)&15];
if (unicode > 0x0)
*out++ = hex[(unicode>>0)&15];
*out++ = '}';
return out - o;
}
else
{ //16bit chars
if (maxlen < 6)
return 0;
*out++ = '^';
*out++ = 'U';
*out++ = hex[(unicode>>12)&15];
*out++ = hex[(unicode>>8)&15];
*out++ = hex[(unicode>>4)&15];
*out++ = hex[(unicode>>0)&15];
return 6;
}
}
unsigned int unicode_encode(char *out, unsigned int unicode, int maxlen)
{
if (com_parseutf8.ival > 0)
return utf8_encode(out, unicode, maxlen);
else if (com_parseutf8.ival)
return iso88591_encode(out, unicode, maxlen);
else
return qchar_encode(out, unicode, maxlen);
}
///=====================================
@ -2291,61 +2400,11 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
if (ignoreflags && (*str & CON_HIDDEN))
continue;
c = *str++ & 0xffff;
if (com_parseutf8.ival > 0)
{
c = utf8_encode(out, c, outsize);
if (!c)
break;
outsize -= c;
out += c;
}
else if (com_parseutf8.ival)
{
//iso8859-1
if ((c >= 0 && c < 255) || (c >= 0xe000+32 && c < 0xe000+127)) //quake chars between 32 and 127 are identical to iso8859-1
{
if (!--outsize)
break;
*out++ = (unsigned char)(c&255);
}
else //any other (quake?) char is not iso8859-1
{
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if (outsize<=6)
break;
outsize -= 6;
*out++ = '^';
*out++ = 'U';
*out++ = hex[(c>>12)&15];
*out++ = hex[(c>>8)&15];
*out++ = hex[(c>>4)&15];
*out++ = hex[(c>>0)&15];
}
}
else
{
//quake chars
if (c == '\n' || c == '\r' || c == '\t' || (c >= 32 && c < 127) || (c >= 0xe000 && c < 0xe100)) //quake chars between 32 and 127 are identical to iso8859-1
{
if (!--outsize)
break;
*out++ = (unsigned char)(c&255);
}
else //any other char is not quake
{
const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if (outsize<=6)
break;
outsize -= 6;
*out++ = '^';
*out++ = 'U';
*out++ = hex[(c>>12)&15];
*out++ = hex[(c>>8)&15];
*out++ = hex[(c>>4)&15];
*out++ = hex[(c>>0)&15];
}
}
c = unicode_encode(out, (*str++ & CON_CHARMASK), outsize-1);
if (!c)
break;
outsize -= c;
out += c;
}
*out = 0;
}
@ -2364,18 +2423,22 @@ static int dehex(int i)
//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, qboolean keepmarkup)
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, int flags)
{
conchar_t extstack[4];
int extstackdepth = 0;
unsigned int uc;
int utf8 = com_parseutf8.ival;
conchar_t linkinitflags = CON_WHITEMASK;/*doesn't need the init, but msvc is stupid*/
qboolean keepmarkup = flags & PFS_KEEPMARKUP;
qboolean linkkeep = keepmarkup;
conchar_t *linkstart = NULL;
conchar_t ext;
if (flags & PFS_FORCEUTF8)
utf8 = 2;
outsize /= sizeof(conchar_t);
if (!outsize)
return out;
@ -2392,10 +2455,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
if (*str == 1 || *str == 2)
{
if (com_parseutf8.ival)
defaultflags = (defaultflags&~CON_FGMASK) | ((com_highlightcolor.ival&15)<<CON_FGSHIFT);
else
defaultflags |= CON_HIGHCHARSMASK;
defaultflags ^= CON_2NDCHARSETTEXT;
str++;
}
@ -2416,7 +2476,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
}
else
{
if (uc > 0xffff)
if (uc > CON_CHARMASK)
uc = 0xfffd;
if (!--outsize)
break;
@ -2514,21 +2574,9 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
ext = defaultflags;
}
else if (str[1] == 'm')
{
if (com_parseutf8.ival)
{
if ((ext & CON_FGMASK) != (COLOR_MAGENTA<<CON_FGSHIFT))
ext = (ext&~CON_FGMASK) | (COLOR_MAGENTA<<CON_FGSHIFT);
else
ext = (ext&~CON_FGMASK) | (CON_WHITEMASK);
}
else
ext ^= CON_HIGHCHARSMASK;
}
ext ^= CON_2NDCHARSETTEXT;
else if (str[1] == 'h')
{
ext ^= CON_HALFALPHA;
}
else if (str[1] == 's') //store on stack (it's great for names)
{
if (extstackdepth < sizeof(extstack)/sizeof(extstack[0]))
@ -2557,22 +2605,46 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
if (!--outsize)
break;
*out++ = uc | (ext&~CON_HIGHCHARSMASK);
*out++ = uc | ext;
str += 6;
continue;
}
}
else if (str[1] == '{') //unicode (Xbit) char ^{xxxx}
{
if (!keepmarkup)
{
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++)
{
uc <<= 4;
uc |= dehex(str[len]);
}
//and eat the close too. oh god I hope its there.
if (str[len] == '}')
len++;
if (uc > CON_CHARMASK)
uc = 0xfffd;
if (!--outsize)
break;
*out++ = uc | ext;
str += len;
continue;
}
}
else if (str[1] == '^')
{
if (keepmarkup)
{
if (!--outsize)
break;
if (com_parseutf8.ival)
*out++ = (unsigned char)(*str) | ext;
else
*out++ = (unsigned char)(*str) | ext | 0xe000;
*out++ = (unsigned char)(*str) | ext;
}
str++;
@ -2647,16 +2719,19 @@ messedup:
break;
uc = (unsigned char)(*str++);
if (utf8)
{
//utf8/iso8859-1 has it easy.
*out++ = uc | ext;
}
else
{
if (uc == '\n' || uc == '\r' || uc == '\t' || uc == ' ')
*out++ = uc | (ext&~CON_HIGHCHARSMASK);
else if (uc >= 32 && uc < 127 && !(ext&CON_HIGHCHARSMASK))
*out++ = uc | ext;
else if (uc >= 0x80+32 && uc < 0x80+127)
*out++ = (uc&127) | ext ^ CON_2NDCHARSETTEXT;
else
else if (uc >= 32 && uc < 127)
*out++ = uc | ext;
else if (uc >= 0x80+32 && uc <= 0xff) //anything using high chars is ascii, with the second charset
*out++ = ((uc&127) | ext) | CON_2NDCHARSETTEXT;
else //(other) control chars are regular printables in quake, and are not ascii. These ALWAYS use the bitmap/fallback font.
*out++ = uc | ext | 0xe000;
}
}

View File

@ -292,9 +292,13 @@ void COM_ParsePlusSets (void);
typedef unsigned int conchar_t;
char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags);
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, qboolean keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator
#define PFS_KEEPMARKUP 1
#define PFS_FORCEUTF8 2
conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t *out, int outsize, int keepmarkup); //ext is usually CON_WHITEMASK, returns its null terminator
unsigned int utf8_decode(int *error, const void *in, char **out);
unsigned int utf8_encode(void *out, unsigned int unicode, int maxlen);
unsigned int iso88591_encode(char *out, unsigned int unicode, int maxlen);
unsigned int qchar_encode(char *out, unsigned int unicode, int maxlen);
char *COM_SkipPath (const char *pathname);
void COM_StripExtension (const char *in, char *out, int outlen);

View File

@ -39,7 +39,7 @@ extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_BLINKTEXT 0x00040000
#define CON_2NDCHARSETTEXT 0x00020000
#define CON_RICHFORECOLOUR 0x00010000 //
#define CON_HIGHCHARSMASK 0x00000080 // Quake's alternative mask
//#define CON_HIGHCHARSMASK 0x00000080 // Quake's alternative mask
#define CON_FLAGSMASK 0xFFFF0000
#define CON_CHARMASK 0x0000FFFF

View File

@ -3945,7 +3945,18 @@ int TCP_OpenStream (netadr_t remoteaddr)
if (connect(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET)
{
Con_Printf ("TCP_OpenStream: connect: error %i\n", qerrno);
int err = qerrno;
if (err == EADDRNOTAVAIL)
{
char buf[128];
NET_AdrToString(buf, sizeof(buf), remoteaddr);
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
Con_Printf ("TCP_OpenStream: connect: error %i\n", err);
closesocket(newsocket);
return INVALID_SOCKET;
}

View File

@ -3994,7 +3994,7 @@ void PR_AutoCvar(pubprogfuncs_t *prinst, cvar_t *var)
}
}
void PDECL PR_FoundPrefixedGlobals(pubprogfuncs_t *progfuncs, char *name, eval_t *val, etype_t type)
void PDECL PR_FoundAutoCvarGlobal(pubprogfuncs_t *progfuncs, char *name, eval_t *val, etype_t type)
{
cvar_t *var;
char *vals;
@ -4009,13 +4009,13 @@ void PDECL PR_FoundPrefixedGlobals(pubprogfuncs_t *progfuncs, char *name, eval_t
if(nlen >= 2 && name[nlen-2] == '_' && (name[nlen-1] == 'x' || name[nlen-1] == 'y' || name[nlen-1] == 'z'))
return;
vals = va("%f", val->_float);
vals = va("%g", val->_float);
break;
case ev_integer:
vals = va("%i", val->_int);
break;
case ev_vector:
vals = va("%f %f %f", val->_vector[0], val->_vector[1], val->_vector[2]);
vals = va("%g %g %g", val->_vector[0], val->_vector[1], val->_vector[2]);
break;
case ev_string:
vals = PR_GetString(progfuncs, val->string);
@ -4035,7 +4035,7 @@ void PDECL PR_FoundPrefixedGlobals(pubprogfuncs_t *progfuncs, char *name, eval_t
void PR_AutoCvarSetup(pubprogfuncs_t *prinst)
{
prinst->FindPrefixGlobals (prinst, "autocvar_", PR_FoundPrefixedGlobals);
prinst->FindPrefixGlobals (prinst, "autocvar_", PR_FoundAutoCvarGlobal);
}
lh_extension_t QSG_Extensions[] = {

View File

@ -369,9 +369,16 @@ enum clcq2_ops_e
#define clc_prydoncursor 82
#define clc_voicechat 83
//==============================================
//these flags are sent as part of the svc_precache index, for any-time precaches. using the upper two bits means we still have 16k available models/sounds/etc
#define PC_TYPE 0xc000
#define PC_MODEL 0x0000
#define PC_SOUND 0x8000
#define PC_PARTICLE 0x4000
#define PC_UNUSED 0xc000
// playerinfo flags from server
// playerinfo always sends: playernum, flags, origin[] and framenumber

View File

@ -231,7 +231,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
bc = e->bottomcolour;
pc = e->h2playerclass;
if (forced || tc != 1 || bc != 1 || plskin)
if (forced || tc != TOP_DEFAULT || bc != BOTTOM_DEFAULT || plskin)
{
int inwidth, inheight;
int tinwidth, tinheight;
@ -532,10 +532,15 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
frac += fracstep;
}
}
cm->texnum.base = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, IF_NOMIPMAP);
cm->texnum.base = R_LoadTexture(va("base$%x$%x$%i$%i$%i$%s", tc, bc, cm->skinnum, subframe, pc, cm->name),
scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, IF_NOMIPMAP);
if (!h2playertranslations)
cm->texnum.bump = shader->defaulttextures.bump;
cm->texnum.fullbright = shader->defaulttextures.fullbright;
cm->texnum.specular = shader->defaulttextures.specular;
/*if (!h2playertranslations)
{
qboolean valid = false;
//now do the fullbrights.
out = pixels;
fracstep = tinwidth*0x10000/scaled_width;
@ -547,11 +552,15 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
{
if (inrow[frac>>16] < 255-vid.fullbright)
((char *) (&out[j]))[3] = 0; //alpha 0
else
valid = true;
frac += fracstep;
}
}
cm->texnum.fullbright = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, IF_NOMIPMAP);
}
if (valid)
cm->texnum.fullbright = R_LoadTexture(va("fb$%x$%x$%i$%i$%i$%s", tc, bc, cm->skinnum, subframe, pc, cm->name),
scaled_width, scaled_height, TF_RGBA32, pixels, IF_NOMIPMAP);
}*/
}
else
{

View File

@ -381,18 +381,6 @@ void Font_FlushPlane(font_t *f)
fontplanes.newestchar = NULL;
}
//obtains a cached char, null if not cached
static struct charcache_s *Font_GetChar(font_t *f, CHARIDXTYPE charidx)
{
struct charcache_s *c = &f->chars[charidx];
if (c->texplane == INVALIDPLANE)
{
//not cached, can't get.
return NULL;
}
return c;
}
//loads a new image into a given character slot for the given font.
//note: make sure it doesn't already exist or things will get cyclic
//alphaonly says if its a greyscale image. false means rgba.
@ -607,6 +595,33 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
return NULL;
}
//obtains a cached char, null if not cached
static struct charcache_s *Font_GetChar(font_t *f, CHARIDXTYPE charidx)
{
struct charcache_s *c = &f->chars[charidx];
if (c->texplane == INVALIDPLANE)
{
//not cached, can't get.
c = Font_TryLoadGlyph(f, charidx);
if (!c)
{
charidx = 0xfffd; //unicode's replacement char
c = &f->chars[charidx];
if (c->texplane == INVALIDPLANE)
c = Font_TryLoadGlyph(f, charidx);
}
if (!c)
{
charidx = '?'; //meh
c = &f->chars[charidx];
if (c->texplane == INVALIDPLANE)
c = Font_TryLoadGlyph(f, charidx);
}
}
return c;
}
qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename)
{
#ifdef AVAIL_FREETYPE
@ -695,9 +710,9 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename)
}
if (*fontdir)
{
error = pFT_New_Face(fontlib, va("%s/%s.ttf", fontdir, fontfilename), 0, &face);
error = pFT_New_Face(fontlib, va("%s/%s", fontdir, fontfilename), 0, &face);
if (error)
error = pFT_New_Face(fontlib, va("%s/%s", fontdir, fontfilename), 0, &face);
error = pFT_New_Face(fontlib, va("%s/%s.ttf", fontdir, fontfilename), 0, &face);
}
}
#endif
@ -1073,11 +1088,16 @@ struct font_s *Font_LoadFont(int vheight, char *fontfilename)
}
if (!Font_LoadFreeTypeFont(f, height, fontfilename))
{
//default to only map the ascii-compatible chars from the quake font.
if (*fontfilename)
f->singletexture = R_LoadHiResTexture(fontfilename, "fonts", IF_2D|IF_NOMIPMAP);
for ( ; i < 32; i++)
{
f->chars[i].texplane = INVALIDPLANE;
}
/*force it to load, even if there's nothing there*/
for (; i < 256; i++)
for ( ; i < 128; i++)
{
f->chars[i].advance = f->charheight;
f->chars[i].bmh = PLANEWIDTH/16;
@ -1233,20 +1253,13 @@ int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode)
if ((charcode&CON_CHARMASK) == '\t')
return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH);
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
}
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt;
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
{
c = Font_TryLoadGlyph(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
return x+0;
return x+0;
}
return x+c->advance;
@ -1259,20 +1272,13 @@ int Font_CharWidth(unsigned int charcode)
struct font_s *font = curfont;
if (charcode&CON_HIDDEN)
return 0;
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
}
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt;
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
{
c = Font_TryLoadGlyph(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
return 0;
return 0;
}
return c->advance;
@ -1396,19 +1402,18 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
{
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
charcode &= ~CON_2NDCHARSETTEXT;
}
else if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff)
charcode &= ~CON_2NDCHARSETTEXT; //don't double-dip
}
//crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
{
c = Font_TryLoadGlyph(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
return px;
}
return px;
nextx = px + c->advance;
@ -1426,7 +1431,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
if (charcode & CON_RICHFORECOLOUR)
{
col = charcode & (CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
col = charcode & (CON_2NDCHARSETTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
if (col != font_colourmask)
{
if (font_colourmask & CON_NONCLEARBG)
@ -1442,11 +1447,18 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
font_backcolour[1] = 0;
font_backcolour[2] = 0;
font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*1.16, 255);
font_forecolour[1] *= 0.54;
font_forecolour[2] *= 0.41;
}
}
}
else
{
col = charcode & (CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
col = charcode & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask)
{
if ((col ^ font_colourmask) & CON_NONCLEARBG)
@ -1464,6 +1476,13 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
font_backcolour[1] = consolecolours[col].fg*255;
font_backcolour[2] = consolecolours[col].fb*255;
font_backcolour[3] = (charcode & CON_NONCLEARBG)?127:0;
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*1.16, 255);
font_forecolour[1] *= 0.54;
font_forecolour[2] *= 0.41;
}
}
}
@ -1553,9 +1572,12 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
if (charcode & CON_2NDCHARSETTEXT)
{
if (font->alt)
{
font = font->alt;
else if ((charcode & CON_CHARMASK) >= 0x20 && (charcode&CON_CHARMASK) < 0x80)
charcode |= 0xe000;
charcode &= ~CON_2NDCHARSETTEXT;
}
else if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff)
charcode &= ~CON_2NDCHARSETTEXT; //don't double-dip
}
cw = curfont_scale[0];
@ -1564,11 +1586,7 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
//crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
{
c = Font_TryLoadGlyph(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
if (!c)
return px;
}
return px;
nextx = px + c->advance*cw;
@ -1584,7 +1602,7 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
if (charcode & CON_RICHFORECOLOUR)
{
col = charcode & (CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
col = charcode & (CON_2NDCHARSETTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
if (col != font_colourmask)
{
if (font_backcolour[3])
@ -1600,11 +1618,18 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
font_backcolour[1] = 0;
font_backcolour[2] = 0;
font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*1.16, 255);
font_forecolour[1] *= 0.54;
font_forecolour[2] *= 0.41;
}
}
}
else
{
col = charcode & (CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
col = charcode & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask)
{
if (font_backcolour[3] != ((charcode & CON_NONCLEARBG)?127:0))
@ -1622,6 +1647,13 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
font_backcolour[1] = consolecolours[col].fg*255;
font_backcolour[2] = consolecolours[col].fb*255;
font_backcolour[3] = (charcode & CON_NONCLEARBG)?127:0;
if (charcode & CON_2NDCHARSETTEXT)
{
font_forecolour[0] = min(font_forecolour[0]*1.16, 255);
font_forecolour[1] *= 0.54;
font_forecolour[2] *= 0.41;
}
}
}

View File

@ -165,13 +165,13 @@ m*_t structures are in-memory
#define _DPEF_SELECTABLE (1<<14) //highlights when prydoncursored
#define _DPEF_DOUBLESIDED (1<<15) //disables culling
#define _DPEF_NOSELFSHADOW (1<<16) //doesn't cast shadows on any noselfshadow entities.
#define EF_UNUSED17 (1<<17)
#define _DPEF_DYNAMICMODELLIGHT (1<<17)
#define EF_UNUSED18 (1<<18)
#define EF_UNUSED19 (1<<19)
#define _DPEF_RESTARTANIM_BIT (1<<20) //exact semantics seems odd
#define _DPEF_TELEPORT_BIT (1<<21) //disable lerping while set
#define DPEF_LOWPRECISION (1<<22) //part of the protocol/server, not the client itself.
#define _DPEF_NOMODELFLAGS (1<<23)
#define EF_NOMODELFLAGS (1<<23)
#define EF_MF_ROCKET (1<<24)
#define EF_MF_GRENADE (1<<25)
#define EF_MF_GIB (1<<26)

View File

@ -5005,6 +5005,9 @@ cin_t *R_ShaderFindCinematic(char *name)
int i;
char shortname[MAX_QPATH];
if (!r_shaders)
return NULL;
COM_StripExtension ( name, shortname, sizeof(shortname));
COM_CleanUpPath(shortname);

View File

@ -534,6 +534,7 @@ reeval:
break;
//load a field to a value
case OP_LOAD_P:
case OP_LOAD_I:
case OP_LOAD_F:
case OP_LOAD_FLD:

View File

@ -8088,6 +8088,7 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
numslots = array->arraysize*array->type->size;
numslots = (numslots+2)/3;
s_file = array->s_file;
func = QCC_PR_GetDef(type_function, qcva("ArrayGetVec*%s", array->name), NULL, true, 0, false);
pr_scope = func;
@ -8143,6 +8144,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
else
fasttrackpossible = NULL;
s_file = scope->s_file;
def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
if (def->type->type == ev_vector)
@ -8316,6 +8318,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
else
fasttrackpossible = NULL;
s_file = scope->s_file;
def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
pr_scope = scope;

View File

@ -73,6 +73,7 @@ cvar_t pr_maxedicts = CVARAFD("pr_maxedicts", "32768", "max_edicts", CVAR_LATCH,
cvar_t pr_no_playerphysics = CVARFD("pr_no_playerphysics", "0", CVAR_LATCH, "Prevents support of the 'SV_PlayerPhysics' QC function. This allows servers to prevent needless breakage of player prediction.");
cvar_t pr_no_parsecommand = CVARFD("pr_no_parsecommand", "0", 0, "Provides a way around invalid mod usage of SV_ParseClientCommand, eg xonotic.");
cvar_t pr_sourcedir = CVARD("pr_sourcedir", "src", "Subdirectory where your qc source is located. Used by the internal compiler and qc debugging functionality.");
cvar_t pr_ssqc_progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER);
cvar_t qc_nonetaccess = CVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc.
cvar_t qc_netpreparse = CVAR("qc_netpreparse", "1"); //server-side writebyte protocol translation
@ -140,6 +141,7 @@ struct {
func_t ClassChangeWeapon;//hexen2 support
func_t AddDebugPolygons;
func_t CheckRejectConnection;
} gfuncs;
func_t SpectatorConnect; //QW
func_t SpectatorThink; //QW
@ -446,7 +448,7 @@ int QDECL QCEditor (pubprogfuncs_t *prinst, char *filename, int line, int statem
f = NULL; //faster.
if (!f)
{
Q_snprintfz(buffer, sizeof(buffer), "src/%s", filename);
Q_snprintfz(buffer, sizeof(buffer), "%s/%s", pr_sourcedir.string, filename);
f = FS_OpenVFS(buffer, "rb", FS_GAME);
}
if (!f)
@ -797,6 +799,7 @@ void PR_LoadGlabalStruct(void)
gfuncs.ClassChangeWeapon = PR_FindFunction(svprogfuncs, "ClassChangeWeapon", PR_ANY);
gfuncs.RunClientCommand = PR_FindFunction(svprogfuncs, "SV_RunClientCommand", PR_ANY);
gfuncs.AddDebugPolygons = PR_FindFunction(svprogfuncs, "SV_AddDebugPolygons", PR_ANY);
gfuncs.CheckRejectConnection = PR_FindFunction(svprogfuncs, "SV_CheckRejectConnection", PR_ANY);
if (pr_no_playerphysics.ival)
SV_PlayerPhysicsQC = 0;
@ -1025,7 +1028,7 @@ void PR_Compile_f(void)
{
int argc=3;
double time = Sys_DoubleTime();
char *argv[64] = {"", "-src", "src", "-srcfile", "progs.src"};
char *argv[64] = {"", "-src", pr_sourcedir.string, "-srcfile", "progs.src"};
if (Cmd_Argc()>2)
{
@ -1235,6 +1238,7 @@ void PR_Init(void)
Cvar_Register(&pr_imitatemvdsv, cvargroup_progs);
Cvar_Register(&pr_fixbrokenqccarrays, cvargroup_progs);
Cvar_Register(&pr_sourcedir, cvargroup_progs);
Cvar_Register(&pr_maxedicts, cvargroup_progs);
Cvar_Register(&pr_no_playerphysics, cvargroup_progs);
Cvar_Register(&pr_no_parsecommand, cvargroup_progs);
@ -3639,13 +3643,67 @@ void PR_CheckEmptyString (char *s)
PR_RunError ("Bad string");
}
*/
//float(string effectname) particleeffectnum (EXT_CSQC)
static void QCBUILTIN PF_sv_particleeffectnum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *s = PR_GetStringOfs(prinst, OFS_PARM0);
/*
#ifdef PEXT_CSQC
#ifdef warningmsg
#pragma warningmsg("PF_sv_particleeffectnum: which effect index values to use?")
#endif
char *efname = PR_GetStringOfs(prinst, OFS_PARM0);
G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname);
#else
G_FLOAT(OFS_RETURN) = -1;
#endif
*/
int i;
if (s[0] <= ' ')
{
PR_BIError (prinst, "PF_precache_particles: Bad string");
return;
}
G_FLOAT(OFS_RETURN) = 0;
for (i=1 ; i<MAX_SSPARTICLESPRE ; i++)
{
if (!*sv.strings.particle_precache[i])
{
strcpy(sv.strings.particle_precache[i], s);
if (sv.state != ss_loading)
{
Con_DPrintf("Delayed particle precache: %s\n", s);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i|PC_PARTICLE);
MSG_WriteString(&sv.reliable_datagram, s);
#ifdef NQPROT
MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache);
MSG_WriteShort(&sv.nqreliable_datagram, i|PC_PARTICLE);
MSG_WriteString(&sv.nqreliable_datagram, s);
#endif
}
}
if (!strcmp(sv.strings.particle_precache[i], s))
{
G_FLOAT(OFS_RETURN) = i;
return;
}
}
PR_BIError (prinst, "PF_precache_particles: overflow");
}
static void QCBUILTIN PF_precache_file (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ // precache_file is only used to copy files with qcc, it does nothing
char *s = PR_GetStringOfs(prinst, OFS_PARM0);
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
/*touch the file, so any packs will be referenced. this is fte behaviour.*/
/*touch the file, so any packs will be referenced. this is fte-specific behaviour.*/
FS_FLocateFile(s, FSLFRT_IFFOUND, NULL);
}
@ -3672,11 +3730,11 @@ void PF_precache_sound_Internal (pubprogfuncs_t *prinst, char *s)
{
Con_DPrintf("Delayed sound precache: %s\n", s);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i+32768);
MSG_WriteShort(&sv.reliable_datagram, i+PC_SOUND);
MSG_WriteString(&sv.reliable_datagram, s);
#ifdef NQPROT
MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache);
MSG_WriteShort(&sv.nqreliable_datagram, i+32768);
MSG_WriteShort(&sv.nqreliable_datagram, i+PC_SOUND);
MSG_WriteString(&sv.nqreliable_datagram, s);
#endif
}
@ -5680,7 +5738,7 @@ int PR_EnableEBFSBuiltin(char *name, int binum)
int i;
for (i = 0;BuiltinList[i].name;i++)
{
if (!strcmp(BuiltinList[i].name, name))
if (!strcmp(BuiltinList[i].name, name) && BuiltinList[i].bifunc != PF_Fixme)
{
if (!binum)
binum = BuiltinList[i].ebfsnum;
@ -6438,6 +6496,104 @@ 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 addrstr[256];
char clfeatures[4096], *bp;
char *ret = NULL;
if (gfuncs.CheckRejectConnection)
{
globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
NET_AdrToString(addrstr, sizeof(addrstr), adr);
*clfeatures = 0;
switch(protocol)
{
default: bp = "unknown"; break;
case SCP_QUAKEWORLD: bp = "qw"; break;
case SCP_QUAKE2: bp = "q2"; break;
case SCP_QUAKE3: bp = "q3"; break;
case SCP_NETQUAKE: bp = "nq"; break;
case SCP_PROQUAKE: bp = "nq"; break; //not nuff difference for it to be meaningful
case SCP_FITZ666: bp = "fitz666"; break;
case SCP_DARKPLACES6: bp = "dp6"; break;
case SCP_DARKPLACES7: bp = "dp7"; break;
}
Info_SetValueForKey(clfeatures, "basicprotocol", bp, sizeof(clfeatures));
Info_SetValueForKey(clfeatures, "guid", guid, sizeof(clfeatures));
Info_SetValueForKey(clfeatures, "maxsounds", "256", sizeof(clfeatures));
Info_SetValueForKey(clfeatures, "maxmodels", "256", sizeof(clfeatures));
//this is not the limits of the client itself, but the limits that the server is able and willing to send to them.
if ((pext1 & PEXT_SOUNDDBL) || (protocol == SCP_FITZ666 || protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "maxsounds", va("%i", MAX_SOUNDS), sizeof(clfeatures));
else
Info_SetValueForKey(clfeatures, "maxsounds", "256", sizeof(clfeatures));
if ((pext1 & PEXT_MODELDBL) || (protocol == SCP_FITZ666 || protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "maxmodels", va("%i", MAX_MODELS), sizeof(clfeatures));
else
Info_SetValueForKey(clfeatures, "maxmodels", "256", sizeof(clfeatures));
if (pext2 & PEXT2_REPLACEMENTDELTAS)
Info_SetValueForKey(clfeatures, "maxentities", va("%i", MAX_EDICTS), sizeof(clfeatures));
else if (protocol == SCP_FITZ666)
// Info_SetValueForKey(clfeatures, "maxentities", "65535", sizeof(clfeatures));
Info_SetValueForKey(clfeatures, "maxentities", "32767", sizeof(clfeatures));
else if (protocol == SCP_DARKPLACES6 || protocol == SCP_DARKPLACES7)
Info_SetValueForKey(clfeatures, "maxentities", "32767", sizeof(clfeatures));
else if (protocol == SCP_NETQUAKE)
Info_SetValueForKey(clfeatures, "maxentities", "600", sizeof(clfeatures));
else //if (protocol == SCP_QUAKEWORLD)
Info_SetValueForKey(clfeatures, "maxentities", "512", sizeof(clfeatures));
if (pext2 & PEXT2_REPLACEMENTDELTAS) //limited by packetlog/size, but server can track the whole lot, assuming they're not all sent in a single packet.
Info_SetValueForKey(clfeatures, "maxvisentities", va("%i", MAX_EDICTS), sizeof(clfeatures));
else if (protocol == SCP_DARKPLACES6 || protocol == SCP_DARKPLACES7) //deltaing protocol allows all ents to be visible at once
Info_SetValueForKey(clfeatures, "maxvisentities", "32767", sizeof(clfeatures));
else if (pext1 & PEXT_256PACKETENTITIES)
Info_SetValueForKey(clfeatures, "maxvisentities", "256", sizeof(clfeatures));
else if (protocol == SCP_QUAKEWORLD)
Info_SetValueForKey(clfeatures, "maxvisentities", "64", sizeof(clfeatures));
//others are limited by packet sizes, so the count can vary...
//features
if (pext1 & PEXT_VIEW2)
Info_SetValueForKey(clfeatures, "PEXT_VIEW2", "1", sizeof(clfeatures));
if (pext1 & PEXT_LIGHTSTYLECOL)
Info_SetValueForKey(clfeatures, "PEXT_LIGHTSTYLECOL", "1", sizeof(clfeatures));
if ((pext1 & PEXT_CSQC) || (protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "PEXT_CSQC", "1", sizeof(clfeatures));
if ((pext1 & PEXT_FLOATCOORDS) || (protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "PEXT_FLOATCOORDS", "1", sizeof(clfeatures));
if ((pext1 & PEXT_ENTITYDBL) || (pext2 & PEXT2_REPLACEMENTDELTAS) || (protocol == SCP_FITZ666 || protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "PEXT_ENTITYDBL", "1", sizeof(clfeatures));
if (pext1 & PEXT_HEXEN2)
Info_SetValueForKey(clfeatures, "PEXT_HEXEN2", "1", sizeof(clfeatures));
if ((pext1 & PEXT_SETATTACHMENT) || (protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "PEXT_SETATTACHMENT", "1", sizeof(clfeatures));
if (pext1 & PEXT_CUSTOMTEMPEFFECTS)
Info_SetValueForKey(clfeatures, "PEXT_CUSTOMTEMPEFFECTS", "1", sizeof(clfeatures));
if ((pext2 & PEXT2_PRYDONCURSOR) || (protocol == SCP_DARKPLACES6) || (protocol == SCP_DARKPLACES7))
Info_SetValueForKey(clfeatures, "PEXT2_PRYDONCURSOR", "1", sizeof(clfeatures));
if (pext2 & PEXT2_VOICECHAT)
Info_SetValueForKey(clfeatures, "PEXT2_VOICECHAT", "1", sizeof(clfeatures));
if (pext2 & PEXT2_REPLACEMENTDELTAS)
Info_SetValueForKey(clfeatures, "PEXT2_REPLACEMENTDELTAS", "1", sizeof(clfeatures));
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.world.edicts);
G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, addrstr);
G_INT(OFS_PARM1) = (int)PR_TempString(svprogfuncs, uinfo);
G_INT(OFS_PARM2) = (int)PR_TempString(svprogfuncs, clfeatures);
PR_ExecuteProgram (svprogfuncs, gfuncs.CheckRejectConnection);
ret = PR_GetStringOfs(svprogfuncs, OFS_RETURN);
if (!*ret)
ret = NULL;
}
return ret;
}
void SV_AddDebugPolygons(void)
{
int i;
@ -7381,19 +7537,6 @@ static void QCBUILTIN PF_CustomTEnt(pubprogfuncs_t *prinst, struct globalvars_s
SV_MulticastProtExt (org, mcd, pr_global_struct->dimension_send, PEXT_CUSTOMTEMPEFFECTS, 0); //now send the new multicast to all that will.
}
//float(string effectname) particleeffectnum (EXT_CSQC)
static void QCBUILTIN PF_sv_particleeffectnum(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
#ifdef PEXT_CSQC
#ifdef warningmsg
#pragma warningmsg("PF_sv_particleeffectnum: which effect index values to use?")
#endif
char *efname = PR_GetStringOfs(prinst, OFS_PARM0);
G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname);
#else
G_FLOAT(OFS_RETURN) = -1;
#endif
}
//void(float effectnum, entity ent, vector start, vector end) trailparticles (EXT_CSQC),
static void QCBUILTIN PF_sv_trailparticles(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -7444,13 +7587,13 @@ static void QCBUILTIN PF_sv_pointparticles(pubprogfuncs_t *prinst, struct global
#ifdef PEXT_CSQC
int efnum = G_FLOAT(OFS_PARM0);
float *org = G_VECTOR(OFS_PARM1);
float *vel = G_VECTOR(OFS_PARM2);
int count = G_FLOAT(OFS_PARM3);
float *vel = (prinst->callargc < 3)?vec3_origin:G_VECTOR(OFS_PARM2);
int count = (prinst->callargc < 4)?1:G_FLOAT(OFS_PARM3);
if (count > 65535)
count = 65535;
if (count == 1 && DotProduct(org, org) == 0)
if (count == 1 && DotProduct(vel, vel) == 0)
{
MSG_WriteByte(&sv.multicast, svcfte_pointparticles1);
MSG_WriteShort(&sv.multicast, efnum);
@ -9221,7 +9364,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"drawline", PF_Fixme, 0, 0, 0, 315, "void(float width, vector pos1, vector pos2)"},// (EXT_CSQC)
{"iscachedpic", PF_Fixme, 0, 0, 0, 316, "float(string name)"},// (EXT_CSQC)
{"precache_pic", PF_Fixme, 0, 0, 0, 317, "string(string name, optional float trywad)"},// (EXT_CSQC)
{"draw_getimagesize",PF_Fixme, 0, 0, 0, 318, "vector(string picname)"},// (EXT_CSQC)
{"drawgetimagesize",PF_Fixme, 0, 0, 0, 318, "#define draw_getimagesize drawgetimagesize\nvector(string picname)"},// (EXT_CSQC)
{"freepic", PF_Fixme, 0, 0, 0, 319, "void(string name)"},// (EXT_CSQC)
//320
{"drawcharacter", PF_Fixme, 0, 0, 0, 320, "float(vector position, float character, vector scale, vector rgb, float alpha, optional float flag)"},// (EXT_CSQC, [EXT_CSQC_???])
@ -10074,7 +10217,7 @@ void PR_DumpPlatform_f(void)
{"SpectatorConnect", "noref void()", QW|NQ},
{"SpectatorDisconnect", "noref void()", QW|NQ},
{"SpectatorThink", "noref void()", QW|NQ},
{"SV_ParseClientCommand", "noref void()", QW|NQ},
{"SV_ParseClientCommand", "noref void(string cmd)", QW|NQ},
{"SV_ParseConnectionlessPacket", "noref void()", QW|NQ},
{"SV_PausedTic", "noref void()", QW|NQ},
{"SV_ShouldPause", "noref void()", QW|NQ},
@ -10083,6 +10226,7 @@ void PR_DumpPlatform_f(void)
{"SV_AddDebugPolygons", "noref void()", QW|NQ},
{"SV_PlayerPhysics", "noref void()", QW|NQ},
{"EndFrame", "noref void()", QW|NQ},
{"SV_CheckRejectConnection","noref string(string addr, string uinfo, string features) ", QW|NQ},
/* //mvdsv compat
{"UserInfo_Changed", "//noref void()", QW},
{"localinfoChanged", "//noref void()", QW},
@ -10247,17 +10391,28 @@ void PR_DumpPlatform_f(void)
{"MOVE_LAGGED", "const float", QW|NQ, MOVE_LAGGED},
{"MOVE_ENTCHAIN", "const float", QW|NQ|CS, MOVE_ENTCHAIN},
{"EF_BRIGHTFIELD", "const float", QW|NQ|CS, EF_BRIGHTFIELD},
{"EF_MUZZLEFLASH", "const float", NQ|CS, EF_MUZZLEFLASH},
{"EF_BRIGHTLIGHT", "const float", QW|NQ|CS, EF_BRIGHTLIGHT},
{"EF_DIMLIGHT", "const float", QW|NQ|CS, EF_DIMLIGHT},
{"EF_FLAG1", "const float", QW , QWEF_FLAG1},
{"EF_FLAG2", "const float", QW , QWEF_FLAG2},
{"EF_ADDITIVE", "const float", NQ|CS, NQEF_ADDITIVE},
{"EF_BLUE", "const float", QW|NQ|CS, EF_BLUE},
{"EF_RED", "const float", QW|NQ|CS, EF_RED},
{"EF_FULLBRIGHT", "const float", QW|NQ|CS, EF_FULLBRIGHT},
{"EF_NODEPTHTEST", "const float", QW|NQ|CS, EF_NODEPTHTEST},
{"EF_BRIGHTFIELD", "const float", QW|NQ|CS, EF_BRIGHTFIELD},
{"EF_MUZZLEFLASH", "const float", NQ|CS, EF_MUZZLEFLASH},
{"EF_BRIGHTLIGHT", "const float", QW|NQ|CS, EF_BRIGHTLIGHT},
{"EF_DIMLIGHT", "const float", QW|NQ|CS, EF_DIMLIGHT},
{"EF_FLAG1", "const float", QW , QWEF_FLAG1},
{"EF_FLAG2", "const float", QW , QWEF_FLAG2},
{"EF_ADDITIVE", "const float", NQ|CS, NQEF_ADDITIVE},
{"EF_BLUE", "const float", QW|NQ|CS, EF_BLUE},
{"EF_RED", "const float", QW|NQ|CS, EF_RED},
{"EF_FULLBRIGHT", "const float", QW|NQ|CS, EF_FULLBRIGHT},
{"EF_NODEPTHTEST", "const float", QW|NQ|CS, EF_NODEPTHTEST},
{"EF_NOMODELFLAGS", "const float", QW|NQ, EF_NOMODELFLAGS},
{"MF_ROCKET", "const float", QW|NQ, EF_MF_ROCKET>>24},
{"MF_GRENADE", "const float", QW|NQ, EF_MF_GRENADE>>24},
{"MF_GIB", "const float", QW|NQ, EF_MF_GIB>>24},
{"MF_ROTATE", "const float", QW|NQ, EF_MF_ROTATE>>24},
{"MF_TRACER", "const float", QW|NQ, EF_MF_TRACER>>24},
{"MF_ZOMGIB", "const float", QW|NQ, EF_MF_ZOMGIB>>24},
{"MF_TRACER2", "const float", QW|NQ, EF_MF_TRACER2>>24},
{"MF_TRACER3", "const float", QW|NQ, EF_MF_TRACER3>>24},
{"STAT_HEALTH", "const float", CS, STAT_HEALTH},
{"STAT_WEAPON", "const float", CS, STAT_WEAPON},
@ -10431,7 +10586,7 @@ void PR_DumpPlatform_f(void)
if (!*fname)
fname = "fteextensions";
fname = va("src/%s.qc", fname);
fname = va("%s/%s.qc", pr_sourcedir.string, fname);
FS_NativePath(fname, FS_GAMEONLY, dbgfname, sizeof(dbgfname));
FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);

View File

@ -191,7 +191,7 @@ typedef enum
GAME_EDICT_BLOCKED, //(self,other)
GAME_CLIENT_SAY, //(int isteam)
GAME_PAUSED_TIC, //(int milliseconds)
} gameExport_t;
} q1qvmgameExport_t;
typedef enum

View File

@ -402,7 +402,7 @@ typedef enum {
BOTLIB_PC_READ_TOKEN,
BOTLIB_PC_SOURCE_FILE_AND_LINE
} gameImport_t;
} q3ggameImport_t;
//

View File

@ -133,6 +133,7 @@ typedef struct
struct {
char *vw_model_precache[32];
char *model_precache[MAX_MODELS]; // NULL terminated
char particle_precache[MAX_SSPARTICLESPRE][MAX_QPATH]; // NULL terminated
char sound_precache[MAX_SOUNDS][MAX_QPATH]; // NULL terminated
char *lightstyles[MAX_LIGHTSTYLES];
char lightstylecolours[MAX_LIGHTSTYLES];
@ -339,6 +340,7 @@ enum
PRESPAWN_SOUNDLIST, //nq skips these
PRESPAWN_MODELLIST,
PRESPAWN_MAPCHECK, //wait for old prespawn command
PRESPAWN_PARTICLES,
PRESPAWN_CUSTOMTENTS,
PRESPAWN_SIGNON_BUF,
PRESPAWN_SPAWNSTATIC,
@ -679,7 +681,6 @@ typedef struct
qboolean fixangle[MAX_CLIENTS];
float fixangletime[MAX_CLIENTS];
vec3_t angles[MAX_CLIENTS];
char name[MAX_OSPATH], path[MAX_OSPATH];
int parsecount;
int lastwritten;
demo_frame_t frames[DEMO_FRAMES];
@ -925,6 +926,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);
//
// sv_main.c

View File

@ -467,7 +467,7 @@ void SV_CSQC_DropAll(client_t *client)
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
Con_Printf("Reset all\n");
// Con_Printf("Reset all\n");
client->pendingentbits[0] = UF_REMOVE;
}

View File

@ -2391,6 +2391,15 @@ client_t *SVC_DirectConnect(void)
#endif
temp.edict = ent;
{
char *reject = SV_CheckRejectConnection(adr, userinfo[0], protocol, protextsupported, protextsupported2, guid);
if (reject)
{
SV_RejectMessage(protocol, "%s", reject);
return NULL;
}
}
break;
#ifdef Q2SERVER
@ -3116,10 +3125,10 @@ void SVNQ_ConnectionlessPacket(void)
continue;
case clc_stringcmd:
numnonnops++;
Cmd_TokenizeString(MSG_ReadString(), false, false);
if (!strcmp("challengeconnect", Cmd_Argv(0)))
if (msg_readcount+17 <= net_message.cursize && !strncmp("challengeconnect ", &net_message.data[msg_readcount], 17))
{
client_t *newcl;
Cmd_TokenizeString(MSG_ReadStringLine(), false, false);
/*okay, so this is a reliable packet from a client, containing a 'cmd challengeconnect $challenge' response*/
str = va("connect %i %i %s \"\\name\\unconnected\\mod\\%s\\modver\\%s\\flags\\%s\\password\\%s\"", NET_PROTOCOL_VERSION, 0, Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3), Cmd_Argv(4), Cmd_Argv(5));
Cmd_TokenizeString (str, false, false);
@ -3131,6 +3140,8 @@ void SVNQ_ConnectionlessPacket(void)
/*if there is anything else in the packet, we don't actually care. its reliable, so they'll resend*/
return;
}
else
MSG_ReadString();
continue;
case -1:
break;

View File

@ -70,9 +70,6 @@ int demomsgtype;
int demomsgto;
static char demomsgbuf[MAX_OVERALLMSGLEN];
entity_state_t demo_entities[UPDATE_MASK+1][MAX_MVDPACKET_ENTITIES];
client_frame_t demo_frames[UPDATE_MASK+1];
mvddest_t *singledest;
mvddest_t *SV_InitStream(int socket);
@ -80,6 +77,7 @@ static qboolean SV_MVD_Record (mvddest_t *dest);
char *SV_MVDName2Txt(char *name);
extern cvar_t qtv_password;
//does not unlink.
void DestClose(mvddest_t *d, qboolean destroyfiles)
{
char path[MAX_OSPATH];
@ -337,6 +335,8 @@ void SV_MVD_RunPendingConnections(void)
//COMPRESSION: Suggests a compression method (multiple are allowed). You'll get a COMPRESSION response, and compression will begin with the binary data.
start = start+1;
while(*start == ' ' || *start == '\t')
start++;
Con_Printf("qtv, got (%s) (%s)\n", com_token, start);
if (!strcmp(com_token, "VERSION"))
{
@ -1292,6 +1292,25 @@ static char *SV_PrintTeams(void)
return va("%s",buf);
}
mvddest_t *SV_FindRecordFile(char *match, mvddest_t ***link_out)
{
mvddest_t **link, *f;
for (link = &demo.dest; *link; link = &(*link)->nextdest)
{
f = *link;
if (f->desttype == DEST_FILE || f->desttype == DEST_BUFFEREDFILE)
{
if (!match || !strcmp(match, f->name))
{
if (link_out)
*link_out = link;
return f;
}
}
}
return NULL;
}
/*
====================
SV_InitRecord
@ -1338,8 +1357,8 @@ mvddest_t *SV_InitRecordFile (char *name)
Q_strncpyz(dst->name, s+1, sizeof(dst->name));
Q_strncpyz(dst->path, sv_demoDir.string, sizeof(dst->path));
if (!*demo.path)
Q_strncpyz(demo.path, ".", MAX_OSPATH);
if (!*dst->path)
Q_strncpyz(dst->path, ".", MAX_OSPATH);
SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording (%s):\n%s\n", (dst->desttype == DEST_BUFFEREDFILE) ? "memory" : "disk", name);
Cvar_ForceSet(Cvar_Get("serverdemo", "", CVAR_NOSET, ""), SV_Demo_CurrentOutput());
@ -1560,17 +1579,6 @@ void SV_WriteSetMVDMessage (void)
void SV_MVD_SendInitialGamestate(mvddest_t *dest);
static qboolean SV_MVD_Record (mvddest_t *dest)
{
/* sizebuf_t buf;
char buf_data[MAX_QWMSGLEN];
int n, i;
char *s, info[MAX_INFO_STRING];
client_t *player;
char *gamedir;
int seq = 1;
*/
int i;
if (!dest)
return false;
@ -1579,14 +1587,8 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
if (!sv.mvdrecording)
{
memset(&demo, 0, sizeof(demo));
demo.recorder.frameunion.frames = demo_frames;
demo.recorder.protocol = SCP_QUAKEWORLD;
demo.recorder.netchan.netprim = sv.datagram.prim;
for (i = 0; i < UPDATE_BACKUP; i++)
{
demo.recorder.frameunion.frames[i].entities.max_entities = MAX_MVDPACKET_ENTITIES;
demo.recorder.frameunion.frames[i].entities.entities = demo_entities[i];
}
demo.datagram.maxsize = sizeof(demo.datagram_data);
demo.datagram.data = demo.datagram_data;
@ -1604,7 +1606,7 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
else if (sv_demoExtensions.ival)
{ /*everything*/
demo.recorder.fteprotocolextensions = PEXT_CSQC | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_CUSTOMTEMPEFFECTS | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_HULLSIZE | PEXT_LIGHTSTYLECOL | PEXT_MODELDBL | PEXT_SCALE | PEXT_SETATTACHMENT | PEXT_SETVIEW | PEXT_SOUNDDBL | PEXT_SPAWNSTATIC2 | PEXT_TRANS | PEXT_VIEW2;
demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_PRYDONCURSOR;
demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_PRYDONCURSOR | PEXT2_REPLACEMENTDELTAS;
/*assume that all playback will be done with a valid csprogs that can correctly decode*/
demo.recorder.csqcactive = true;
/*enable these, because we might as well (stat ones are always useful)*/
@ -1620,19 +1622,6 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
//pointless extensions that are redundant with mvds
demo.recorder.fteprotocolextensions &= ~PEXT_ACCURATETIMINGS | PEXT_HLBSP|PEXT_Q2BSP|PEXT_Q3BSP;
demo.recorder.max_net_ents = 512;
if (demo.recorder.fteprotocolextensions & PEXT_ENTITYDBL)
demo.recorder.max_net_ents += 512;
if (demo.recorder.fteprotocolextensions & PEXT_ENTITYDBL2)
demo.recorder.max_net_ents += 1024;
if (demo.recorder.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
demo.recorder.max_net_ents = 32767;
if (demo.recorder.fteprotocolextensions & PEXT_MODELDBL)
demo.recorder.maxmodels = MAX_MODELS;
else
demo.recorder.maxmodels = 256;
}
// else
// SV_WriteRecordMVDMessage(&buf, dem_read);
@ -1640,9 +1629,12 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
dest->nextdest = demo.dest;
demo.dest = dest;
SV_ClientProtocolExtensionsChanged(&demo.recorder);
SV_MVD_SendInitialGamestate(dest);
return true;
}
void SV_EnableClientsCSQC(void);
void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{
sizebuf_t buf;
@ -1658,6 +1650,10 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
sv.mvdrecording = true;
host_client = &demo.recorder;
if (host_client->fteprotocolextensions & PEXT_CSQC)
SV_EnableClientsCSQC();
demo.pingtime = demo.time = sv.time;
@ -1817,7 +1813,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (demo.recorder.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
MSG_WriteByte(&buf, svcfte_spawnbaseline2);
SVQW_WriteDelta(&from, state, &buf, true, demo.recorder.fteprotocolextensions);
SVFTE_EmitBaseline(state, true, &buf);
}
else if (!ent)
{
@ -1917,7 +1913,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (!sv.strings.lightstyles[i])
continue;
#ifdef PEXT_LIGHTSTYLECOL
if ((demo.recorder.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7)
if ((demo.recorder.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7 && sv.strings.lightstyles[i])
{
MSG_WriteByte (&buf, svcfte_lightstylecol);
MSG_WriteByte (&buf, (unsigned char)i);
@ -2588,6 +2584,7 @@ void SV_MVDRemove_f (void)
char name[MAX_MVD_NAME], *ptr;
char path[MAX_OSPATH];
int i;
mvddest_t *active;
if (Cmd_Argc() != 2)
{
@ -2610,7 +2607,8 @@ void SV_MVDRemove_f (void)
{
if (strstr(list->name, ptr))
{
if (sv.mvdrecording && !strcmp(list->name, demo.name))
mvddest_t *active = SV_FindRecordFile(list->name, NULL);
if (active)
SV_MVDStop_f();
// stop recording first;
@ -2643,7 +2641,8 @@ void SV_MVDRemove_f (void)
snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name);
if (sv.mvdrecording && !strcmp(name, demo.name))
active = SV_FindRecordFile(name, NULL);
if (active)
SV_MVDStop_f();
if (FS_Remove(path, FS_GAMEONLY))
@ -2680,7 +2679,8 @@ void SV_MVDRemoveNum_f (void)
if (name != NULL)
{
if (sv.mvdrecording && !strcmp(name, demo.name))
mvddest_t *active = SV_FindRecordFile(name, NULL);
if (active)
SV_MVDStop_f();
snprintf(path, MAX_OSPATH, "%s/%s", sv_demoDir.string, name);
@ -2710,13 +2710,14 @@ void SV_MVDInfoAdd_f (void)
if (!strcmp(Cmd_Argv(1), "*"))
{
if (!sv.mvdrecording)
mvddest_t *active = SV_FindRecordFile(NULL, NULL);
if (!active)
{
Con_Printf("Not recording demo!\n");
return;
}
snprintf(path, MAX_OSPATH, "%s/%s", demo.path, SV_MVDName2Txt(demo.name));
snprintf(path, MAX_OSPATH, "%s/%s", active->path, SV_MVDName2Txt(active->name));
}
else
{
@ -2761,13 +2762,14 @@ void SV_MVDInfoRemove_f (void)
if (!strcmp(Cmd_Argv(1), "*"))
{
if (!sv.mvdrecording)
mvddest_t *active = SV_FindRecordFile(NULL, NULL);
if (!active)
{
Con_Printf("Not recording demo!\n");
return;
}
snprintf(path, MAX_OSPATH, "%s/%s", demo.path, SV_MVDName2Txt(demo.name));
snprintf(path, MAX_OSPATH, "%s/%s", active->path, SV_MVDName2Txt(active->name));
}
else
{
@ -2802,13 +2804,14 @@ void SV_MVDInfo_f (void)
if (!strcmp(Cmd_Argv(1), "*"))
{
if (!sv.mvdrecording)
mvddest_t *active = SV_FindRecordFile(NULL, NULL);
if (!active)
{
Con_Printf("Not recording demo!\n");
return;
}
snprintf(path, MAX_OSPATH, "%s/%s", demo.path, SV_MVDName2Txt(demo.name));
snprintf(path, MAX_OSPATH, "%s/%s", active->path, SV_MVDName2Txt(active->name));
}
else
{

View File

@ -2463,6 +2463,7 @@ void SV_SendClientMessages (void)
#pragma optimize( "", on )
#endif
void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time);
void DemoWriteQTVTimePad(int msecs);
#define Max(a, b) ((a>b)?a:b)
@ -2618,29 +2619,34 @@ void SV_SendMVDMessage(void)
if (!demo.recorder.delta_sequence)
demo.recorder.delta_sequence = -1;
SV_WriteEntitiesToClient (&demo.recorder, &msg, true);
dmsg = MVDWrite_Begin(dem_all, 0, msg.cursize);
SZ_Write (dmsg, msg.data, msg.cursize);
// copy the accumulated multicast datagram
// for this client out to the message
if (demo.datagram.cursize)
if (demo.datagram.cursize && sv.mvdrecording)
{
dmsg = MVDWrite_Begin(dem_all, 0, demo.datagram.cursize);
SZ_Write (dmsg, demo.datagram.data, demo.datagram.cursize);
SZ_Clear (&demo.datagram);
}
demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255;
demo.recorder.netchan.incoming_sequence++;
demo.frames[demo.parsecount&DEMO_FRAMES_MASK].time = demo.time = sv.time;
if (demo.parsecount - demo.lastwritten > 60) // that's a backup of 3sec in 20fps, should be enough
while (demo.lastwritten < demo.parsecount-1 && sv.mvdrecording)
{
SV_MVDWritePackets(1);
}
demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255;
demo.recorder.netchan.incoming_sequence++;
demo.frames[demo.parsecount&DEMO_FRAMES_MASK].time = demo.time = sv.time;
if (sv.mvdrecording)
{
SV_WriteEntitiesToClient (&demo.recorder, &msg, true);
SV_WriteMVDMessage(&msg, dem_all, 0, sv.time);
// dmsg = MVDWrite_Begin(dem_all, 0, msg.cursize);
// SZ_Write (dmsg, msg.data, msg.cursize);
}
demo.parsecount++;
// MVDSetMsgBuf(demo.dbuf,&demo.frames[demo.parsecount&DEMO_FRAMES_MASK].buf);
}

View File

@ -1092,6 +1092,27 @@ void SV_SendClientPrespawnInfo(client_t *client)
return;
}
if (client->prespawn_stage == PRESPAWN_PARTICLES)
{
while (client->netchan.message.cursize < (client->netchan.message.maxsize/2))
{
if (client->prespawn_idx >= MAX_SSPARTICLESPRE)
{
client->prespawn_stage++;
client->prespawn_idx = 0;
break;
}
if (*sv.strings.particle_precache[client->prespawn_idx])
{
ClientReliableWrite_Begin (client, ISNQCLIENT(client)?svcdp_precache:svcfte_precache, 4 + strlen(sv.strings.particle_precache[client->prespawn_idx]));
ClientReliableWrite_Short (client, client->prespawn_idx | PC_PARTICLE);
ClientReliableWrite_String (client, sv.strings.particle_precache[client->prespawn_idx]);
}
client->prespawn_idx++;
}
}
if (client->prespawn_stage == PRESPAWN_CUSTOMTENTS)
{
while (client->netchan.message.cursize < (client->netchan.message.maxsize/2))
@ -2482,7 +2503,7 @@ qboolean SV_AllowDownload (const char *name)
name = cleanname;
//allowed at all?
if (!allow_download.value)
if (!allow_download.ival)
return false;
//no subdirs?
@ -2499,11 +2520,11 @@ qboolean SV_AllowDownload (const char *name)
{
if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name)))
{
if (!allow_download_packages.ival)
return false;
/*do not permit 'id1/pak1.pak' or 'baseq3/pak0.pk3' or any similarly named packages. such packages would violate copyright, and must be obtained through other means (like buying the damn game)*/
if (FS_GetPackageDownloadable(name+8))
return !!allow_download_packages.value;
else
return !!allow_download_copyrighted.ival;
return !!allow_download_packages.ival;
}
return false;
}
@ -2579,7 +2600,10 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
if (!SV_AllowDownload(name))
{
Sys_Printf ("%s denied download of %s due to path/name rules\n", host_client->name, name);
return -2; //not permitted (even if it exists).
}
//mvdsv demo downloading support demonum/ -> demos/XXXX (sets up the client paths)
if (!strncmp(name, "demonum/", 8))
@ -2662,7 +2686,10 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
if (protectedpak)
{
if (!allow_download_anymap.value && !strncmp(name, "maps/", 5))
{
Sys_Printf ("%s denied download of %s - it is in a pak\n", host_client->name, name+8);
return -2;
}
}
if (replacementname)
@ -2685,7 +2712,10 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
if (protectedpak)
{ //if its in a pak file, don't allow downloads if we don't allow the contents of paks to be sent.
if (!allow_download_pakcontents.value)
{
Sys_Printf ("%s denied download of %s - it is in a pak\n", host_client->name, name+8);
return -2;
}
}
if (replacementname && *replacementname)

View File

@ -253,6 +253,26 @@
RelativePath="..\netchan.c"
>
</File>
<File
RelativePath="..\nq_api.c"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\parse.c"
>

View File

@ -112,7 +112,7 @@ private:
if (dy > 0)
{
//if we're moving downwards, we need to write the bottom before the top (so we don't overwrite the data before its copied)
for (y = h; y >= 0; y--)
for (y = h-1; y >= 0; y--)
{
memmove(ctx->buffer + (dl + (dt+y)*ctx->width), ctx->buffer + (sl + (st+y)*ctx->width), w*4);
}
@ -244,7 +244,11 @@ static void Dec_GetSize (void *vctx, int *width, int *height)
static qboolean Dec_SetSize (void *vctx, int width, int height)
{
decctx *ctx = (decctx*)vctx;
if (ctx->width == width || ctx->height == height)
if (width < 4)
width = 4;
if (height < 4)
height = 4;
if (ctx->width == width && ctx->height == height)
return qtrue; //no point
//there's no resize notification. apparently javascript cannot resize windows. yay.