mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-21 19:41:14 +00:00
preliminary bidi support.
add blind+speconly penalties. add dpi-aware flag. fix issue when switching between singleplayer and multiplayer between maps. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4703 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
75e22d98fe
commit
a704b1423b
11 changed files with 274 additions and 13 deletions
|
@ -1299,6 +1299,12 @@ void CL_ClearState (void)
|
|||
|
||||
if (cl.lerpents)
|
||||
BZ_Free(cl.lerpents);
|
||||
if (cl.particle_ssprecaches)
|
||||
{
|
||||
for (i = 0; i < MAX_SSPARTICLESPRE; i++)
|
||||
if (cl.particle_ssname[i])
|
||||
free(cl.particle_ssname[i]);
|
||||
}
|
||||
|
||||
{
|
||||
downloadlist_t *next;
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:trustInfo>
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</asmv3:trustInfo>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
|
@ -2684,6 +2684,186 @@ static unsigned int koi2wc (unsigned char uc)
|
|||
return uc;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
BIDI_NEUTRAL,
|
||||
BIDI_LTR,
|
||||
BIDI_RTL,
|
||||
};
|
||||
static char *bidi_chartype;
|
||||
static unsigned int bidi_charcount;
|
||||
|
||||
|
||||
//semi-colon delimited tokens
|
||||
char *COM_ParseStringSetSep (const char *data, char sep)
|
||||
{
|
||||
int c;
|
||||
size_t len;
|
||||
|
||||
len = 0;
|
||||
com_token[0] = 0;
|
||||
|
||||
if (data)
|
||||
for (;*data;)
|
||||
{
|
||||
if (len >= sizeof(com_token)-1)
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return (char*)data;
|
||||
}
|
||||
c = *data++;
|
||||
if (c == ';')
|
||||
break;
|
||||
com_token[len++] = c;
|
||||
}
|
||||
|
||||
com_token[len] = 0;
|
||||
return (char*)data;
|
||||
}
|
||||
void COM_BiDi_Setup(void)
|
||||
{
|
||||
char *file;
|
||||
char *line;
|
||||
char *end;
|
||||
char *tok;
|
||||
unsigned int c;
|
||||
qofs_t size;
|
||||
|
||||
file = FS_MallocFile("bidi.dat", FS_ROOT, &size);
|
||||
if (file)
|
||||
{
|
||||
bidi_chartype = file;
|
||||
bidi_charcount = size;
|
||||
return;
|
||||
}
|
||||
|
||||
file = FS_MallocFile("UnicodeData.txt", FS_ROOT, NULL);
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
bidi_charcount = 0xffff;
|
||||
bidi_chartype = BZ_Malloc(bidi_charcount);
|
||||
if (!bidi_chartype)
|
||||
bidi_charcount = 0;
|
||||
else
|
||||
{
|
||||
for (c = 0; c < bidi_charcount; c++)
|
||||
bidi_chartype[c] = BIDI_NEUTRAL;
|
||||
for(line = file; line; line = end)
|
||||
{
|
||||
end = strchr(line, '\n');
|
||||
if (end)
|
||||
*end++ = 0;
|
||||
|
||||
tok = COM_ParseStringSetSep(line,';'); //number
|
||||
c = strtoul(com_token, NULL, 16);
|
||||
tok = COM_ParseStringSetSep(tok,';'); //name
|
||||
tok = COM_ParseStringSetSep(tok,';'); //class?
|
||||
tok = COM_ParseStringSetSep(tok,';'); //?
|
||||
tok = COM_ParseStringSetSep(tok,';'); //bidi
|
||||
if (c < bidi_charcount)
|
||||
{
|
||||
if (!Q_strcasecmp(com_token, "R") || !Q_strcasecmp(com_token, "AL"))
|
||||
bidi_chartype[c] = BIDI_RTL;
|
||||
else if (!Q_strcasecmp(com_token, "L"))
|
||||
bidi_chartype[c] = BIDI_LTR;
|
||||
else
|
||||
bidi_chartype[c] = BIDI_NEUTRAL;
|
||||
}
|
||||
}
|
||||
|
||||
//trim
|
||||
while(bidi_charcount>0 && bidi_chartype[bidi_charcount-1] == BIDI_NEUTRAL)
|
||||
bidi_charcount--;
|
||||
FS_WriteFile("bidi.dat", bidi_chartype, bidi_charcount, FS_ROOT);
|
||||
}
|
||||
BZ_Free(file);
|
||||
}
|
||||
//bi-direction text is fun.
|
||||
//the text is specified in input order. the first in the string is the first entered on the keyboard.
|
||||
//this makes switching direction mid-line quite awkward. so lets hope you don't do that too often, mmkay?
|
||||
void COM_BiDi_Parse(conchar_t *fte_restrict start, size_t length)
|
||||
{
|
||||
char fl[2048], next, run, prev, para = BIDI_LTR;
|
||||
size_t i, runstart, j, k;
|
||||
unsigned int c;
|
||||
conchar_t swap;
|
||||
if (!bidi_charcount || !length || length > sizeof(fl))
|
||||
return;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
c = start[i] & CON_CHARMASK;
|
||||
if (c >= bidi_charcount)
|
||||
fl[i] = BIDI_NEUTRAL;
|
||||
else
|
||||
fl[i] = bidi_chartype[c];
|
||||
}
|
||||
|
||||
//de-neutralise it
|
||||
prev = fl[0];
|
||||
for (i = 0; i < length; )
|
||||
{
|
||||
if (fl[i] == BIDI_NEUTRAL)
|
||||
{
|
||||
next = prev; //trailing weak chars can just use the first side
|
||||
for (runstart = i; i < length; i++)
|
||||
{
|
||||
next = fl[i];
|
||||
if (next != BIDI_NEUTRAL)
|
||||
{
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//this can happen if the only text is neutral
|
||||
if (prev == BIDI_NEUTRAL)
|
||||
run = next;
|
||||
//if the strong cars are the same direction on both side, we can just use that direction
|
||||
else if (prev == next)
|
||||
run = prev;
|
||||
//if the strong chars differ, we revert to the paragraph's direction.
|
||||
else
|
||||
run = para;
|
||||
|
||||
while(runstart <= i)
|
||||
fl[runstart++] = run;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = fl[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (run = para, runstart = 0, i = 0; i <= length; i++)
|
||||
{
|
||||
if (i >= length)
|
||||
next = para;
|
||||
else
|
||||
next = fl[i];
|
||||
if (next != run)
|
||||
{
|
||||
if (run == BIDI_NEUTRAL)
|
||||
break;
|
||||
if (run == BIDI_RTL)
|
||||
{ //now swap the rtl text
|
||||
k = (i-runstart)/2;
|
||||
for (j = 0; j < k; j++)
|
||||
{
|
||||
//FIXME: ( -> ) and vice versa.
|
||||
swap = start[runstart+j];
|
||||
start[runstart+j] = start[i-j-1];
|
||||
start[i-j-1] = swap;
|
||||
}
|
||||
}
|
||||
run = next;
|
||||
runstart = 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, int flags)
|
||||
|
@ -2698,6 +2878,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
|
|||
conchar_t *linkstart = NULL;
|
||||
|
||||
conchar_t ext;
|
||||
conchar_t *oldout = out;
|
||||
|
||||
if (flags & PFS_FORCEUTF8)
|
||||
utf8 = 2;
|
||||
|
@ -3113,6 +3294,8 @@ messedup:
|
|||
}
|
||||
}
|
||||
*out = 0;
|
||||
|
||||
COM_BiDi_Parse(oldout, out - oldout);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -3272,7 +3455,7 @@ char *COM_ParseStringSet (const char *data)
|
|||
com_token[len] = c;
|
||||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
c = *(unsigned char*)data;
|
||||
} while (c>32 && c != ';');
|
||||
|
||||
com_token[len] = 0;
|
||||
|
@ -4362,6 +4545,8 @@ void COM_Init (void)
|
|||
|
||||
TranslateInit();
|
||||
|
||||
COM_BiDi_Setup();
|
||||
|
||||
|
||||
nullentitystate.hexen2flags = SCALE_ORIGIN_ORIGIN;
|
||||
nullentitystate.colormod[0] = 32;
|
||||
|
|
|
@ -444,6 +444,7 @@ qboolean FS_Remove(const char *fname, enum fs_relative relativeto); //0 on succe
|
|||
qboolean FS_Copy(const char *source, const char *dest, enum fs_relative relativesource, enum fs_relative relativedest);
|
||||
qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out, int outlen); //if you really need to fopen yourself
|
||||
qboolean FS_WriteFile (const char *filename, const void *data, int len, enum fs_relative relativeto);
|
||||
void *FS_MallocFile(const char *filename, enum fs_relative relativeto, qofs_t *filesize);
|
||||
vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto);
|
||||
vfsfile_t *FS_OpenTemp(void);
|
||||
vfsfile_t *FS_OpenTCP(const char *name, int defaultport);
|
||||
|
|
|
@ -1482,6 +1482,29 @@ void FS_CreatePath(const char *pname, enum fs_relative relativeto)
|
|||
COM_CreatePath(fullname);
|
||||
}
|
||||
|
||||
void *FS_MallocFile(const char *filename, enum fs_relative relativeto, qofs_t *filesize)
|
||||
{
|
||||
vfsfile_t *f;
|
||||
qbyte *buf;
|
||||
qofs_t len;
|
||||
|
||||
f = FS_OpenVFS(filename, "rb", relativeto);
|
||||
if (!f)
|
||||
return NULL;
|
||||
len = VFS_GETLEN(f);
|
||||
if (filesize)
|
||||
*filesize = len;
|
||||
|
||||
buf = (qbyte*)BZ_Malloc(len+1);
|
||||
if (!buf)
|
||||
Sys_Error ("FS_MallocFile: out of memory loading %s", filename);
|
||||
|
||||
((qbyte *)buf)[len] = 0;
|
||||
|
||||
VFS_READ(f, buf, len);
|
||||
VFS_CLOSE(f);
|
||||
return buf;
|
||||
}
|
||||
qboolean FS_WriteFile (const char *filename, const void *data, int len, enum fs_relative relativeto)
|
||||
{
|
||||
vfsfile_t *f;
|
||||
|
|
|
@ -580,7 +580,10 @@ static void *Terr_GenerateWater(hmsection_t *s, float maxheight)
|
|||
s->water = w;
|
||||
#ifndef SERVERONLY
|
||||
if (!isDedicated)
|
||||
{
|
||||
w->shader = R_RegisterCustom (s->hmmod->defaultwatershader, SUF_NONE, Shader_DefaultWaterShader, NULL);
|
||||
R_BuildDefaultTexnums(NULL, w->shader); //this might get expensive. hideously so.
|
||||
}
|
||||
#endif
|
||||
w->simple = true;
|
||||
w->contentmask = FTECONTENTS_WATER;
|
||||
|
|
|
@ -3015,7 +3015,7 @@ void Shader_Shutdown (void)
|
|||
for (i = 0; i < r_numshaders; i++)
|
||||
{
|
||||
shader = r_shaders[i];
|
||||
if (!shader || !shader->uses)
|
||||
if (!shader)
|
||||
continue;
|
||||
|
||||
Shader_Free(shader);
|
||||
|
@ -4886,6 +4886,9 @@ static shader_t *R_LoadShader (const char *name, unsigned int usageflags, shader
|
|||
f = r_numshaders;
|
||||
if (f == r_maxshaders)
|
||||
{
|
||||
if (!r_maxshaders)
|
||||
Sys_Error( "R_LoadShader: shader system not inited.");
|
||||
|
||||
nm = r_maxshaders * 2;
|
||||
n = realloc(r_shaders, nm*sizeof(*n));
|
||||
if (!n)
|
||||
|
|
|
@ -837,7 +837,7 @@ void SV_EvaluatePenalties(client_t *cl)
|
|||
if (delta & BAN_VIP)
|
||||
{
|
||||
delta &= ~BAN_VIP; //don't refer to this as a penalty
|
||||
if (penalties & p)
|
||||
if (penalties & BAN_VIP)
|
||||
SV_PrintToClient(cl, PRINT_HIGH, "You are a VIP, apparently\n");
|
||||
else
|
||||
SV_PrintToClient(cl, PRINT_HIGH, "VIP expired\n");
|
||||
|
@ -1068,7 +1068,7 @@ static void SV_FilterIP_f (void)
|
|||
if (Cmd_Argc() < 2)
|
||||
{
|
||||
Con_Printf("%s <address/mask|adress/maskbits> [flags] [+time] [reason]\n", Cmd_Argv(0));
|
||||
Con_Printf("allowed flags: ban,safe,cuff,mute,cripple,deaf,lag. time is in seconds (omitting the plus will be taken to mean unix time).\n", Cmd_Argv(0));
|
||||
Con_Printf("allowed flags: ban,safe,cuff,mute,cripple,deaf,lag,blind,spec. time is in seconds (omitting the plus will be taken to mean unix time).\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1109,6 +1109,8 @@ static void SV_FilterIP_f (void)
|
|||
proto.banflags |= BAN_VIP;
|
||||
else if (!Q_strcasecmp(com_token, "blind"))
|
||||
proto.banflags |= BAN_BLIND;
|
||||
else if (!Q_strcasecmp(com_token, "spec"))
|
||||
proto.banflags |= BAN_SPECONLY;
|
||||
else
|
||||
Con_Printf("Unknown ban/penalty flag: %s. ignoring.\n", com_token);
|
||||
}
|
||||
|
@ -1176,6 +1178,7 @@ static void SV_FilterList_f (void)
|
|||
"lag",
|
||||
"vip",
|
||||
"blind",
|
||||
"spec",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -1256,12 +1259,16 @@ static void SV_Unfilter_f (void)
|
|||
banflags |= BAN_LAGGED;
|
||||
else if (!Q_strcasecmp(com_token, "vip"))
|
||||
banflags |= BAN_VIP;
|
||||
else if (!Q_strcasecmp(com_token, "blind"))
|
||||
banflags |= BAN_BLIND;
|
||||
else if (!Q_strcasecmp(com_token, "spec"))
|
||||
banflags |= BAN_SPECONLY;
|
||||
else
|
||||
Con_Printf("Unknown ban/penalty flag: %s. ignoring.\n", com_token);
|
||||
}
|
||||
//if no flags were specified, assume all
|
||||
if (!banflags)
|
||||
banflags = BAN_BAN|BAN_PERMIT|BAN_CUFF|BAN_MUTE|BAN_CRIPPLED|BAN_DEAF|BAN_LAGGED|BAN_VIP;
|
||||
banflags = BAN_BAN|BAN_PERMIT|BAN_CUFF|BAN_MUTE|BAN_CRIPPLED|BAN_DEAF|BAN_LAGGED|BAN_VIP|BAN_BLIND|BAN_SPECONLY;
|
||||
|
||||
for (link = &svs.bannedips ; (nb = *link) ; )
|
||||
{
|
||||
|
|
|
@ -599,6 +599,7 @@ void SV_UpdateMaxPlayers(int newmax)
|
|||
int i;
|
||||
if (newmax != svs.allocated_client_slots)
|
||||
{
|
||||
client_t *old = svs.clients;
|
||||
for (i = newmax; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
if (svs.clients[i].state)
|
||||
|
@ -618,6 +619,19 @@ void SV_UpdateMaxPlayers(int newmax)
|
|||
svs.clients[i].name = svs.clients[i].namebuf;
|
||||
svs.clients[i].team = svs.clients[i].teambuf;
|
||||
}
|
||||
for (i = 0; i < min(newmax, svs.allocated_client_slots); i++)
|
||||
{
|
||||
if (svs.clients[i].netchan.message.data)
|
||||
svs.clients[i].netchan.message.data = (qbyte*)&svs.clients[i] + (svs.clients[i].netchan.message.data - (qbyte*)&old[i]);
|
||||
if (svs.clients[i].datagram.data)
|
||||
svs.clients[i].datagram.data = (qbyte*)&svs.clients[i] + (svs.clients[i].datagram.data - (qbyte*)&old[i]);
|
||||
if (svs.clients[i].backbuf.data)
|
||||
svs.clients[i].backbuf.data = (qbyte*)&svs.clients[i] + (svs.clients[i].backbuf.data - (qbyte*)&old[i]);
|
||||
if (svs.clients[i].controlled)
|
||||
svs.clients[i].controlled = svs.clients + (svs.clients[i].controlled - old);
|
||||
if (svs.clients[i].controller)
|
||||
svs.clients[i].controller = svs.clients + (svs.clients[i].controller - old);
|
||||
}
|
||||
svs.allocated_client_slots = sv.allocated_client_slots = newmax;
|
||||
}
|
||||
sv.allocated_client_slots = svs.allocated_client_slots;
|
||||
|
@ -852,7 +866,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
if (allow_download_refpackages.ival)
|
||||
FS_ReferenceControl(1, 1);
|
||||
|
||||
strcpy (sv.name, server);
|
||||
Q_strncpyz (sv.name, server, sizeof(sv.name));
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
//SCR_BeginLoadingPlaque();
|
||||
|
@ -900,8 +914,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer);
|
||||
extern model_t *loadmodel;
|
||||
|
||||
strcpy (sv.name, server);
|
||||
strcpy (sv.modelname, "");
|
||||
Q_strncpyz (sv.name, server, sizeof(sv.name));
|
||||
Q_strncpyz (sv.modelname, "", sizeof(sv.modelname));
|
||||
|
||||
loadmodel = sv.world.worldmodel = Mod_FindName (sv.modelname);
|
||||
loadmodel->needload = !Mod_LoadQ2BrushModel (sv.world.worldmodel, NULL);
|
||||
|
|
|
@ -68,8 +68,8 @@ sv_masterlist_t sv_masterlist[] = {
|
|||
{MP_QUAKEWORLD, CVARC("sv_master8", "", SV_Masterlist_Callback)},
|
||||
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra1", "qwmaster.ocrana.de:27000", SV_Masterlist_Callback)}, //german. admin unknown
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra2", "masterserver.exhale.de:27000", SV_Masterlist_Callback)}, //german. admin unknown
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra3", "asgaard.morphos-team.net:27000", SV_Masterlist_Callback)}, //german. admin bigfoot
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra2", ""/*"masterserver.exhale.de:27000" seems dead*/, SV_Masterlist_Callback)}, //german. admin unknown
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra3", "asgaard.morphos-team.net:27000", SV_Masterlist_Callback)}, //germany. admin bigfoot
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra4", "master.quakeservers.net:27000", SV_Masterlist_Callback)}, //european. admin: raz0?
|
||||
{MP_QUAKEWORLD, CVARC("sv_qwmasterextra5", "qwmaster.fodquake.net:27000", SV_Masterlist_Callback)},
|
||||
|
||||
|
@ -3577,6 +3577,14 @@ client_t *SVC_DirectConnect(void)
|
|||
|
||||
SV_EvaluatePenalties(newcl);
|
||||
|
||||
if (newcl->penalties & BAN_SPECONLY)
|
||||
{
|
||||
if (spectators >= maxspectators.ival)
|
||||
newcl->drop = true; //oops.
|
||||
newcl->spectator = spectator = true;
|
||||
Info_SetValueForStarKey (cl->userinfo, "*spectator", "1", sizeof(cl->userinfo));
|
||||
}
|
||||
|
||||
newcl->fteprotocolextensions &= ~PEXT_SPLITSCREEN;
|
||||
for (clients = 1; clients < numssclients; clients++)
|
||||
{
|
||||
|
|
|
@ -4402,6 +4402,12 @@ void Cmd_Join_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (host_client->penalties & BAN_SPECONLY)
|
||||
{
|
||||
SV_ClientTPrintf(host_client, PRINT_HIGH, "You are banned from joining the game.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// count players already on server
|
||||
numclients = 0;
|
||||
seats = 0;
|
||||
|
|
Loading…
Reference in a new issue