mostly miscilaneous changes (some old stuff that I don't remember), lightsampling changes, qtv changes, avi sound changes
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2379 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
4c32449d26
commit
42c43d960f
60 changed files with 2066 additions and 643 deletions
|
@ -3395,14 +3395,14 @@ void PF_sv_getlight (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
vec3_t diffuse, ambient, dir;
|
||||
if (sv.worldmodel && sv.worldmodel->funcs.LightPointValues)
|
||||
{
|
||||
sv.worldmodel->funcs.LightPointValues(point, diffuse, ambient, dir);
|
||||
sv.worldmodel->funcs.LightPointValues(sv.worldmodel, point, diffuse, ambient, dir);
|
||||
VectorMA(ambient, 0.5, diffuse, G_VECTOR(OFS_RETURN));
|
||||
}
|
||||
else
|
||||
{
|
||||
G_FLOAT(OFS_RETURN+0) = 0.5;
|
||||
G_FLOAT(OFS_RETURN+1) = 0.5;
|
||||
G_FLOAT(OFS_RETURN+2) = 0.5;
|
||||
G_FLOAT(OFS_RETURN+0) = 128;
|
||||
G_FLOAT(OFS_RETURN+1) = 128;
|
||||
G_FLOAT(OFS_RETURN+2) = 128;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3928,33 +3928,11 @@ void PF_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
PF_lightstyle
|
||||
|
||||
void(float style, string value [, float colour]) lightstyle
|
||||
===============
|
||||
*/
|
||||
void PF_lightstyle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
void PF_applylightstyle(int style, char *val, int col)
|
||||
{
|
||||
int style;
|
||||
char *val;
|
||||
client_t *client;
|
||||
int j;
|
||||
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
int col;
|
||||
if (*svprogfuncs->callargc >= 3)
|
||||
{
|
||||
col = G_FLOAT(OFS_PARM2);
|
||||
if (IS_NAN(col) || !col || col > 0x111)
|
||||
col = 7;
|
||||
}
|
||||
else col = 7;
|
||||
#endif
|
||||
|
||||
style = G_FLOAT(OFS_PARM0);
|
||||
val = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
|
||||
if (style < 0 || style >= MAX_LIGHTSTYLES)
|
||||
{
|
||||
|
@ -4009,6 +3987,35 @@ void PF_lightstyle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
PF_lightstyle
|
||||
|
||||
void(float style, string value [, float colour]) lightstyle
|
||||
===============
|
||||
*/
|
||||
void PF_lightstyle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int style;
|
||||
char *val;
|
||||
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
int col;
|
||||
if (*svprogfuncs->callargc >= 3)
|
||||
{
|
||||
col = G_FLOAT(OFS_PARM2);
|
||||
if (IS_NAN(col) || !col || col > 0x111)
|
||||
col = 7;
|
||||
}
|
||||
else col = 7;
|
||||
#endif
|
||||
|
||||
style = G_FLOAT(OFS_PARM0);
|
||||
val = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
|
||||
PF_applylightstyle(style, val, col);
|
||||
}
|
||||
|
||||
void PF_lightstylevalue (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int style;
|
||||
|
@ -4026,8 +4033,6 @@ void PF_lightstylestatic (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
int style;
|
||||
float num;
|
||||
char *val;
|
||||
client_t *client;
|
||||
int j;
|
||||
|
||||
static char *styleDefs[] =
|
||||
{
|
||||
|
@ -4056,56 +4061,7 @@ void PF_lightstylestatic (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
num = 'z'-'a'-1;
|
||||
val = styleDefs[(int)num];
|
||||
|
||||
|
||||
if (style < 0 || style >= MAX_LIGHTSTYLES)
|
||||
{
|
||||
Con_Printf("WARNING: Bad lightstyle %i.\n", style);
|
||||
return;
|
||||
}
|
||||
if (strlen(val) > MAX_STYLESTRING-1)
|
||||
Con_Printf("WARNING: Style string is longer than standard (%i). Some clients could crash.\n", MAX_STYLESTRING-1);
|
||||
|
||||
|
||||
// change the string in sv
|
||||
if (sv.strings.lightstyles[style])
|
||||
Z_Free(sv.strings.lightstyles[style]);
|
||||
sv.strings.lightstyles[style] = Z_Malloc(strlen(val)+1);
|
||||
strcpy(sv.strings.lightstyles[style], val);
|
||||
// sv.lightstyles[style] = val;
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
sv.strings.lightstylecolours[style] = col;
|
||||
#endif
|
||||
|
||||
// send message to all clients on this server
|
||||
if (sv.state != ss_active)
|
||||
return;
|
||||
|
||||
for (j=0, client = svs.clients ; j<sv.allocated_client_slots ; j++, client++)
|
||||
{
|
||||
if (client->controller)
|
||||
continue;
|
||||
|
||||
if ( client->state == cs_spawned )
|
||||
{
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
if ((client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && col!=7)
|
||||
{
|
||||
ClientReliableWrite_Begin (client, svc_lightstylecol, strlen(val)+4);
|
||||
ClientReliableWrite_Char (client, style);
|
||||
ClientReliableWrite_Char (client, col);
|
||||
ClientReliableWrite_String (client, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3);
|
||||
ClientReliableWrite_Char (client, style);
|
||||
ClientReliableWrite_String (client, val);
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
PF_applylightstyle(style, val, col);
|
||||
}
|
||||
|
||||
void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
|
@ -9188,7 +9144,7 @@ void PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals
|
|||
|
||||
|
||||
surf = model->surfaces;
|
||||
for (i = model->numsurfaces; i; i--, surf = surf++)
|
||||
for (i = model->numsurfaces; i; i--, surf++)
|
||||
{
|
||||
if (surf->flags & SURF_PLANEBACK)
|
||||
planedist = -DotProduct(point, surf->plane->normal);
|
||||
|
|
|
@ -513,6 +513,11 @@ typedef struct client_s
|
|||
|
||||
int rate;
|
||||
int drate;
|
||||
|
||||
netadr_t realip;
|
||||
int realip_status;
|
||||
int realip_num;
|
||||
int realip_ping;
|
||||
} client_t;
|
||||
|
||||
#define ISQWCLIENT(cl) ((cl)->protocol == SCP_QUAKEWORLD)
|
||||
|
@ -616,6 +621,7 @@ typedef struct
|
|||
int forceFrame;
|
||||
|
||||
struct mvddest_s *dest;
|
||||
struct mvdpendingdest_s *pendingdest;
|
||||
} demo_t;
|
||||
|
||||
|
||||
|
|
|
@ -488,14 +488,17 @@ void SV_Map_f (void)
|
|||
startspot = spot;
|
||||
}
|
||||
|
||||
COM_FlushFSCache();
|
||||
|
||||
// check to make sure the level exists
|
||||
if (*level == '*')
|
||||
{
|
||||
memmove(level, level+1, strlen(level));
|
||||
newunit=true;
|
||||
}
|
||||
#ifndef SERVERONLY
|
||||
SCR_ImageName(level);
|
||||
#endif
|
||||
|
||||
COM_FlushFSCache();
|
||||
|
||||
if (strlen(level) > 4 && !strcmp(level + strlen(level)-4, ".cin"))
|
||||
{
|
||||
|
@ -573,14 +576,15 @@ void SV_Map_f (void)
|
|||
svs.clients[i].state=cs_connected;
|
||||
}
|
||||
|
||||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SendMessagesToAll ();
|
||||
|
||||
#ifndef SERVERONLY
|
||||
S_StopAllSounds (true);
|
||||
SCR_BeginLoadingPlaque();
|
||||
// SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(level);
|
||||
#endif
|
||||
|
||||
SV_BroadcastCommand ("changing \"%s\"\n", level);
|
||||
SV_SendMessagesToAll ();
|
||||
|
||||
if (newunit || !startspot || !SV_LoadLevelCache(level, startspot, false))
|
||||
{
|
||||
if (waschangelevel && !startspot)
|
||||
|
|
|
@ -581,7 +581,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
total_loading_size = 100;
|
||||
current_loading_size = 0;
|
||||
loading_stage = 1;
|
||||
SCR_BeginLoadingPlaque();
|
||||
// SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
NET_InitServer();
|
||||
|
@ -711,7 +712,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
strcpy (sv.name, server);
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
Cvar_ApplyLatches(CVAR_LATCH);
|
||||
|
@ -772,12 +774,14 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
// SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
SV_CalcPHS ();
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
if (sv.worldmodel->fromgame == fg_doom)
|
||||
|
@ -921,7 +925,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
|
@ -993,7 +998,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
//
|
||||
|
@ -1152,7 +1158,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
Q_strncpyz(sv.mapname, sv.name, sizeof(sv.mapname));
|
||||
|
@ -1178,14 +1185,16 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
// run two frames to allow everything to settle
|
||||
realtime += 0.1;
|
||||
SV_Physics ();
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
realtime += 0.1;
|
||||
sv.time += 0.1;
|
||||
|
@ -1194,7 +1203,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
// save movement vars
|
||||
|
@ -1242,7 +1252,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
#ifndef SERVERONLY
|
||||
current_loading_size+=10;
|
||||
SCR_BeginLoadingPlaque();
|
||||
//SCR_BeginLoadingPlaque();
|
||||
SCR_ImageName(server);
|
||||
#endif
|
||||
|
||||
if (svs.gametype == GT_PROGS)
|
||||
|
|
|
@ -2196,6 +2196,61 @@ void SVC_RemoteCommand (void)
|
|||
SV_EndRedirect ();
|
||||
}
|
||||
|
||||
void SVC_RealIP (void)
|
||||
{
|
||||
unsigned int slotnum;
|
||||
int cookie;
|
||||
slotnum = atoi(Cmd_Argv(1));
|
||||
cookie = atoi(Cmd_Argv(2));
|
||||
|
||||
if (slotnum >= MAX_CLIENTS)
|
||||
{
|
||||
//a malitious user
|
||||
return;
|
||||
}
|
||||
|
||||
if (cookie != svs.clients[slotnum].realip_num)
|
||||
{
|
||||
//could be someone trying to kick someone else
|
||||
//so we can't kick, as much as we might like to.
|
||||
return;
|
||||
}
|
||||
|
||||
if (svs.clients[slotnum].realip_status)
|
||||
return;
|
||||
|
||||
|
||||
svs.clients[slotnum].realip_status = 1;
|
||||
svs.clients[slotnum].realip = net_from;
|
||||
}
|
||||
|
||||
void SVC_ACK (void)
|
||||
{
|
||||
int slotnum;
|
||||
for (slotnum = 0; slotnum < MAX_CLIENTS; slotnum++)
|
||||
{
|
||||
if (svs.clients[slotnum].state)
|
||||
{
|
||||
if (svs.clients[slotnum].realip_status == 1 && NET_CompareAdr(svs.clients[slotnum].realip, net_from))
|
||||
{
|
||||
if (!*Cmd_Argv(1))
|
||||
svs.clients[slotnum].realip_status = 2;
|
||||
else if (atoi(Cmd_Argv(1)) == svs.clients[slotnum].realip_ping &&
|
||||
atoi(Cmd_Argv(2)) == svs.clients[slotnum].realip_num)
|
||||
{
|
||||
svs.clients[slotnum].realip_status = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Netchan_OutOfBandPrint(NS_SERVER, net_from, "realip not accepted. Please stop hacking.\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ConnectionlessPacket
|
||||
|
@ -2231,7 +2286,7 @@ qboolean SV_ConnectionlessPacket (void)
|
|||
if (!strcmp(c, "ping") || ( c[0] == A2A_PING && (c[1] == 0 || c[1] == '\n')) )
|
||||
SVC_Ping ();
|
||||
else if (c[0] == A2A_ACK && (c[1] == 0 || c[1] == '\n') )
|
||||
Con_Printf ("A2A_ACK from %s\n", NET_AdrToString (net_from));
|
||||
SVC_ACK ();
|
||||
else if (!strcmp(c,"status"))
|
||||
SVC_Status ();
|
||||
else if (!strcmp(c,"log"))
|
||||
|
@ -2272,6 +2327,8 @@ qboolean SV_ConnectionlessPacket (void)
|
|||
#endif
|
||||
else if (!strcmp(c, "rcon"))
|
||||
SVC_RemoteCommand ();
|
||||
else if (!strcmp(c, "realip"))
|
||||
SVC_RealIP ();
|
||||
else if (!PR_GameCodePacket(net_message.data+4))
|
||||
Con_Printf ("bad connectionless packet from %s:\n%s\n"
|
||||
, NET_AdrToString (net_from), s);
|
||||
|
|
|
@ -30,6 +30,24 @@ void SV_MVDStop_f (void);
|
|||
|
||||
#define demo_size_padding 0x1000
|
||||
|
||||
//qtv proxies are meant to send a small header now, bit like http
|
||||
//this header gives supported version numbers and stuff
|
||||
typedef struct mvdpendingdest_s {
|
||||
qboolean error; //disables writers, quit ASAP.
|
||||
int socket;
|
||||
|
||||
char inbuffer[2048];
|
||||
char outbuffer[2048];
|
||||
|
||||
char challenge[64];
|
||||
int hasauthed;
|
||||
|
||||
int insize;
|
||||
int outsize;
|
||||
|
||||
struct mvdpendingdest_s *nextdest;
|
||||
} mvdpendingdest_t;
|
||||
|
||||
typedef struct mvddest_s {
|
||||
qboolean error; //disables writers, quit ASAP.
|
||||
|
||||
|
@ -51,6 +69,10 @@ typedef struct mvddest_s {
|
|||
} mvddest_t;
|
||||
mvddest_t *singledest;
|
||||
|
||||
mvddest_t *SV_InitStream(int socket);
|
||||
static qboolean SV_MVD_Record (mvddest_t *dest);
|
||||
extern cvar_t qtv_password;
|
||||
|
||||
void DestClose(mvddest_t *d, qboolean destroyfiles)
|
||||
{
|
||||
char path[MAX_OSPATH];
|
||||
|
@ -151,6 +173,364 @@ void DestFlush(qboolean compleate)
|
|||
}
|
||||
}
|
||||
|
||||
void SV_MVD_RunPendingConnections(void)
|
||||
{
|
||||
unsigned short ushort_result;
|
||||
char *e;
|
||||
int len;
|
||||
mvdpendingdest_t *p;
|
||||
mvdpendingdest_t *np;
|
||||
|
||||
if (!demo.pendingdest)
|
||||
return;
|
||||
|
||||
while (demo.pendingdest && demo.pendingdest->error)
|
||||
{
|
||||
np = demo.pendingdest->nextdest;
|
||||
|
||||
if (demo.pendingdest->socket != -1)
|
||||
closesocket(demo.pendingdest->socket);
|
||||
Z_Free(demo.pendingdest);
|
||||
demo.pendingdest = np;
|
||||
}
|
||||
|
||||
for (p = demo.pendingdest; p && p->nextdest; p = p->nextdest)
|
||||
{
|
||||
if (p->nextdest->error)
|
||||
{
|
||||
np = p->nextdest->nextdest;
|
||||
if (p->nextdest->socket != -1)
|
||||
closesocket(p->nextdest->socket);
|
||||
Z_Free(p->nextdest);
|
||||
p->nextdest = np;
|
||||
}
|
||||
}
|
||||
|
||||
for (p = demo.pendingdest; p; p = p->nextdest)
|
||||
{
|
||||
if (p->outsize && !p->error)
|
||||
{
|
||||
len = send(p->socket, p->outbuffer, p->outsize, 0);
|
||||
if (len == 0) //client died
|
||||
p->error = true;
|
||||
else if (len > 0) //we put some data through
|
||||
{ //move up the buffer
|
||||
p->outsize -= len;
|
||||
memmove(p->outbuffer, p->outbuffer+len, p->outsize );
|
||||
}
|
||||
else
|
||||
{ //error of some kind. would block or something
|
||||
int e;
|
||||
e = qerrno;
|
||||
if (e != EWOULDBLOCK)
|
||||
p->error = true;
|
||||
}
|
||||
}
|
||||
if (!p->error)
|
||||
{
|
||||
len = recv(p->socket, p->inbuffer + p->insize, sizeof(p->inbuffer) - p->insize - 1, 0);
|
||||
if (len > 0)
|
||||
{//fixme: cope with extra \rs
|
||||
char *end;
|
||||
p->insize += len;
|
||||
p->inbuffer[p->insize] = 0;
|
||||
|
||||
for (end = p->inbuffer; ; end++)
|
||||
{
|
||||
if (*end == '\0')
|
||||
{
|
||||
end = NULL;
|
||||
break; //not enough data
|
||||
}
|
||||
|
||||
if (end[0] == '\n')
|
||||
{
|
||||
if (end[1] == '\n')
|
||||
{
|
||||
end[1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end)
|
||||
{ //we found the end of the header
|
||||
char *start, *lineend;
|
||||
int versiontouse = 0;
|
||||
int raw = 0;
|
||||
char password[256] = "";
|
||||
enum {
|
||||
QTVAM_NONE,
|
||||
QTVAM_PLAIN,
|
||||
QTVAM_CCITT,
|
||||
QTVAM_MD4,
|
||||
QTVAM_MD5,
|
||||
} authmethod = QTVAM_NONE;
|
||||
|
||||
start = p->inbuffer;
|
||||
|
||||
lineend = strchr(start, '\n');
|
||||
if (!lineend)
|
||||
{
|
||||
// char *e;
|
||||
// e = "This is a QTV server.";
|
||||
// send(p->socket, e, strlen(e), 0);
|
||||
|
||||
p->error = true;
|
||||
continue;
|
||||
}
|
||||
*lineend = '\0';
|
||||
COM_ParseToken(start, NULL);
|
||||
start = lineend+1;
|
||||
if (strcmp(com_token, "QTV"))
|
||||
{ //it's an error if it's not qtv.
|
||||
p->error = true;
|
||||
lineend = strchr(start, '\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
lineend = strchr(start, '\n');
|
||||
if (!lineend)
|
||||
break;
|
||||
*lineend = '\0';
|
||||
start = COM_ParseToken(start, NULL);
|
||||
if (*start == ':')
|
||||
{
|
||||
//VERSION: a list of the different qtv protocols supported. Multiple versions can be specified. The first is assumed to be the prefered version.
|
||||
//RAW: if non-zero, send only a raw mvd with no additional markup anywhere (for telnet use). Doesn't work with challenge-based auth, so will only be accepted when proxy passwords are not required.
|
||||
//AUTH: specifies an auth method, the exact specs varies based on the method
|
||||
// PLAIN: the password is sent as a PASSWORD line
|
||||
// MD4: the server responds with an "AUTH: MD4\n" line as well as a "CHALLENGE: somerandomchallengestring\n" line, the client sends a new 'initial' request with CHALLENGE: MD4\nRESPONSE: hexbasedmd4checksumhere\n"
|
||||
// MD5: same as md4
|
||||
// CCITT: same as md4, but using the CRC stuff common to all quake engines.
|
||||
// if the supported/allowed auth methods don't match, the connection is silently dropped.
|
||||
//SOURCE: which stream to play from, DEFAULT is special. Without qualifiers, it's assumed to be a tcp address.
|
||||
//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;
|
||||
Con_Printf("qtv, got (%s) (%s)\n", com_token, start);
|
||||
if (!strcmp(com_token, "VERSION"))
|
||||
{
|
||||
start = COM_ParseToken(start, NULL);
|
||||
if (atoi(com_token) == 1)
|
||||
versiontouse = 1;
|
||||
}
|
||||
else if (!strcmp(com_token, "RAW"))
|
||||
{
|
||||
start = COM_ParseToken(start, NULL);
|
||||
raw = atoi(com_token);
|
||||
}
|
||||
else if (!strcmp(com_token, "PASSWORD"))
|
||||
{
|
||||
start = COM_ParseToken(start, NULL);
|
||||
Q_strncpyz(password, com_token, sizeof(password));
|
||||
}
|
||||
else if (!strcmp(com_token, "AUTH"))
|
||||
{
|
||||
int thisauth;
|
||||
start = COM_ParseToken(start, NULL);
|
||||
if (!strcmp(com_token, "NONE"))
|
||||
thisauth = QTVAM_PLAIN;
|
||||
else if (!strcmp(com_token, "PLAIN"))
|
||||
thisauth = QTVAM_PLAIN;
|
||||
else if (!strcmp(com_token, "CCIT"))
|
||||
thisauth = QTVAM_CCITT;
|
||||
else if (!strcmp(com_token, "MD4"))
|
||||
thisauth = QTVAM_MD4;
|
||||
// else if (!strcmp(com_token, "MD5"))
|
||||
// thisauth = QTVAM_MD5;
|
||||
else
|
||||
{
|
||||
thisauth = QTVAM_NONE;
|
||||
Con_DPrintf("qtv: received unrecognised auth method (%s)\n", com_token);
|
||||
}
|
||||
|
||||
if (authmethod < thisauth)
|
||||
authmethod = thisauth;
|
||||
}
|
||||
else if (!strcmp(com_token, "SOURCE"))
|
||||
{
|
||||
//servers don't support source, and ignore it.
|
||||
//source is only useful for qtv proxy servers.
|
||||
}
|
||||
else if (!strcmp(com_token, "COMPRESSION"))
|
||||
{
|
||||
//compression not supported yet
|
||||
}
|
||||
else
|
||||
{
|
||||
//not recognised.
|
||||
}
|
||||
}
|
||||
start = lineend+1;
|
||||
}
|
||||
|
||||
len = (end - p->inbuffer)+2;
|
||||
p->insize -= len;
|
||||
memmove(p->inbuffer, p->inbuffer + len, p->insize);
|
||||
p->inbuffer[p->insize] = 0;
|
||||
|
||||
e = NULL;
|
||||
if (p->hasauthed)
|
||||
{
|
||||
}
|
||||
else if (!*qtv_password.string)
|
||||
p->hasauthed = true; //no password, no need to auth.
|
||||
else if (*password)
|
||||
{
|
||||
switch (authmethod)
|
||||
{
|
||||
case QTVAM_NONE:
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: You need to provide a common auth method.\n\n");
|
||||
break;
|
||||
case QTVAM_PLAIN:
|
||||
p->hasauthed = !strcmp(qtv_password.string, password);
|
||||
break;
|
||||
case QTVAM_CCITT:
|
||||
QCRC_Init(&ushort_result);
|
||||
QCRC_AddBlock(&ushort_result, p->challenge, strlen(p->challenge));
|
||||
QCRC_AddBlock(&ushort_result, qtv_password.string, strlen(qtv_password.string));
|
||||
p->hasauthed = (ushort_result == atoi(password));
|
||||
break;
|
||||
case QTVAM_MD4:
|
||||
{
|
||||
char hash[512];
|
||||
int md4sum[4];
|
||||
|
||||
snprintf(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
|
||||
Com_BlockFullChecksum (hash, strlen(hash), (unsigned char*)md4sum);
|
||||
sprintf(hash, "%X%X%X%X", md4sum[0], md4sum[1], md4sum[2], md4sum[3]);
|
||||
p->hasauthed = !strcmp(password, hash);
|
||||
}
|
||||
break;
|
||||
case QTVAM_MD5:
|
||||
default:
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: FTEQWSV bug detected.\n\n");
|
||||
break;
|
||||
}
|
||||
if (!p->hasauthed && !e)
|
||||
{
|
||||
if (raw)
|
||||
e = "";
|
||||
else
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: Bad password.\n\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//no password, and not automagically authed
|
||||
switch (authmethod)
|
||||
{
|
||||
case QTVAM_NONE:
|
||||
if (raw)
|
||||
e = "";
|
||||
else
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: You need to provide a common auth method.\n\n");
|
||||
break;
|
||||
case QTVAM_PLAIN:
|
||||
p->hasauthed = !strcmp(qtv_password.string, password);
|
||||
break;
|
||||
|
||||
if (0)
|
||||
{
|
||||
case QTVAM_CCITT:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: CCITT\n"
|
||||
"CHALLENGE: ");
|
||||
}
|
||||
else if (0)
|
||||
{
|
||||
case QTVAM_MD4:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: MD4\n"
|
||||
"CHALLENGE: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
case QTVAM_MD5:
|
||||
e = ("QTVSV 1\n"
|
||||
"AUTH: MD5\n"
|
||||
"CHALLENGE: ");
|
||||
}
|
||||
|
||||
send(p->socket, e, strlen(e), 0);
|
||||
send(p->socket, p->challenge, strlen(p->challenge), 0);
|
||||
e = "\n\n";
|
||||
send(p->socket, e, strlen(e), 0);
|
||||
continue;
|
||||
|
||||
default:
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: FTEQWSV bug detected.\n\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e)
|
||||
{
|
||||
}
|
||||
else if (!versiontouse)
|
||||
{
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: Incompatable version (valid version is v1)\n\n");
|
||||
}
|
||||
else if (raw)
|
||||
{
|
||||
if (p->hasauthed == false)
|
||||
{
|
||||
e = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_MVD_Record(SV_InitStream(p->socket));
|
||||
p->socket = -1; //so it's not cleared wrongly.
|
||||
}
|
||||
p->error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->hasauthed == true)
|
||||
{
|
||||
e = ("QTVSV 1\n"
|
||||
"\n");
|
||||
send(p->socket, e, strlen(e), 0);
|
||||
e = NULL;
|
||||
SV_MVD_Record(SV_InitStream(p->socket));
|
||||
p->socket = -1; //so it's not cleared wrongly.
|
||||
}
|
||||
else
|
||||
{
|
||||
e = ("QTVSV 1\n"
|
||||
"PERROR: You need to provide a password.\n\n");
|
||||
}
|
||||
p->error = true;
|
||||
}
|
||||
|
||||
if (e)
|
||||
{
|
||||
send(p->socket, e, strlen(e), 0);
|
||||
p->error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (len == 0)
|
||||
p->error = true;
|
||||
else
|
||||
{ //error of some kind. would block or something
|
||||
int e;
|
||||
e = qerrno;
|
||||
if (e != EWOULDBLOCK)
|
||||
p->error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DestCloseAllFlush(qboolean destroyfiles)
|
||||
{
|
||||
mvddest_t *d;
|
||||
|
@ -192,7 +572,7 @@ int DemoWriteDest(void *data, int len, mvddest_t *d)
|
|||
return len;
|
||||
}
|
||||
|
||||
int DemoWrite(void *data, int len) //broadcast to all proxies
|
||||
int DemoWrite(void *data, int len) //broadcast to all proxies/mvds
|
||||
{
|
||||
mvddest_t *d;
|
||||
for (d = demo.dest; d; d = d->nextdest)
|
||||
|
@ -204,6 +584,36 @@ int DemoWrite(void *data, int len) //broadcast to all proxies
|
|||
return len;
|
||||
}
|
||||
|
||||
void DemoWriteQTVTimePad(int msecs) //broadcast to all proxies
|
||||
{
|
||||
mvddest_t *d;
|
||||
unsigned char buffer[6];
|
||||
while (msecs > 0)
|
||||
{
|
||||
//duration
|
||||
if (msecs > 255)
|
||||
buffer[0] = 255;
|
||||
else
|
||||
buffer[0] = msecs;
|
||||
msecs -= buffer[0];
|
||||
//message type
|
||||
buffer[1] = dem_read;
|
||||
//length
|
||||
buffer[2] = 0;
|
||||
buffer[3] = 0;
|
||||
buffer[4] = 0;
|
||||
buffer[5] = 0;
|
||||
|
||||
for (d = demo.dest; d; d = d->nextdest)
|
||||
{
|
||||
if (d->desttype == DEST_STREAM)
|
||||
{
|
||||
DemoWriteDest(buffer, sizeof(buffer), d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SV_TimeOfDay(date_t *date)
|
||||
{
|
||||
|
@ -395,8 +805,9 @@ cvar_t sv_demoNoVis = SCVAR("sv_demoNoVis", "");
|
|||
cvar_t sv_demoMaxSize = SCVAR("sv_demoMaxSize", "");
|
||||
cvar_t sv_demoExtraNames = SCVAR("sv_demoExtraNames", "");
|
||||
|
||||
cvar_t mvd_streamport = SCVAR("mvd_streamport", "0");
|
||||
cvar_t mvd_maxstreams = SCVAR("mvd_maxstreams", "1");
|
||||
cvar_t qtv_password = SCVAR("qtv_password", "");
|
||||
cvar_t qtv_streamport = FCVAR("qtv_streamport", "mvd_streamport", "0", 0);
|
||||
cvar_t qtv_maxstreams = FCVAR("qtv_maxstreams", "mvd_maxstreams", "1", 0);
|
||||
|
||||
cvar_t sv_demoPrefix = SCVAR("sv_demoPrefix", "");
|
||||
cvar_t sv_demoSuffix = SCVAR("sv_demoSuffix", "");
|
||||
|
@ -1071,6 +1482,21 @@ mvddest_t *SV_InitStream(int socket)
|
|||
return dst;
|
||||
}
|
||||
|
||||
void SV_MVD_InitPendingStream(int socket, char *ip)
|
||||
{
|
||||
mvdpendingdest_t *dst;
|
||||
int i;
|
||||
dst = Z_Malloc(sizeof(mvdpendingdest_t));
|
||||
dst->socket = socket;
|
||||
|
||||
Q_strncpyz(dst->challenge, ip, sizeof(dst->challenge));
|
||||
for (i = strlen(dst->challenge); i < sizeof(dst->challenge)-1; i++)
|
||||
dst->challenge[i] = rand()%(127-33) + 33; //generate a random challenge
|
||||
|
||||
dst->nextdest = demo.pendingdest;
|
||||
demo.pendingdest = dst;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_Stop
|
||||
|
@ -1739,37 +2165,6 @@ void SV_MVDEasyRecord_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
// -> scream
|
||||
/* if (c == 2)
|
||||
Q_strncpyz (name, Cmd_Argv(1), sizeof(name));
|
||||
|
||||
else {
|
||||
// guess game type and write demo name
|
||||
i = Dem_CountPlayers();
|
||||
if (teamplay.value && i > 2)
|
||||
{
|
||||
// Teamplay
|
||||
snprintf (name, sizeof(name), "team_%s_vs_%s_%s",
|
||||
Dem_Team(1),
|
||||
Dem_Team(2),
|
||||
sv.name);
|
||||
} else {
|
||||
if (i == 2) {
|
||||
// Duel
|
||||
snprintf (name, sizeof(name), "duel_%s_vs_%s_%s",
|
||||
Dem_PlayerName(1),
|
||||
Dem_PlayerName(2),
|
||||
sv.name);
|
||||
} else {
|
||||
// FFA
|
||||
snprintf (name, sizeof(name), "ffa_%s(%d)",
|
||||
sv.name,
|
||||
i);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
if (c == 2)
|
||||
Q_strncpyz (name, Cmd_Argv(1), sizeof(name));
|
||||
else
|
||||
|
@ -1881,22 +2276,31 @@ void SV_MVDStream_Poll(void)
|
|||
int count;
|
||||
qboolean wanted;
|
||||
mvddest_t *dest;
|
||||
char *ip;
|
||||
|
||||
if (!sv.state || !mvd_streamport.value)
|
||||
if (!sv.state || !qtv_streamport.value)
|
||||
wanted = false;
|
||||
else if (listenport && (int)mvd_streamport.value != listenport) //easy way to switch... disable for a frame. :)
|
||||
else if (listenport && (int)qtv_streamport.value != listenport) //easy way to switch... disable for a frame. :)
|
||||
{
|
||||
listenport = mvd_streamport.value;
|
||||
listenport = qtv_streamport.value;
|
||||
wanted = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
listenport = mvd_streamport.value;
|
||||
listenport = qtv_streamport.value;
|
||||
wanted = true;
|
||||
}
|
||||
|
||||
if (wanted && listensocket==INVALID_SOCKET)
|
||||
{
|
||||
listensocket = MVD_StreamStartListening(listenport);
|
||||
if (listensocket==INVALID_SOCKET && qtv_streamport.modified)
|
||||
{
|
||||
Con_Printf("Cannot open TCP port %i for QTV\n", listenport);
|
||||
qtv_streamport.modified = false;
|
||||
}
|
||||
|
||||
}
|
||||
else if (!wanted && listensocket!=INVALID_SOCKET)
|
||||
{
|
||||
closesocket(listensocket);
|
||||
|
@ -1912,7 +2316,7 @@ void SV_MVDStream_Poll(void)
|
|||
if (client == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
if (mvd_maxstreams.value > 0)
|
||||
if (qtv_maxstreams.value > 0)
|
||||
{
|
||||
count = 0;
|
||||
for (dest = demo.dest; dest; dest = dest->nextdest)
|
||||
|
@ -1923,28 +2327,23 @@ void SV_MVDStream_Poll(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (count > mvd_maxstreams.value)
|
||||
if (count > qtv_maxstreams.value)
|
||||
{ //sorry
|
||||
char *goawaymessage = "This server enforces a limit on the number of proxies connected at any one time. Please try again later\n";
|
||||
char packetheader[6];
|
||||
packetheader[0] = 1;
|
||||
packetheader[1] = dem_all;
|
||||
packetheader[2] = strlen(goawaymessage)+1;
|
||||
packetheader[3] = 0;
|
||||
packetheader[4] = 0;
|
||||
packetheader[5] = 0;
|
||||
char *goawaymessage = "QTVSV 1\nERROR: This server enforces a limit on the number of proxies connected at any one time. Please try again later\n\n";
|
||||
|
||||
send(client, packetheader, sizeof(packetheader), 0);
|
||||
send(client, goawaymessage, strlen(goawaymessage)+1, 0);
|
||||
send(client, goawaymessage, strlen(goawaymessage), 0);
|
||||
closesocket(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SockadrToNetadr(&addr, &na);
|
||||
Con_Printf("MVD streaming client connected from %s\n", NET_AdrToString(na));
|
||||
ip = NET_AdrToString(na);
|
||||
Con_Printf("MVD streaming client attempting to connect from %s\n", ip);
|
||||
|
||||
SV_MVD_Record (SV_InitStream(client));
|
||||
SV_MVD_InitPendingStream(client, ip);
|
||||
|
||||
// SV_MVD_Record (SV_InitStream(client));
|
||||
}
|
||||
|
||||
void SV_MVDList_f (void)
|
||||
|
@ -2357,8 +2756,9 @@ void SV_MVDInit(void)
|
|||
Cmd_AddCommand ("rmdemo", SV_MVDRemove_f);
|
||||
Cmd_AddCommand ("rmdemonum", SV_MVDRemoveNum_f);
|
||||
|
||||
Cvar_Register(&mvd_streamport, "MVD Streaming");
|
||||
Cvar_Register(&mvd_maxstreams, "MVD Streaming");
|
||||
Cvar_Register(&qtv_streamport, "MVD Streaming");
|
||||
Cvar_Register(&qtv_maxstreams, "MVD Streaming");
|
||||
Cvar_Register(&qtv_password, "MVD Streaming");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -759,6 +759,9 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove)
|
|||
block = SV_TestEntityPosition (check);
|
||||
if (!block)
|
||||
{
|
||||
//if leaving it where it was, allow it to drop to the floor again (useful for plats that move downward)
|
||||
check->v->flags = (int)check->v->flags & ~FL_ONGROUND;
|
||||
|
||||
num_moved--;
|
||||
continue;
|
||||
}
|
||||
|
@ -1914,6 +1917,7 @@ qboolean SV_Physics (void)
|
|||
old_time = sv.time;
|
||||
host_frametime = 0;
|
||||
}
|
||||
if (svs.gametype != GT_QUAKE3)
|
||||
if (host_frametime < sv_maxtic.value && realtime)
|
||||
{
|
||||
// sv.time+=host_frametime;
|
||||
|
|
|
@ -1914,7 +1914,7 @@ void SV_SendClientMessages (void)
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
void DemoWriteQTVTimePad(int msecs);
|
||||
#define Max(a, b) ((a>b)?a:b)
|
||||
void SV_SendMVDMessage(void)
|
||||
{
|
||||
|
@ -1929,6 +1929,8 @@ void SV_SendMVDMessage(void)
|
|||
extern cvar_t sv_demoPings;
|
||||
// extern cvar_t sv_demoMaxSize;
|
||||
|
||||
SV_MVD_RunPendingConnections();
|
||||
|
||||
if (!sv.mvdrecording)
|
||||
return;
|
||||
|
||||
|
@ -1959,8 +1961,12 @@ void SV_SendMVDMessage(void)
|
|||
cls |= 1 << i;
|
||||
}
|
||||
|
||||
if (!cls) {
|
||||
if (!cls)
|
||||
{
|
||||
SZ_Clear (&demo.datagram);
|
||||
DemoWriteQTVTimePad((int)((sv.time - demo.time)*1000));
|
||||
DestFlush(false);
|
||||
demo.time = sv.time;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ double Sys_DoubleTime (void)
|
|||
static int starttime;
|
||||
|
||||
_ftime( &tstruct );
|
||||
|
||||
|
||||
if (!starttime)
|
||||
starttime = tstruct.time;
|
||||
t = (tstruct.time-starttime) + tstruct.millitm*0.001;
|
||||
|
|
|
@ -107,6 +107,60 @@ host_client and sv_player will be valid.
|
|||
============================================================
|
||||
*/
|
||||
|
||||
qboolean SV_CheakRealIP(client_t *client, qboolean force)
|
||||
{
|
||||
//returns true if they have a real ip
|
||||
cvar_t *sv_getrealip;
|
||||
char *serverip;
|
||||
char *msg;
|
||||
|
||||
sv_getrealip = Cvar_Get("sv_getrealip", "0", 0, "Experimental cvars");
|
||||
|
||||
if (!sv_getrealip || !sv_getrealip->value)
|
||||
return true;
|
||||
|
||||
if (client->netchan.remote_address.type == NA_LOOPBACK)
|
||||
return true; //the loopback client doesn't have to pass realip checks
|
||||
|
||||
if (client->realip_status == 3)
|
||||
return true; //we know that the ip is authentic
|
||||
if (client->realip_status == 2)
|
||||
{
|
||||
ClientReliableWrite_Begin(client, svc_print, 256);
|
||||
ClientReliableWrite_Byte(client, svc_print);
|
||||
ClientReliableWrite_Byte(client, PRINT_HIGH);
|
||||
ClientReliableWrite_String(client, "Couldn't verify your real ip\n");
|
||||
return true; //client doesn't support certainty.
|
||||
}
|
||||
if (client->realip_status == -1)
|
||||
return true; //can't get a better answer
|
||||
|
||||
if (realtime - host_client->connection_started > 10)
|
||||
{
|
||||
client->realip_status = -1;
|
||||
ClientReliableWrite_Begin(client, svc_print, 256);
|
||||
ClientReliableWrite_Byte(client, svc_print);
|
||||
ClientReliableWrite_Byte(client, PRINT_HIGH);
|
||||
ClientReliableWrite_String(client, "Couldn't determine your real ip\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (client->realip_status == 1)
|
||||
{
|
||||
msg = va("\xff\xff\xff\xff%c %i", A2A_PING, client->realip_ping);
|
||||
NET_SendPacket(NS_SERVER, strlen(msg), msg, client->realip);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverip = NET_AdrToString (net_local_sv_ipadr);
|
||||
|
||||
ClientReliableWrite_Byte(client, svc_stufftext);
|
||||
ClientReliableWrite_String(client, va("packet %s \"realip %i %i\"\n", serverip, client-svs.clients, client->realip_num));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_New_f
|
||||
|
@ -125,6 +179,8 @@ void SV_New_f (void)
|
|||
if (host_client->state == cs_spawned)
|
||||
return;
|
||||
|
||||
SV_CheakRealIP(host_client, false);
|
||||
|
||||
/* splitt delay
|
||||
host_client->state = cs_connected;
|
||||
host_client->connection_started = realtime;
|
||||
|
@ -1236,6 +1292,16 @@ void SV_Begin_f (void)
|
|||
int i;
|
||||
qboolean sendangles=false;
|
||||
|
||||
if (!SV_CheakRealIP(host_client, true))
|
||||
{
|
||||
if (host_client->protocol == SCP_QUAKE2)
|
||||
ClientReliableWrite_Begin (host_client, svcq2_stufftext, 13+strlen(Cmd_Args()));
|
||||
else
|
||||
ClientReliableWrite_Begin (host_client, svc_stufftext, 13+strlen(Cmd_Args()));
|
||||
ClientReliableWrite_String (host_client, va("cmd begin %s\n", Cmd_Args()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (host_client->state == cs_spawned)
|
||||
return; // don't begin again
|
||||
|
||||
|
|
|
@ -43,8 +43,155 @@ int mod_numknown;
|
|||
texture_t r_notexture_mip_real;
|
||||
texture_t *r_notexture_mip = &r_notexture_mip_real;
|
||||
|
||||
cvar_t sv_nogetlight = SCVAR("sv_nogetlight", "0");
|
||||
|
||||
unsigned *model_checksum;
|
||||
|
||||
|
||||
int SVQ1_RecursiveLightPoint3C (model_t *model, mnode_t *node, vec3_t start, vec3_t end)
|
||||
{
|
||||
int r;
|
||||
float front, back, frac;
|
||||
int side;
|
||||
mplane_t *plane;
|
||||
vec3_t mid;
|
||||
msurface_t *surf;
|
||||
int s, t, ds, dt;
|
||||
int i;
|
||||
mtexinfo_t *tex;
|
||||
qbyte *lightmap;
|
||||
unsigned scale;
|
||||
int maps;
|
||||
|
||||
|
||||
if (model->fromgame == fg_quake2)
|
||||
{
|
||||
if (node->contents != -1)
|
||||
return -1; // solid
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node->contents < 0)
|
||||
return -1; // didn't hit anything
|
||||
}
|
||||
|
||||
// calculate mid point
|
||||
|
||||
// FIXME: optimize for axial
|
||||
plane = node->plane;
|
||||
front = DotProduct (start, plane->normal) - plane->dist;
|
||||
back = DotProduct (end, plane->normal) - plane->dist;
|
||||
side = front < 0;
|
||||
|
||||
if ( (back < 0) == side)
|
||||
return SVQ1_RecursiveLightPoint3C (model, node->children[side], start, end);
|
||||
|
||||
frac = front / (front-back);
|
||||
mid[0] = start[0] + (end[0] - start[0])*frac;
|
||||
mid[1] = start[1] + (end[1] - start[1])*frac;
|
||||
mid[2] = start[2] + (end[2] - start[2])*frac;
|
||||
|
||||
// go down front side
|
||||
r = SVQ1_RecursiveLightPoint3C (model, node->children[side], start, mid);
|
||||
if (r >= 0)
|
||||
return r; // hit something
|
||||
|
||||
if ( (back < 0) == side )
|
||||
return -1; // didn't hit anuthing
|
||||
|
||||
// check for impact on this node
|
||||
|
||||
surf = model->surfaces + node->firstsurface;
|
||||
for (i=0 ; i<node->numsurfaces ; i++, surf++)
|
||||
{
|
||||
if (surf->flags & SURF_DRAWTILED)
|
||||
continue; // no lightmaps
|
||||
|
||||
tex = surf->texinfo;
|
||||
|
||||
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
|
||||
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
|
||||
|
||||
if (s < surf->texturemins[0] ||
|
||||
t < surf->texturemins[1])
|
||||
continue;
|
||||
|
||||
ds = s - surf->texturemins[0];
|
||||
dt = t - surf->texturemins[1];
|
||||
|
||||
if ( ds > surf->extents[0] || dt > surf->extents[1] )
|
||||
continue;
|
||||
|
||||
if (!surf->samples)
|
||||
return 0;
|
||||
|
||||
ds >>= 4;
|
||||
dt >>= 4;
|
||||
|
||||
lightmap = surf->samples;
|
||||
r = 0;
|
||||
if (lightmap)
|
||||
{
|
||||
|
||||
lightmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3;
|
||||
|
||||
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
|
||||
maps++)
|
||||
{
|
||||
scale = sv.strings.lightstyles[surf->styles[maps]][0];
|
||||
r += (lightmap[0]+lightmap[1]+lightmap[2])/3 * scale;
|
||||
lightmap += ((surf->extents[0]>>4)+1) *
|
||||
((surf->extents[1]>>4)+1)*3;
|
||||
}
|
||||
|
||||
r >>= 8;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return SVQ1_RecursiveLightPoint3C (model, node->children[!side], mid, end);
|
||||
}
|
||||
|
||||
void SVQ1_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
|
||||
{
|
||||
vec3_t end;
|
||||
float r;
|
||||
|
||||
res_dir[0] = 0; //software doesn't load luxes
|
||||
res_dir[1] = 1;
|
||||
res_dir[2] = 1;
|
||||
|
||||
end[0] = point[0];
|
||||
end[1] = point[1];
|
||||
end[2] = point[2] - 2048;
|
||||
|
||||
r = SVQ1_RecursiveLightPoint3C (model, model->nodes, point, end);
|
||||
if (r < 0)
|
||||
{
|
||||
res_diffuse[0] = 0;
|
||||
res_diffuse[1] = 0;
|
||||
res_diffuse[2] = 0;
|
||||
|
||||
res_ambient[0] = 0;
|
||||
res_ambient[1] = 0;
|
||||
res_ambient[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res_diffuse[0] = r;
|
||||
res_diffuse[1] = r;
|
||||
res_diffuse[2] = r;
|
||||
|
||||
res_ambient[0] = r;
|
||||
res_ambient[1] = r;
|
||||
res_ambient[2] = r;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Mod_Init
|
||||
|
@ -53,6 +200,7 @@ Mod_Init
|
|||
void Mod_Init (void)
|
||||
{
|
||||
memset (mod_novis, 0xff, sizeof(mod_novis));
|
||||
Cvar_Register(&sv_nogetlight, "Memory preservation");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -514,15 +662,38 @@ void Mod_LoadTextures (lump_t *l)
|
|||
Mod_LoadLighting
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadLighting (lump_t *l)
|
||||
qboolean Mod_LoadLighting (lump_t *l)
|
||||
{
|
||||
int i;
|
||||
char *in;
|
||||
char *out;
|
||||
if (!l->filelen)
|
||||
{
|
||||
loadmodel->lightdata = NULL;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
|
||||
memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
|
||||
|
||||
if (loadmodel->fromgame == fg_halflife)
|
||||
{
|
||||
loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
|
||||
memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, loadname);
|
||||
|
||||
in = mod_base + l->fileofs;
|
||||
out = loadmodel->lightdata;
|
||||
|
||||
for (i = 0; i < l->filelen; i++)
|
||||
{
|
||||
*out++ = *in;
|
||||
*out++ = *in;
|
||||
*out++ = *in++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -566,7 +737,7 @@ void Mod_LoadEntities (lump_t *l)
|
|||
Mod_LoadVertexes
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadVertexes (lump_t *l)
|
||||
qboolean Mod_LoadVertexes (lump_t *l)
|
||||
{
|
||||
dvertex_t *in;
|
||||
mvertex_t *out;
|
||||
|
@ -574,7 +745,10 @@ void Mod_LoadVertexes (lump_t *l)
|
|||
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in))
|
||||
SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
{
|
||||
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
return false;
|
||||
}
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = Hunk_AllocName ( count*sizeof(*out), loadname);
|
||||
|
||||
|
@ -587,6 +761,7 @@ void Mod_LoadVertexes (lump_t *l)
|
|||
out->position[1] = LittleFloat (in->point[1]);
|
||||
out->position[2] = LittleFloat (in->point[2]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -690,7 +865,7 @@ qboolean Mod_LoadSubmodels (lump_t *l)
|
|||
Mod_LoadEdges
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadEdges (lump_t *l)
|
||||
qboolean Mod_LoadEdges (lump_t *l)
|
||||
{
|
||||
dedge_t *in;
|
||||
medge_t *out;
|
||||
|
@ -698,7 +873,10 @@ void Mod_LoadEdges (lump_t *l)
|
|||
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in))
|
||||
SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
{
|
||||
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
return false;
|
||||
}
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
|
||||
|
||||
|
@ -710,6 +888,7 @@ void Mod_LoadEdges (lump_t *l)
|
|||
out->v[0] = (unsigned short)LittleShort(in->v[0]);
|
||||
out->v[1] = (unsigned short)LittleShort(in->v[1]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -717,7 +896,7 @@ void Mod_LoadEdges (lump_t *l)
|
|||
Mod_LoadTexinfo
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadTexinfo (lump_t *l)
|
||||
qboolean Mod_LoadTexinfo (lump_t *l)
|
||||
{
|
||||
texinfo_t *in;
|
||||
mtexinfo_t *out;
|
||||
|
@ -727,7 +906,10 @@ void Mod_LoadTexinfo (lump_t *l)
|
|||
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in))
|
||||
SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
{
|
||||
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
return false;
|
||||
}
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = Hunk_AllocName ( count*sizeof(*out), loadname);
|
||||
|
||||
|
@ -774,6 +956,7 @@ void Mod_LoadTexinfo (lump_t *l)
|
|||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -837,7 +1020,7 @@ void CalcSurfaceExtents (msurface_t *s);
|
|||
Mod_LoadFaces
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadFaces (lump_t *l)
|
||||
qboolean Mod_LoadFaces (lump_t *l)
|
||||
{
|
||||
dface_t *in;
|
||||
msurface_t *out;
|
||||
|
@ -846,7 +1029,10 @@ void Mod_LoadFaces (lump_t *l)
|
|||
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in))
|
||||
SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
{
|
||||
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
return false;
|
||||
}
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = Hunk_AllocName ( count*sizeof(*out), loadname);
|
||||
|
||||
|
@ -877,8 +1063,10 @@ void Mod_LoadFaces (lump_t *l)
|
|||
i = LittleLong(in->lightofs);
|
||||
if (i == -1)
|
||||
out->samples = NULL;
|
||||
else
|
||||
else if (loadmodel->fromgame == fg_halflife)
|
||||
out->samples = loadmodel->lightdata + i;
|
||||
else
|
||||
out->samples = loadmodel->lightdata + i*3;
|
||||
|
||||
// set the drawing flags flag
|
||||
|
||||
|
@ -899,6 +1087,8 @@ void Mod_LoadFaces (lump_t *l)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1209,14 +1399,17 @@ void Mod_LoadMarksurfaces (lump_t *l)
|
|||
Mod_LoadSurfedges
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadSurfedges (lump_t *l)
|
||||
qboolean Mod_LoadSurfedges (lump_t *l)
|
||||
{
|
||||
int i, count;
|
||||
int *in, *out;
|
||||
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
if (l->filelen % sizeof(*in))
|
||||
SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
{
|
||||
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
|
||||
return false;
|
||||
}
|
||||
count = l->filelen / sizeof(*in);
|
||||
out = Hunk_AllocName ( count*sizeof(*out), loadname);
|
||||
|
||||
|
@ -1225,6 +1418,8 @@ void Mod_LoadSurfedges (lump_t *l)
|
|||
|
||||
for ( i=0 ; i<count ; i++)
|
||||
out[i] = LittleLong (in[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1315,7 +1510,8 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
|
|||
mod->checksum2 = 0;
|
||||
|
||||
// checksum all of the map, except for entities
|
||||
for (i = 0; i < HEADER_LUMPS; i++) {
|
||||
for (i = 0; i < HEADER_LUMPS; i++)
|
||||
{
|
||||
if (i == LUMP_ENTITIES)
|
||||
continue;
|
||||
chksum = Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
|
||||
|
@ -1328,15 +1524,21 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
|
|||
}
|
||||
|
||||
noerrors = true;
|
||||
// Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
|
||||
// Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
|
||||
// Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
|
||||
if (!sv_nogetlight.value)
|
||||
{
|
||||
noerrors = noerrors && Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
|
||||
noerrors = noerrors && Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
|
||||
noerrors = noerrors && Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
|
||||
///*/on server?*/ Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
|
||||
// Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
|
||||
noerrors = noerrors && Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
|
||||
}
|
||||
noerrors = noerrors && Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
|
||||
noerrors = noerrors && Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
|
||||
///*/on server?*/ Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
|
||||
// Mod_LoadFaces (&header->lumps[LUMP_FACES]);
|
||||
if (!sv_nogetlight.value)
|
||||
{
|
||||
noerrors = noerrors && Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
|
||||
noerrors = noerrors && Mod_LoadFaces (&header->lumps[LUMP_FACES]);
|
||||
}
|
||||
// Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
|
||||
if (noerrors)
|
||||
Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
|
||||
|
@ -1357,6 +1559,9 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
|
|||
|
||||
Q1BSP_SetModelFuncs(mod);
|
||||
|
||||
if (mod->surfaces && mod->lightdata)
|
||||
mod->funcs.LightPointValues = SVQ1_LightPointValues;
|
||||
|
||||
|
||||
mod->numframes = 2; // regular and alternate animation
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue