Rewritted entity parsing, so should work fine with .join now.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2451 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
a0c7a347df
commit
55f5344510
7 changed files with 449 additions and 105 deletions
|
@ -203,8 +203,16 @@ void Cluster_Run(cluster_t *cluster, qboolean dowait)
|
||||||
m = STDIN+1;
|
m = STDIN+1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timeout.tv_sec = 100/1000;
|
if (cluster->viewserver)
|
||||||
timeout.tv_usec = (100%1000)*1000;
|
{
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout.tv_sec = 100/1000;
|
||||||
|
timeout.tv_usec = (100%1000)*1000;
|
||||||
|
}
|
||||||
|
|
||||||
m = select(m, &socketset, NULL, NULL, &timeout);
|
m = select(m, &socketset, NULL, NULL, &timeout);
|
||||||
|
|
||||||
|
@ -363,11 +371,9 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
cluster_t cluster;
|
cluster_t cluster;
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#ifdef SIGPIPE
|
#ifdef SIGPIPE
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
|
@ -387,61 +393,6 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
Sys_Printf(&cluster, "QTV Build %i.\n", cluster.buildnumber);
|
Sys_Printf(&cluster, "QTV Build %i.\n", cluster.buildnumber);
|
||||||
|
|
||||||
if (argc >= 2 && (!strcmp(argv[1], "-view") || !strcmp(argv[1], "-play")))
|
|
||||||
{
|
|
||||||
#ifdef VIEWER
|
|
||||||
sv_t *sv;
|
|
||||||
sv_t *svtest;
|
|
||||||
char sourcename[256];
|
|
||||||
char *s;
|
|
||||||
printf("Please enter a QTV source\n");
|
|
||||||
printf("eg: file:test.mvd\n");
|
|
||||||
printf("eg: udp:localhost:27500\n");
|
|
||||||
printf("eg: tcp:localhost:27599\n");
|
|
||||||
fgets(sourcename, sizeof(sourcename), stdin);
|
|
||||||
for (s = sourcename + strlen(sourcename)-1; s>=sourcename; s--)
|
|
||||||
{
|
|
||||||
if (*s == '\r' || *s == '\n')
|
|
||||||
*s = '\0';
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sv = QTV_NewServerConnection(&cluster, sourcename, "", false, false, true);
|
|
||||||
if (!sv)
|
|
||||||
{
|
|
||||||
printf("Unable to connect\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!strcmp(argv[1], "-play"))
|
|
||||||
sv->proxyplayer = true;
|
|
||||||
DemoViewer_Init();
|
|
||||||
while (!cluster.wanttoexit)
|
|
||||||
{
|
|
||||||
Cluster_Run(&cluster, false);
|
|
||||||
|
|
||||||
for (svtest = cluster.servers; svtest; svtest = svtest->next)
|
|
||||||
{ //not the cleanest way to do this, of course
|
|
||||||
if (svtest == sv)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (svtest)
|
|
||||||
DemoViewer_Update(svtest);
|
|
||||||
else
|
|
||||||
cluster.wanttoexit = true;
|
|
||||||
}
|
|
||||||
DemoViewer_Shutdown();
|
|
||||||
while(cluster.viewers)
|
|
||||||
QW_FreeViewer(&cluster, cluster.viewers);
|
|
||||||
while(cluster.servers)
|
|
||||||
QTV_Shutdown(cluster.servers);
|
|
||||||
#else
|
|
||||||
Sys_Printf(&cluster, "Demo viewer is not enabled in this build. Sorry.\n");
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DoCommandLine(&cluster, argc, argv);
|
DoCommandLine(&cluster, argc, argv);
|
||||||
|
|
||||||
if (!cluster.numservers)
|
if (!cluster.numservers)
|
||||||
|
@ -472,7 +423,12 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!cluster.wanttoexit)
|
while (!cluster.wanttoexit)
|
||||||
|
{
|
||||||
Cluster_Run(&cluster, true);
|
Cluster_Run(&cluster, true);
|
||||||
|
#ifdef VIEWER
|
||||||
|
DemoViewer_Update(cluster.viewserver);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
249
fteqtv/parse.c
249
fteqtv/parse.c
|
@ -292,7 +292,7 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
||||||
v->thinksitsconnected = false;
|
v->thinksitsconnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tv->maxents = 0; //clear these
|
// tv->maxents = 0; //clear these
|
||||||
tv->spawnstatic_count = 0;
|
tv->spawnstatic_count = 0;
|
||||||
memset(tv->modellist, 0, sizeof(tv->modellist));
|
memset(tv->modellist, 0, sizeof(tv->modellist));
|
||||||
memset(tv->soundlist, 0, sizeof(tv->soundlist));
|
memset(tv->soundlist, 0, sizeof(tv->soundlist));
|
||||||
|
@ -737,18 +737,122 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
||||||
tv->players[num].current.origin[2]/8.0f, 32);
|
tv->players[num].current.origin[2]/8.0f, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FlushPacketEntities(sv_t *tv)
|
static int readentitynum(netmsg_t *m, unsigned int *retflags)
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MAX_ENTITIES; i++)
|
|
||||||
tv->entity[i].current.modelindex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ParsePacketEntities(sv_t *tv, netmsg_t *m)
|
|
||||||
{
|
{
|
||||||
int entnum;
|
int entnum;
|
||||||
int flags;
|
unsigned int flags;
|
||||||
qboolean forcerelink;
|
unsigned short moreflags = 0;
|
||||||
|
flags = ReadShort(m);
|
||||||
|
if (!flags)
|
||||||
|
{
|
||||||
|
*retflags = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entnum = flags&511;
|
||||||
|
flags &= ~511;
|
||||||
|
|
||||||
|
if (flags & U_MOREBITS)
|
||||||
|
{
|
||||||
|
flags |= ReadByte(m);
|
||||||
|
|
||||||
|
/* if (flags & U_EVENMORE)
|
||||||
|
flags |= ReadByte(m)<<16;
|
||||||
|
if (flags & U_YETMORE)
|
||||||
|
flags |= ReadByte(m)<<24;
|
||||||
|
*/ }
|
||||||
|
|
||||||
|
/* if (flags & U_ENTITYDBL)
|
||||||
|
entnum += 512;
|
||||||
|
if (flags & U_ENTITYDBL2)
|
||||||
|
entnum += 1024;
|
||||||
|
*/
|
||||||
|
*retflags = flags;
|
||||||
|
|
||||||
|
return entnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ParseEntityDelta(sv_t *tv, netmsg_t *m, entity_state_t *old, entity_state_t *new, unsigned int flags, entity_t *ent, qboolean forcerelink)
|
||||||
|
{
|
||||||
|
memcpy(new, old, sizeof(entity_state_t));
|
||||||
|
|
||||||
|
if (flags & U_MODEL)
|
||||||
|
new->modelindex = ReadByte(m);
|
||||||
|
if (flags & U_FRAME)
|
||||||
|
new->frame = ReadByte(m);
|
||||||
|
if (flags & U_COLORMAP)
|
||||||
|
new->colormap = ReadByte(m);
|
||||||
|
if (flags & U_SKIN)
|
||||||
|
new->skinnum = ReadByte(m);
|
||||||
|
if (flags & U_EFFECTS)
|
||||||
|
new->effects = ReadByte(m);
|
||||||
|
|
||||||
|
if (flags & U_ORIGIN1)
|
||||||
|
new->origin[0] = ReadShort(m);
|
||||||
|
if (flags & U_ANGLE1)
|
||||||
|
new->angles[0] = ReadByte(m);
|
||||||
|
if (flags & U_ORIGIN2)
|
||||||
|
new->origin[1] = ReadShort(m);
|
||||||
|
if (flags & U_ANGLE2)
|
||||||
|
new->angles[1] = ReadByte(m);
|
||||||
|
if (flags & U_ORIGIN3)
|
||||||
|
new->origin[2] = ReadShort(m);
|
||||||
|
if (flags & U_ANGLE3)
|
||||||
|
new->angles[2] = ReadByte(m);
|
||||||
|
|
||||||
|
|
||||||
|
if (forcerelink || (flags & (U_ORIGIN1|U_ORIGIN2|U_ORIGIN3|U_MODEL)))
|
||||||
|
{
|
||||||
|
ent->leafcount =
|
||||||
|
BSP_SphereLeafNums(tv->bsp, MAX_ENTITY_LEAFS, ent->leafs,
|
||||||
|
new->origin[0]/8.0f,
|
||||||
|
new->origin[1]/8.0f,
|
||||||
|
new->origin[2]/8.0f, 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ExpandFrame(unsigned int newmax, frame_t *frame)
|
||||||
|
{
|
||||||
|
entity_state_t *newents;
|
||||||
|
unsigned short *newnums;
|
||||||
|
|
||||||
|
if (newmax < frame->maxents)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
newmax += 16;
|
||||||
|
|
||||||
|
newents = malloc(sizeof(*newents) * newmax);
|
||||||
|
if (!newents)
|
||||||
|
return false;
|
||||||
|
newnums = malloc(sizeof(*newnums) * newmax);
|
||||||
|
if (!newnums)
|
||||||
|
{
|
||||||
|
free(newents);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(newents, frame->ents, sizeof(*newents) * frame->maxents);
|
||||||
|
memcpy(newnums, frame->entnums, sizeof(*newnums) * frame->maxents);
|
||||||
|
|
||||||
|
if (frame->ents)
|
||||||
|
free(frame->ents);
|
||||||
|
if (frame->entnums)
|
||||||
|
free(frame->entnums);
|
||||||
|
|
||||||
|
frame->ents = newents;
|
||||||
|
frame->entnums = newnums;
|
||||||
|
frame->maxents = newmax;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ParsePacketEntities(sv_t *tv, netmsg_t *m, int deltaframe)
|
||||||
|
{
|
||||||
|
frame_t *newframe;
|
||||||
|
frame_t *oldframe;
|
||||||
|
int oldcount;
|
||||||
|
int newnum, oldnum;
|
||||||
|
int newindex, oldindex;
|
||||||
|
unsigned int flags;
|
||||||
|
|
||||||
viewer_t *v;
|
viewer_t *v;
|
||||||
|
|
||||||
|
@ -763,6 +867,120 @@ static void ParsePacketEntities(sv_t *tv, netmsg_t *m)
|
||||||
v->chokeme = false;
|
v->chokeme = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (deltaframe != -1)
|
||||||
|
deltaframe &= (ENTITY_FRAMES-1);
|
||||||
|
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
|
{
|
||||||
|
newframe = &tv->frame[tv->netchan.incoming_sequence & (ENTITY_FRAMES-1)];
|
||||||
|
|
||||||
|
if (newframe->oldframe != deltaframe)
|
||||||
|
Sys_Printf(tv->cluster, "Mismatching delta frames\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deltaframe = tv->netchan.incoming_sequence & (ENTITY_FRAMES-1);
|
||||||
|
tv->netchan.incoming_sequence++;
|
||||||
|
newframe = &tv->frame[tv->netchan.incoming_sequence & (ENTITY_FRAMES-1)];
|
||||||
|
}
|
||||||
|
if (deltaframe != -1)
|
||||||
|
{
|
||||||
|
oldframe = &tv->frame[deltaframe];
|
||||||
|
oldcount = oldframe->numents;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldframe = NULL;
|
||||||
|
oldcount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldindex = 0;
|
||||||
|
newindex = 0;
|
||||||
|
|
||||||
|
//printf("frame\n");
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
newnum = readentitynum(m, &flags);
|
||||||
|
if (!newnum)
|
||||||
|
{
|
||||||
|
//end of packet
|
||||||
|
//any remaining old ents need to be copied to the new frame
|
||||||
|
while (oldindex < oldcount)
|
||||||
|
{
|
||||||
|
//printf("Propogate (spare)\n");
|
||||||
|
if (!ExpandFrame(newindex, newframe))
|
||||||
|
break;
|
||||||
|
|
||||||
|
memcpy(&newframe->ents[newindex], &oldframe->ents[oldindex], sizeof(entity_state_t));
|
||||||
|
newframe->entnums[newindex] = oldframe->entnums[oldindex];
|
||||||
|
newindex++;
|
||||||
|
oldindex++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldindex >= oldcount)
|
||||||
|
oldnum = 0xffff;
|
||||||
|
else
|
||||||
|
oldnum = oldframe->entnums[oldindex];
|
||||||
|
while(newnum > oldnum)
|
||||||
|
{
|
||||||
|
//printf("Propogate (unchanged)\n");
|
||||||
|
if (!ExpandFrame(newindex, newframe))
|
||||||
|
break;
|
||||||
|
|
||||||
|
memcpy(&newframe->ents[newindex], &oldframe->ents[oldindex], sizeof(entity_state_t));
|
||||||
|
newframe->entnums[newindex] = oldframe->entnums[oldindex];
|
||||||
|
newindex++;
|
||||||
|
oldindex++;
|
||||||
|
|
||||||
|
if (oldindex >= oldcount)
|
||||||
|
oldnum = 0xffff;
|
||||||
|
else
|
||||||
|
oldnum = oldframe->entnums[oldindex];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newnum < oldnum)
|
||||||
|
{ //this ent wasn't in the last packet
|
||||||
|
//printf("add\n");
|
||||||
|
if (flags & U_REMOVE)
|
||||||
|
{ //remove this ent... just don't copy it across.
|
||||||
|
//printf("add\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ExpandFrame(newindex, newframe))
|
||||||
|
break;
|
||||||
|
ParseEntityDelta(tv, m, &tv->entity[newnum].baseline, &newframe->ents[newindex], flags, &tv->entity[newnum], true);
|
||||||
|
newframe->entnums[newindex] = newnum;
|
||||||
|
newindex++;
|
||||||
|
}
|
||||||
|
else if (newnum == oldnum)
|
||||||
|
{
|
||||||
|
if (flags & U_REMOVE)
|
||||||
|
{ //remove this ent... just don't copy it across.
|
||||||
|
//printf("add\n");
|
||||||
|
oldindex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//printf("Propogate (changed)\n");
|
||||||
|
if (!ExpandFrame(newindex, newframe))
|
||||||
|
break;
|
||||||
|
ParseEntityDelta(tv, m, &oldframe->ents[oldindex], &newframe->ents[newindex], flags, &tv->entity[newnum], false);
|
||||||
|
newframe->entnums[newindex] = newnum;
|
||||||
|
newindex++;
|
||||||
|
oldindex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
newframe->numents = newindex;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
//luckilly, only updated entities are here, so that keeps cpu time down a bit.
|
//luckilly, only updated entities are here, so that keeps cpu time down a bit.
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -825,6 +1043,7 @@ static void ParsePacketEntities(sv_t *tv, netmsg_t *m)
|
||||||
tv->entity[entnum].current.origin[1]/8.0f,
|
tv->entity[entnum].current.origin[1]/8.0f,
|
||||||
tv->entity[entnum].current.origin[2]/8.0f, 32);
|
tv->entity[entnum].current.origin[2]/8.0f, 32);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParseUpdatePing(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
static void ParseUpdatePing(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
|
@ -1524,12 +1743,11 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case svc_packetentities:
|
case svc_packetentities:
|
||||||
FlushPacketEntities(tv);
|
// FlushPacketEntities(tv);
|
||||||
ParsePacketEntities(tv, &buf);
|
ParsePacketEntities(tv, &buf, -1);
|
||||||
break;
|
break;
|
||||||
case svc_deltapacketentities:
|
case svc_deltapacketentities:
|
||||||
ReadByte(&buf);
|
ParsePacketEntities(tv, &buf, ReadByte(&buf));
|
||||||
ParsePacketEntities(tv, &buf);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
||||||
|
@ -1561,3 +1779,4 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
fteqtv/qtv.h
16
fteqtv/qtv.h
|
@ -474,9 +474,9 @@ typedef struct bsp_s bsp_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
entity_state_t baseline;
|
entity_state_t baseline;
|
||||||
entity_state_t current;
|
// entity_state_t current;
|
||||||
entity_state_t old;
|
// entity_state_t old;
|
||||||
unsigned int updatetime; //to stop lerping when it's an old entity (bodies, stationary grenades, ...)
|
// unsigned int updatetime; //to stop lerping when it's an old entity (bodies, stationary grenades, ...)
|
||||||
|
|
||||||
int leafcount;
|
int leafcount;
|
||||||
unsigned short leafs[MAX_ENTITY_LEAFS];
|
unsigned short leafs[MAX_ENTITY_LEAFS];
|
||||||
|
@ -484,9 +484,11 @@ typedef struct {
|
||||||
|
|
||||||
#define MAX_ENTITY_FRAMES 64
|
#define MAX_ENTITY_FRAMES 64
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
int oldframe;
|
||||||
int numents;
|
int numents;
|
||||||
int maxents;
|
int maxents;
|
||||||
entity_state_t *ents; //dynamically allocated
|
entity_state_t *ents; //dynamically allocated
|
||||||
|
unsigned short *entnums; //dynamically allocated
|
||||||
} frame_t;
|
} frame_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -515,7 +517,7 @@ struct sv_s {
|
||||||
int cdtrack;
|
int cdtrack;
|
||||||
entity_t entity[MAX_ENTITIES];
|
entity_t entity[MAX_ENTITIES];
|
||||||
frame_t frame[MAX_ENTITY_FRAMES];
|
frame_t frame[MAX_ENTITY_FRAMES];
|
||||||
int maxents;
|
// int maxents;
|
||||||
staticsound_t staticsound[MAX_STATICSOUNDS];
|
staticsound_t staticsound[MAX_STATICSOUNDS];
|
||||||
int staticsound_count;
|
int staticsound_count;
|
||||||
entity_state_t spawnstatic[MAX_STATICENTITIES];
|
entity_state_t spawnstatic[MAX_STATICENTITIES];
|
||||||
|
@ -619,6 +621,8 @@ struct cluster_s {
|
||||||
int nextstreamid;
|
int nextstreamid;
|
||||||
int nextuserid;
|
int nextuserid;
|
||||||
|
|
||||||
|
sv_t *viewserver;
|
||||||
|
|
||||||
//options
|
//options
|
||||||
int qwlistenportnum;
|
int qwlistenportnum;
|
||||||
int tcplistenportnum;
|
int tcplistenportnum;
|
||||||
|
@ -908,9 +912,7 @@ unsigned char *FS_ReadFile(char *gamedir, char *filename, unsigned int *size);
|
||||||
|
|
||||||
void ChooseFavoriteTrack(sv_t *tv);
|
void ChooseFavoriteTrack(sv_t *tv);
|
||||||
|
|
||||||
void DemoViewer_Init(void);
|
|
||||||
void DemoViewer_Update(sv_t *svtest);
|
void DemoViewer_Update(sv_t *svtest);
|
||||||
void DemoViewer_Shutdown(void);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -525,8 +525,32 @@ SOURCE=.\source.c
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\viewer\common.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\viewer\cvar.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\viewer\d3drend\d3drenderer.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\viewer\glrenderer.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\viewer\maths.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\qtv.h
|
SOURCE=.\qtv.h
|
||||||
# End Source File
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\viewer\renderer.h
|
||||||
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "Resource Files"
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
|
124
fteqtv/qw.c
124
fteqtv/qw.c
|
@ -1198,12 +1198,14 @@ void SV_EmitPacketEntities (const sv_t *qtv, const viewer_t *v, const packet_ent
|
||||||
|
|
||||||
void Prox_SendInitialEnts(sv_t *qtv, oproxy_t *prox, netmsg_t *msg)
|
void Prox_SendInitialEnts(sv_t *qtv, oproxy_t *prox, netmsg_t *msg)
|
||||||
{
|
{
|
||||||
int i;
|
frame_t *frame;
|
||||||
|
int i, entnum;
|
||||||
WriteByte(msg, svc_packetentities);
|
WriteByte(msg, svc_packetentities);
|
||||||
for (i = 0; i < qtv->maxents; i++)
|
frame = &qtv->frame[qtv->netchan.incoming_sequence & (ENTITY_FRAMES-1)];
|
||||||
|
for (i = 0; i < frame->numents; i++)
|
||||||
{
|
{
|
||||||
if (qtv->entity[i].current.modelindex)
|
entnum = frame->entnums[i];
|
||||||
SV_WriteDelta(i, &nullentstate, &qtv->entity[i].current, msg, true);
|
SV_WriteDelta(i, &qtv->entity[entnum].baseline, &frame->ents[i], msg, true);
|
||||||
}
|
}
|
||||||
WriteShort(msg, 0);
|
WriteShort(msg, 0);
|
||||||
}
|
}
|
||||||
|
@ -1609,7 +1611,7 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
||||||
if (bits & UNQ_ANGLE3)
|
if (bits & UNQ_ANGLE3)
|
||||||
WriteByte(msg, pl->current.angles[2]>>8);
|
WriteByte(msg, pl->current.angles[2]>>8);
|
||||||
}
|
}
|
||||||
for (e = 0; e < tv->maxents; e++)
|
/* for (e = 0; e < tv->maxents; e++)
|
||||||
{
|
{
|
||||||
ent = &tv->entity[e];
|
ent = &tv->entity[e];
|
||||||
if (!ent->current.modelindex)
|
if (!ent->current.modelindex)
|
||||||
|
@ -1618,6 +1620,9 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
||||||
if (ent->current.modelindex >= tv->numinlines && !BSP_Visible(tv->bsp, ent->leafcount, ent->leafs))
|
if (ent->current.modelindex >= tv->numinlines && !BSP_Visible(tv->bsp, ent->leafcount, ent->leafs))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (msg->cursize + 128 > msg->maxsize)
|
||||||
|
break;
|
||||||
|
|
||||||
// send an update
|
// send an update
|
||||||
bits = 0;
|
bits = 0;
|
||||||
|
|
||||||
|
@ -1710,6 +1715,7 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
||||||
if (bits & UNQ_ANGLE3)
|
if (bits & UNQ_ANGLE3)
|
||||||
WriteByte(msg, ent->current.angles[2]);
|
WriteByte(msg, ent->current.angles[2]);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1734,6 +1740,11 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
||||||
int track;
|
int track;
|
||||||
int runaway = 10;
|
int runaway = 10;
|
||||||
|
|
||||||
|
int snapdist = 128; //in quake units
|
||||||
|
|
||||||
|
snapdist = snapdist*8;
|
||||||
|
snapdist = snapdist*snapdist;
|
||||||
|
|
||||||
|
|
||||||
memset(&to, 0, sizeof(to));
|
memset(&to, 0, sizeof(to));
|
||||||
|
|
||||||
|
@ -1837,12 +1848,23 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
||||||
WriteByte(msg, i);
|
WriteByte(msg, i);
|
||||||
WriteShort(msg, flags);
|
WriteShort(msg, flags);
|
||||||
|
|
||||||
interp = (lerp)*tv->players[i].current.origin[0] + (1-lerp)*tv->players[i].old.origin[0];
|
if ((tv->players[i].current.origin[0] - tv->players[i].old.origin[0])*(tv->players[i].current.origin[0] - tv->players[i].old.origin[0]) > snapdist ||
|
||||||
WriteShort(msg, interp);
|
(tv->players[i].current.origin[1] - tv->players[i].old.origin[1])*(tv->players[i].current.origin[1] - tv->players[i].old.origin[1]) > snapdist ||
|
||||||
interp = (lerp)*tv->players[i].current.origin[1] + (1-lerp)*tv->players[i].old.origin[1];
|
(tv->players[i].current.origin[2] - tv->players[i].old.origin[2])*(tv->players[i].current.origin[2] - tv->players[i].old.origin[2]) > snapdist)
|
||||||
WriteShort(msg, interp);
|
{ //teleported (or respawned), so don't interpolate
|
||||||
interp = (lerp)*tv->players[i].current.origin[2] + (1-lerp)*tv->players[i].old.origin[2];
|
WriteShort(msg, tv->players[i].current.origin[0]);
|
||||||
WriteShort(msg, interp);
|
WriteShort(msg, tv->players[i].current.origin[1]);
|
||||||
|
WriteShort(msg, tv->players[i].current.origin[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //send interpolated angles
|
||||||
|
interp = (lerp)*tv->players[i].current.origin[0] + (1-lerp)*tv->players[i].old.origin[0];
|
||||||
|
WriteShort(msg, interp);
|
||||||
|
interp = (lerp)*tv->players[i].current.origin[1] + (1-lerp)*tv->players[i].old.origin[1];
|
||||||
|
WriteShort(msg, interp);
|
||||||
|
interp = (lerp)*tv->players[i].current.origin[2] + (1-lerp)*tv->players[i].old.origin[2];
|
||||||
|
WriteShort(msg, interp);
|
||||||
|
}
|
||||||
|
|
||||||
WriteByte(msg, tv->players[i].current.frame);
|
WriteByte(msg, tv->players[i].current.frame);
|
||||||
|
|
||||||
|
@ -1883,22 +1905,79 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
||||||
e = &v->frame[v->netchan.outgoing_sequence&(ENTITY_FRAMES-1)];
|
e = &v->frame[v->netchan.outgoing_sequence&(ENTITY_FRAMES-1)];
|
||||||
e->numents = 0;
|
e->numents = 0;
|
||||||
if (tv)
|
if (tv)
|
||||||
for (i = 0; i < tv->maxents; i++)
|
{
|
||||||
|
int oldindex = 0, newindex = 0;
|
||||||
|
entity_state_t *newstate;
|
||||||
|
int newnum, oldnum;
|
||||||
|
frame_t *frompacket, *topacket;
|
||||||
|
topacket = &tv->frame[tv->netchan.incoming_sequence&(ENTITY_FRAMES-1)];
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
{
|
{
|
||||||
if (!tv->entity[i].current.modelindex)
|
//qw protocols don't interpolate... yet
|
||||||
|
frompacket = topacket;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frompacket = &tv->frame[(tv->netchan.incoming_sequence-1)&(ENTITY_FRAMES-1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (newindex = 0; newindex < topacket->numents; newindex++)
|
||||||
|
{
|
||||||
|
//don't pvs cull bsp models
|
||||||
|
//pvs cull everything else
|
||||||
|
newstate = &topacket->ents[newindex];
|
||||||
|
newnum = topacket->entnums[newindex];
|
||||||
|
if (newstate->modelindex >= tv->numinlines && !BSP_Visible(tv->bsp, tv->entity[newnum].leafcount, tv->entity[newnum].leafs))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tv->entity[i].current.modelindex >= tv->numinlines && !BSP_Visible(tv->bsp, tv->entity[i].leafcount, tv->entity[i].leafs))
|
e->entnum[e->numents] = newnum;
|
||||||
continue;
|
memcpy(&e->ents[e->numents], newstate, sizeof(entity_state_t));
|
||||||
|
|
||||||
e->entnum[e->numents] = i;
|
if (frompacket != topacket) //optimisation for qw protocols
|
||||||
memcpy(&e->ents[e->numents], &tv->entity[i].current, sizeof(entity_state_t));
|
|
||||||
|
|
||||||
if (tv->entity[i].updatetime == tv->oldpackettime)
|
|
||||||
{
|
{
|
||||||
e->ents[e->numents].origin[0] = (lerp)*tv->entity[i].current.origin[0] + (1-lerp)*tv->entity[i].old.origin[0];
|
entity_state_t *oldstate;
|
||||||
e->ents[e->numents].origin[1] = (lerp)*tv->entity[i].current.origin[1] + (1-lerp)*tv->entity[i].old.origin[1];
|
|
||||||
e->ents[e->numents].origin[2] = (lerp)*tv->entity[i].current.origin[2] + (1-lerp)*tv->entity[i].old.origin[2];
|
if (oldindex < frompacket->numents)
|
||||||
|
{
|
||||||
|
oldnum = frompacket->entnums[oldindex];
|
||||||
|
|
||||||
|
while(oldnum < newnum)
|
||||||
|
{
|
||||||
|
oldindex++;
|
||||||
|
if (oldindex >= frompacket->numents)
|
||||||
|
break; //no more
|
||||||
|
oldnum = frompacket->entnums[oldindex];
|
||||||
|
}
|
||||||
|
if (oldnum == newnum)
|
||||||
|
{
|
||||||
|
//ent exists in old packet
|
||||||
|
oldstate = &frompacket->ents[oldindex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldstate = newstate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //reached end, definatly not in packet
|
||||||
|
oldstate = newstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((newstate->origin[0] - oldstate->origin[0])*(newstate->origin[0] - oldstate->origin[0]) > snapdist ||
|
||||||
|
(newstate->origin[1] - oldstate->origin[1])*(newstate->origin[1] - oldstate->origin[1]) > snapdist ||
|
||||||
|
(newstate->origin[2] - oldstate->origin[2])*(newstate->origin[2] - oldstate->origin[2]) > snapdist)
|
||||||
|
{ //teleported (or respawned), so don't interpolate
|
||||||
|
e->ents[e->numents].origin[0] = newstate->origin[0];
|
||||||
|
e->ents[e->numents].origin[1] = newstate->origin[1];
|
||||||
|
e->ents[e->numents].origin[2] = newstate->origin[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e->ents[e->numents].origin[0] = (lerp)*newstate->origin[0] + (1-lerp)*oldstate->origin[0];
|
||||||
|
e->ents[e->numents].origin[1] = (lerp)*newstate->origin[1] + (1-lerp)*oldstate->origin[1];
|
||||||
|
e->ents[e->numents].origin[2] = (lerp)*newstate->origin[2] + (1-lerp)*oldstate->origin[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e->numents++;
|
e->numents++;
|
||||||
|
@ -1906,6 +1985,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
||||||
if (e->numents == ENTS_PER_FRAME)
|
if (e->numents == ENTS_PER_FRAME)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SV_EmitPacketEntities(tv, v, e, msg);
|
SV_EmitPacketEntities(tv, v, e, msg);
|
||||||
|
|
||||||
|
|
|
@ -486,6 +486,27 @@ void catbuffer(char *buffer, int bufsize, char *format, ...)
|
||||||
|
|
||||||
Q_strncatz(buffer, string, bufsize);
|
Q_strncatz(buffer, string, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *Cmd_Say(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int sizeofbuffer, qboolean localcommand)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
viewer_t *v;
|
||||||
|
char message[8192];
|
||||||
|
message[0] = '\0';
|
||||||
|
for (i = 1; i < MAX_ARGS; i++)
|
||||||
|
catbuffer(message, sizeof(message)-1, "%s%s", i==1?"":" ", arg[i]);
|
||||||
|
|
||||||
|
for (v = cluster->viewers; v; v = v->next)
|
||||||
|
{
|
||||||
|
if (v->server == qtv || !qtv)
|
||||||
|
QW_PrintfToViewer(v, "proxy: %s\n", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[0] = '\0';
|
||||||
|
catbuffer(buffer, sizeofbuffer, "proxy: %s\n", message);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
char *Cmd_Status(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int sizeofbuffer, qboolean localcommand)
|
char *Cmd_Status(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int sizeofbuffer, qboolean localcommand)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -769,6 +790,24 @@ char *Cmd_MVDPort(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef VIEWER
|
||||||
|
char *Cmd_Watch(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int sizeofbuffer, qboolean localcommand)
|
||||||
|
{
|
||||||
|
if (!localcommand)
|
||||||
|
return "watch is not permitted remotly\n";
|
||||||
|
|
||||||
|
if (cluster->viewserver == qtv)
|
||||||
|
{
|
||||||
|
cluster->viewserver = NULL;
|
||||||
|
return "Stopped watching\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster->viewserver = qtv;
|
||||||
|
|
||||||
|
return "Watching\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
char *Cmd_Commands(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int sizeofbuffer, qboolean localcommand)
|
char *Cmd_Commands(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int sizeofbuffer, qboolean localcommand)
|
||||||
{
|
{
|
||||||
return "fixme\n";
|
return "fixme\n";
|
||||||
|
@ -785,6 +824,7 @@ const rconcommands_t rconcommands[] =
|
||||||
{
|
{
|
||||||
{"exec", 1, 1, Cmd_Exec},
|
{"exec", 1, 1, Cmd_Exec},
|
||||||
{"status", 1, 1, Cmd_Status},
|
{"status", 1, 1, Cmd_Status},
|
||||||
|
{"say", 1, 1, Cmd_Say},
|
||||||
|
|
||||||
{"help", 0, 1, Cmd_Help},
|
{"help", 0, 1, Cmd_Help},
|
||||||
{"commands", 0, 1, Cmd_Commands},
|
{"commands", 0, 1, Cmd_Commands},
|
||||||
|
@ -816,13 +856,16 @@ const rconcommands_t rconcommands[] =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{"disconnect", 1, 0, Cmd_Disconnect},
|
{"disconnect", 1, 0, Cmd_Disconnect},
|
||||||
{"record", 1, 0, Cmd_Record},
|
{"record", 1, 0, Cmd_Record},
|
||||||
{"stop", 1, 0, Cmd_Stop},
|
{"stop", 1, 0, Cmd_Stop},
|
||||||
{"tcpport", 1, 0, Cmd_MVDPort},
|
{"tcpport", 1, 0, Cmd_MVDPort},
|
||||||
{"mvdport", 1, 0, Cmd_MVDPort},
|
{"mvdport", 1, 0, Cmd_MVDPort},
|
||||||
|
|
||||||
|
#ifdef VIEWER
|
||||||
|
{"watch", 1, 0, Cmd_Watch},
|
||||||
|
#endif
|
||||||
|
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -857,6 +857,9 @@ void QTV_Shutdown(sv_t *qtv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cluster->viewserver == qtv)
|
||||||
|
cluster->viewserver = NULL;
|
||||||
|
|
||||||
for (v = cluster->viewers; v; v = v->next)
|
for (v = cluster->viewers; v; v = v->next)
|
||||||
{
|
{
|
||||||
if (v->server == qtv)
|
if (v->server == qtv)
|
||||||
|
@ -1200,6 +1203,8 @@ void QTV_CollectCommentry(sv_t *qtv)
|
||||||
|
|
||||||
void QTV_Run(sv_t *qtv)
|
void QTV_Run(sv_t *qtv)
|
||||||
{
|
{
|
||||||
|
int from;
|
||||||
|
int to;
|
||||||
int lengthofs;
|
int lengthofs;
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
@ -1331,7 +1336,7 @@ void QTV_Run(sv_t *qtv)
|
||||||
|
|
||||||
SetMoveCRC(qtv, &msg);
|
SetMoveCRC(qtv, &msg);
|
||||||
}
|
}
|
||||||
else if (qtv->proxyplayer)
|
else if (qtv->proxyplayer || qtv->trackplayer < 0)
|
||||||
{
|
{
|
||||||
usercmd_t *cmd[3];
|
usercmd_t *cmd[3];
|
||||||
cmd[0] = &qtv->proxyplayerucmds[(qtv->proxyplayerucmdnum-2)%3];
|
cmd[0] = &qtv->proxyplayerucmds[(qtv->proxyplayerucmdnum-2)%3];
|
||||||
|
@ -1364,6 +1369,21 @@ void QTV_Run(sv_t *qtv)
|
||||||
SetMoveCRC(qtv, &msg);
|
SetMoveCRC(qtv, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to = qtv->netchan.outgoing_sequence & (ENTITY_FRAMES-1);
|
||||||
|
from = qtv->netchan.incoming_sequence & (ENTITY_FRAMES-1);
|
||||||
|
if (qtv->frame[from].numents)
|
||||||
|
{
|
||||||
|
//remember which one we came from
|
||||||
|
qtv->frame[to].oldframe = from;
|
||||||
|
|
||||||
|
WriteByte(&msg, clc_delta);
|
||||||
|
WriteByte(&msg, qtv->frame[to].oldframe); //let the server know
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qtv->frame[to].oldframe = -1;
|
||||||
|
|
||||||
|
qtv->frame[to].numents = 0;
|
||||||
|
|
||||||
Netchan_Transmit(qtv->cluster, &qtv->netchan, msg.cursize, msg.data);
|
Netchan_Transmit(qtv->cluster, &qtv->netchan, msg.cursize, msg.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue