my attempt at android multitouch (csqc can also distinguish separate mice in windows too).
playing around with fragmentation and mtus. added net_mtu to negotiate some mtu size for smaller (or larger) network messages. setting a custom mtu allows for message fragmentation too. trying to add a reworked deltaing protocol, including all sorts of fun stuff like bbox sizes, and higher ent limits. added support for content override entities. set the skin field to some (negative) contents value, and you get movable water with prediction and waterwarp and everything, though you likely want a custom qbsp or a shader to get backface culling. removed some madness with model skins, fixing some weird q3 bugs. fixed forced-pause-on-start for q2 fixed q3 server to actually accept client packets again. fixed strftime builtin git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3979 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
fb35b91e01
commit
9ee7301d32
74 changed files with 3175 additions and 1276 deletions
|
@ -1577,6 +1577,10 @@ void Q_InitProgs(void)
|
|||
sv.world.max_edicts = MAX_EDICTS;
|
||||
sv.world.edict_size = PR_InitEnts(svprogfuncs, sv.world.max_edicts);
|
||||
|
||||
if (progstype == PROG_QW)
|
||||
sv.world.defaultgravityscale = 0;
|
||||
else
|
||||
sv.world.defaultgravityscale = 1;
|
||||
|
||||
SV_RegisterH2CustomTents();
|
||||
|
||||
|
@ -5607,18 +5611,7 @@ lh_extension_t *checkfteextensioncl(int mask, char *name) //true if the cient ex
|
|||
|
||||
lh_extension_t *checkfteextensionsv(char *name) //true if the server supports an protocol extension.
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if (svs.fteprotocolextensions & (1<<i))
|
||||
{
|
||||
if (QSG_Extensions[i].name) //some were removed
|
||||
if (!stricmp(name, QSG_Extensions[i].name)) //name matches
|
||||
return &QSG_Extensions[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return checkfteextensioncl(Net_PextMask(1), name);
|
||||
}
|
||||
|
||||
lh_extension_t *checkextension(char *name)
|
||||
|
@ -8326,7 +8319,6 @@ static void QCBUILTIN PF_runclientphys(progfuncs_t *prinst, struct globalvars_s
|
|||
VectorCopy(ent->v->velocity, pmove.velocity);
|
||||
VectorCopy(ent->v->maxs, player_maxs);
|
||||
VectorCopy(ent->v->mins, player_mins);
|
||||
pmove.hullnum = SV_HullNumForPlayer(ent->xv->hull, ent->v->mins, ent->v->maxs);
|
||||
|
||||
pmove.numphysent = 1;
|
||||
pmove.physents[0].model = sv.world.worldmodel;
|
||||
|
@ -9262,7 +9254,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
|
||||
//VM_SV_getextresponse, // #624 string getextresponse(void)
|
||||
|
||||
{"sprintf", PF_sprintf, 0, 0, 0, 627, "string(...)" STUB},
|
||||
{"sprintf", PF_sprintf, 0, 0, 0, 627, "string(...)"},
|
||||
// {"getsurfacenumpoints",VM_getsurfacenumtriangles,0,0, 0, 628, "float(entity e, float s)" STUB},
|
||||
// {"getsurfacepoint",VM_getsurfacenumtriangles,0,0, 0, 629, "vector(entity e, float s, float n)" STUB},
|
||||
|
||||
|
@ -9369,10 +9361,10 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any
|
|||
if (pr_builtin[BuiltinList[i].ebfsnum] == PF_Fixme && builtincount[BuiltinList[i].ebfsnum] == (BuiltinList[i].obsolete?0:1))
|
||||
{
|
||||
pr_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc;
|
||||
Con_DPrintf("Enabled %s (%i)\n", BuiltinList[i].name, BuiltinList[i].ebfsnum);
|
||||
// Con_DPrintf("Enabled %s (%i)\n", BuiltinList[i].name, BuiltinList[i].ebfsnum);
|
||||
}
|
||||
else if (pr_builtin[i] != BuiltinList[i].bifunc)
|
||||
Con_DPrintf("Not enabled %s (%i)\n", BuiltinList[i].name, BuiltinList[i].ebfsnum);
|
||||
// else if (pr_builtin[i] != BuiltinList[i].bifunc)
|
||||
// Con_DPrintf("Not enabled %s (%i)\n", BuiltinList[i].name, BuiltinList[i].ebfsnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9486,7 +9478,7 @@ void PR_SVExtensionList_f(void)
|
|||
|
||||
if (i < 32)
|
||||
{
|
||||
if (!(svs.fteprotocolextensions & (1<<i)))
|
||||
if (!(Net_PextMask(1) & (1<<i)))
|
||||
{
|
||||
if (showflags & SHOW_NOTSUPPORTEDEXT)
|
||||
Con_Printf("^4protocol %s is not supported\n", extlist[i].name);
|
||||
|
@ -9955,6 +9947,12 @@ void PR_DumpPlatform_f(void)
|
|||
{"RF_FRAMETIMESARESTARTTIMES","const float", CS, CSQCRF_FRAMETIMESARESTARTTIMES},
|
||||
{"RF_NOAUTOADD", "const float", CS, CSQCRF_NOAUTOADD},
|
||||
|
||||
{"IE_KEYDOWN", "const float", CS, CSIE_KEYDOWN},
|
||||
{"IE_KEYUP", "const float", CS, CSIE_KEYUP},
|
||||
{"IE_MOUSEDELTA", "const float", CS, CSIE_MOUSEDELTA},
|
||||
{"IE_MOUSEABS", "const float", CS, CSIE_MOUSEABS},
|
||||
{"IE_ACCELEROMETER", "const float", CS, CSIE_ACCELEROMETER},
|
||||
|
||||
{"FILE_READ", "const float", QW|NQ|CS, FRIK_FILE_READ},
|
||||
{"FILE_APPEND", "const float", QW|NQ|CS, FRIK_FILE_APPEND},
|
||||
{"FILE_WRITE", "const float", QW|NQ|CS, FRIK_FILE_WRITE},
|
||||
|
|
|
@ -199,6 +199,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
|
|||
comfieldentity(tag_entity)\
|
||||
comfieldfloat(skeletonindex) /*FTE_CSQC_SKELETONOBJECTS*/\
|
||||
comfieldvector(colormod)\
|
||||
comfieldvector(glowmod)\
|
||||
comfieldfloat(pmove_flags)/*EXT_CSQC_1*/\
|
||||
comfieldfloat(friction)/*DP_...PHYSICS*/\
|
||||
comfieldfloat(erp)/*DP_...PHYSICS*/\
|
||||
|
@ -277,7 +278,6 @@ and the extension fields are added on the end and can have extra vm-specific stu
|
|||
\
|
||||
comfieldfloat(drawmask) /*So that the qc can specify all rockets at once or all bannanas at once*/ \
|
||||
comfieldfunction(predraw, ".void()") /*If present, is called just before it's drawn.*/ \
|
||||
comfieldvector(glowmod) \
|
||||
\
|
||||
comfieldfloat(ideal_pitch)\
|
||||
comfieldfloat(pitch_speed)
|
||||
|
|
|
@ -581,7 +581,7 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
|
|||
f = FS_OpenVFS(name, "rb", FS_GAME);
|
||||
if (!f)
|
||||
{
|
||||
Con_TPrintf (STL_ERRORCOULDNTOPEN);
|
||||
Con_Printf ("ERROR: Couldn't load \"%s\"\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -790,35 +790,37 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
|
|||
vfsfile_t *f;
|
||||
int i;
|
||||
char comment[SAVEGAME_COMMENT_LENGTH+1];
|
||||
|
||||
levelcache_t *cache;
|
||||
|
||||
if (!sv.state)
|
||||
return;
|
||||
|
||||
cache = svs.levcache;
|
||||
while(cache)
|
||||
if (!dontharmgame)
|
||||
{
|
||||
if (!strcmp(cache->mapname, sv.name))
|
||||
break;
|
||||
cache = svs.levcache;
|
||||
while(cache)
|
||||
{
|
||||
if (!strcmp(cache->mapname, sv.name))
|
||||
break;
|
||||
|
||||
cache = cache->next;
|
||||
cache = cache->next;
|
||||
}
|
||||
if (!cache) //not visited yet. Let us know that we went there.
|
||||
{
|
||||
cache = Z_Malloc(sizeof(levelcache_t)+strlen(sv.name)+1);
|
||||
cache->mapname = (char *)(cache+1);
|
||||
strcpy(cache->mapname, sv.name);
|
||||
|
||||
cache->gametype = svs.gametype;
|
||||
cache->next = svs.levcache;
|
||||
svs.levcache = cache;
|
||||
}
|
||||
}
|
||||
if (!cache) //not visited yet. Let us know that we went there.
|
||||
{
|
||||
cache = Z_Malloc(sizeof(levelcache_t)+strlen(sv.name)+1);
|
||||
cache->mapname = (char *)(cache+1);
|
||||
strcpy(cache->mapname, sv.name);
|
||||
|
||||
cache->gametype = svs.gametype;
|
||||
cache->next = svs.levcache;
|
||||
svs.levcache = cache;
|
||||
}
|
||||
|
||||
|
||||
if (savedir)
|
||||
Q_snprintfz (name, sizeof(name), "saves/%s/%s", savedir, cache->mapname);
|
||||
Q_snprintfz (name, sizeof(name), "saves/%s/%s", savedir, sv.name);
|
||||
else
|
||||
Q_snprintfz (name, sizeof(name), "saves/%s", cache->mapname);
|
||||
Q_snprintfz (name, sizeof(name), "saves/%s", sv.name);
|
||||
COM_DefaultExtension (name, ".lvc", sizeof(name));
|
||||
|
||||
FS_CreatePath(name, FS_GAMEONLY);
|
||||
|
@ -859,7 +861,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame)
|
|||
VFS_PRINTF (f, "%s\n", comment);
|
||||
if (!dontharmgame)
|
||||
{
|
||||
for (cl = svs.clients, clnum=0; clnum < MAX_CLIENTS; cl++,clnum++)//fake dropping
|
||||
for (cl = svs.clients, clnum=0; clnum < sv.allocated_client_slots; cl++,clnum++)//fake dropping
|
||||
{
|
||||
if (cl->state < cs_spawned && !cl->istobeloaded) //don't drop if they are still connecting
|
||||
{
|
||||
|
|
|
@ -76,7 +76,7 @@ typedef struct laggedpacket_s
|
|||
double time;
|
||||
struct laggedpacket_s *next;
|
||||
int length;
|
||||
unsigned char data[MAX_QWMSGLEN];
|
||||
unsigned char data[MAX_QWMSGLEN+10];
|
||||
} laggedpacket_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -284,14 +284,16 @@ typedef struct
|
|||
// received from client
|
||||
|
||||
// reply
|
||||
double senttime;
|
||||
float ping_time;
|
||||
int move_msecs;
|
||||
int packetsizein;
|
||||
int packetsizeout;
|
||||
vec3_t playerpositions[MAX_CLIENTS];
|
||||
qboolean playerpresent[MAX_CLIENTS];
|
||||
packet_entities_t entities; //must come last (mvd states are bigger)
|
||||
double senttime; //time we sent this frame to the client, for ping calcs
|
||||
int sequence; //the outgoing sequence - without mask, meaning we know if its current or stale
|
||||
float ping_time; //how long it took for the client to ack it, may be negativ
|
||||
int move_msecs; //
|
||||
int packetsizein; //amount of data received for this frame
|
||||
int packetsizeout; //amount of data that was sent in the frame
|
||||
vec3_t playerpositions[MAX_CLIENTS]; //where each player was in this frame, for antilag
|
||||
qboolean playerpresent[MAX_CLIENTS]; //whether the player was actually present
|
||||
packet_entities_t entities; //package containing entity states that were sent in this frame, for deltaing
|
||||
unsigned int *resendentbits; //the bits of each entity that were sent in this frame
|
||||
} client_frame_t;
|
||||
|
||||
#ifdef Q2SERVER
|
||||
|
@ -351,6 +353,7 @@ typedef struct client_s
|
|||
usercmd_t lastcmd; // for filling in big drops and partial predictions
|
||||
double localtime; // of last message
|
||||
qboolean jump_held;
|
||||
qboolean lockangles; //mod is spamming angle changes, don't do relative changes
|
||||
|
||||
float maxspeed; // localized maxspeed
|
||||
float entgravity; // localized ent gravity
|
||||
|
@ -417,6 +420,8 @@ typedef struct client_s
|
|||
q3client_frame_t *q3frames;
|
||||
#endif
|
||||
} frameunion;
|
||||
packet_entities_t sentents;
|
||||
unsigned int *pendingentbits;
|
||||
|
||||
char downloadfn[MAX_QPATH];
|
||||
vfsfile_t *download; // file being downloaded
|
||||
|
@ -469,7 +474,7 @@ typedef struct client_s
|
|||
netchan_t netchan;
|
||||
qboolean isindependant;
|
||||
|
||||
int lastsequence_acknoledged;
|
||||
int lastsequence_acknowledged;
|
||||
|
||||
#ifdef VOICECHAT
|
||||
unsigned int voice_read; /*place in ring*/
|
||||
|
@ -507,7 +512,7 @@ typedef struct client_s
|
|||
unsigned long fteprotocolextensions2;
|
||||
#endif
|
||||
unsigned long zquake_extensions;
|
||||
unsigned int max_net_ents;
|
||||
unsigned int max_net_ents; /*highest entity number the client can receive (limited by either protocol or client's buffer size)*/
|
||||
unsigned int maxmodels; /*max models supported by whatever the protocol is*/
|
||||
|
||||
enum {
|
||||
|
@ -760,10 +765,6 @@ typedef struct
|
|||
progsnum_t progsnum[MAX_PROGS];
|
||||
int numprogs;
|
||||
|
||||
#ifdef PROTOCOLEXTENSIONS
|
||||
unsigned long fteprotocolextensions;
|
||||
unsigned long fteprotocolextensions2;
|
||||
#endif
|
||||
struct netprim_s netprim;
|
||||
|
||||
qboolean demoplayback;
|
||||
|
@ -772,6 +773,7 @@ typedef struct
|
|||
|
||||
int language; //the server operators language
|
||||
laggedpacket_t *free_lagged_packet;
|
||||
packet_entities_t entstatebuffer; /*just a temp buffer*/
|
||||
|
||||
levelcache_t *levcache;
|
||||
} server_static_t;
|
||||
|
@ -917,7 +919,7 @@ void SVNQ_FullClientUpdate (client_t *client, sizebuf_t *buf);
|
|||
int SV_ModelIndex (char *name);
|
||||
|
||||
void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg);
|
||||
void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext);
|
||||
void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext);
|
||||
|
||||
void SV_SaveSpawnparms (qboolean);
|
||||
void SV_SaveLevelCache(char *savename, qboolean dontharmgame);
|
||||
|
@ -955,8 +957,8 @@ qboolean SVQ2_InitGameProgs(void);
|
|||
void VARGS SVQ2_ShutdownGameProgs (void);
|
||||
|
||||
//svq2_ents.c
|
||||
void SV_BuildClientFrame (client_t *client);
|
||||
void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg);
|
||||
void SVQ2_BuildClientFrame (client_t *client);
|
||||
void SVQ2_WriteFrameToClient (client_t *client, sizebuf_t *msg);
|
||||
#ifdef Q2SERVER
|
||||
void MSGQ2_WriteDeltaEntity (q2entity_state_t *from, q2entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean newentity);
|
||||
void SVQ2_BuildBaselines(void);
|
||||
|
@ -967,7 +969,7 @@ void SVQ2_BuildBaselines(void);
|
|||
void SVQ3_ShutdownGame(void);
|
||||
qboolean SVQ3_InitGame(void);
|
||||
qboolean SVQ3_ConsoleCommand(void);
|
||||
void SVQ3_HandleClient(void);
|
||||
qboolean SVQ3_HandleClient(void);
|
||||
void SVQ3_DirectConnect(void);
|
||||
void SVQ3_DropClient(client_t *cl);
|
||||
int SVQ3_AddBot(void);
|
||||
|
|
|
@ -393,10 +393,33 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef PEXT_CSQC
|
||||
void SV_CSQC_DroppedPacket(client_t *client, int sequence)
|
||||
{
|
||||
int i;
|
||||
//skip it if we never generated that frame, to avoid pulling in stale data
|
||||
if (client->frameunion.frames[sequence & UPDATE_MASK].sequence != sequence)
|
||||
{
|
||||
Con_Printf("SV: Stale %i\n", sequence);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
{
|
||||
unsigned int *f = client->frameunion.frames[sequence & UPDATE_MASK].resendentbits;
|
||||
Con_Printf("SV: Resend %i\n", sequence);
|
||||
i = client->max_net_ents;
|
||||
if (i > sv.world.num_edicts)
|
||||
i = sv.world.num_edicts;
|
||||
while (i > 0)
|
||||
{
|
||||
if (f[i])
|
||||
{
|
||||
client->pendingentbits[i] |= f[i];
|
||||
f[i] = 0;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(client->csqcactive)) //we don't need this, but it might be a little faster.
|
||||
return;
|
||||
|
@ -408,13 +431,19 @@ void SV_CSQC_DroppedPacket(client_t *client, int sequence)
|
|||
void SV_CSQC_DropAll(client_t *client)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
{
|
||||
Con_Printf("Reset all\n");
|
||||
client->pendingentbits[0] = UF_REMOVE;
|
||||
}
|
||||
|
||||
if (!(client->csqcactive)) //we don't need this, but it might be a little faster.
|
||||
return;
|
||||
|
||||
for (i = 0; i < sv.world.num_edicts; i++)
|
||||
client->csqcentversions[i]--; //do that update thang (but later).
|
||||
}
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
@ -427,7 +456,7 @@ Writes part of a packetentities message.
|
|||
Can delta from either a baseline or a previous packet_entity
|
||||
==================
|
||||
*/
|
||||
void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext)
|
||||
void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext)
|
||||
{
|
||||
#ifdef PROTOCOLEXTENSIONS
|
||||
int evenmorebits=0;
|
||||
|
@ -554,8 +583,8 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb
|
|||
evenmorebits |= U_LIGHT;
|
||||
#endif
|
||||
|
||||
if (to->flags & U_SOLID)
|
||||
bits |= U_SOLID;
|
||||
// if (to->solid)
|
||||
// bits |= U_SOLID;
|
||||
|
||||
if (msg->cursize + 40 > msg->maxsize)
|
||||
{ //not enough space in the buffer, don't send the entity this frame. (not sending means nothing changes, and it takes no bytes!!)
|
||||
|
@ -684,15 +713,382 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb
|
|||
MSG_WriteByte (msg, (to->effects&0xff00)>>8);
|
||||
}
|
||||
|
||||
/*special flags which are slightly more compact. these are 'wasted' as part of the delta itself*/
|
||||
#define UF_REMOVE UF_16BIT /*special flag, slightly more compact (we can reuse the 16bit flag as its not important)*/
|
||||
#define UF_MOVETYPE UF_EFFECTS2
|
||||
//#define UF_WASTED3 UF_EXTEND1
|
||||
//#define UF_WASTED2 UF_EXTEND2
|
||||
//#define UF_WASTED1 UF_EXTEND3
|
||||
|
||||
static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to)
|
||||
{
|
||||
unsigned int bits = 0;
|
||||
|
||||
if (to->u.q1.pmovetype)
|
||||
{
|
||||
bits |= UF_PREDINFO;
|
||||
/*if we've got player movement then always resend this extra stuff to avoid any weird loss*/
|
||||
bits |= UF_ORIGINXY | UF_ORIGINZ | UF_ANGLESXZ | UF_ANGLESY;
|
||||
if (from->u.q1.pmovetype != to->u.q1.pmovetype)
|
||||
bits |= UF_MOVETYPE;
|
||||
}
|
||||
|
||||
if (to->origin[0] != from->origin[0])
|
||||
bits |= UF_ORIGINXY;
|
||||
if (to->origin[1] != from->origin[1])
|
||||
bits |= UF_ORIGINXY;
|
||||
if (to->origin[2] != from->origin[2])
|
||||
bits |= UF_ORIGINZ;
|
||||
|
||||
if (to->angles[0] != from->angles[0])
|
||||
bits |= UF_ANGLESXZ;
|
||||
if (to->angles[1] != from->angles[1])
|
||||
bits |= UF_ANGLESY;
|
||||
if (to->angles[2] != from->angles[2])
|
||||
bits |= UF_ANGLESXZ;
|
||||
|
||||
|
||||
if (to->modelindex != from->modelindex)
|
||||
bits |= UF_MODEL;
|
||||
if (to->frame != from->frame)
|
||||
bits |= UF_FRAME;
|
||||
if (to->skinnum != from->skinnum)
|
||||
bits |= UF_SKIN;
|
||||
if (to->colormap != from->colormap)
|
||||
bits |= UF_COLORMAP;
|
||||
if (to->effects != from->effects)
|
||||
bits |= UF_EFFECTS;
|
||||
if (to->dpflags != from->dpflags)
|
||||
bits |= UF_FLAGS;
|
||||
if (to->solid != from->solid)
|
||||
bits |= UF_SOLID;
|
||||
|
||||
if (to->scale != from->scale)
|
||||
bits |= UF_SCALE;
|
||||
if (to->trans != from->trans)
|
||||
bits |= UF_ALPHA;
|
||||
if (to->fatness != from->fatness)
|
||||
bits |= UF_FATNESS;
|
||||
|
||||
if (to->hexen2flags != from->hexen2flags)
|
||||
bits |= UF_DRAWFLAGS;
|
||||
if (to->abslight != from->abslight)
|
||||
bits |= UF_ABSLIGHT;
|
||||
|
||||
if (to->colormod[0]!=from->colormod[0]||to->colormod[1]!=from->colormod[1]||to->colormod[2]!=from->colormod[2])
|
||||
bits |= UF_COLORMOD;
|
||||
|
||||
if (to->glowmod[0]!=from->glowmod[0]||to->glowmod[1]!=from->glowmod[1]||to->glowmod[2]!=from->glowmod[2])
|
||||
bits |= UF_GLOWMOD;
|
||||
|
||||
if (to->tagentity != from->tagentity || to->tagindex != from->tagindex)
|
||||
bits |= UF_TAGINFO;
|
||||
|
||||
if (to->light[0] != from->light[0] || to->light[1] != from->light[1] || to->light[2] != from->light[2] || to->light[3] != from->light[3] || to->lightstyle != from->lightstyle || to->lightpflags != from->lightstyle)
|
||||
bits |= UF_LIGHT;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_t *msg)
|
||||
{
|
||||
unsigned int predbits = 0;
|
||||
if (bits & UF_MOVETYPE)
|
||||
{
|
||||
bits &= ~UF_MOVETYPE;
|
||||
predbits |= UFP_MOVETYPE;
|
||||
}
|
||||
|
||||
/*check if we need more precision*/
|
||||
if ((bits & UF_MODEL) && state->modelindex > 255)
|
||||
bits |= UF_16BIT;
|
||||
if ((bits & UF_SKIN) && state->skinnum > 255)
|
||||
bits |= UF_16BIT;
|
||||
if ((bits & UF_FRAME) && state->frame > 255)
|
||||
bits |= UF_16BIT;
|
||||
|
||||
/*convert effects bits to higher lengths if needed*/
|
||||
if (bits & UF_EFFECTS)
|
||||
{
|
||||
if (state->effects & 0xffff0000) /*both*/
|
||||
bits |= UF_EFFECTS | UF_EFFECTS2;
|
||||
else if (state->effects & 0x0000ff00) /*2 only*/
|
||||
bits = (bits & ~UF_EFFECTS) | UF_EFFECTS2;
|
||||
}
|
||||
if (bits & 0xff000000)
|
||||
bits |= UF_EXTEND3;
|
||||
if (bits & 0x00ff0000)
|
||||
bits |= UF_EXTEND2;
|
||||
if (bits & 0x0000ff00)
|
||||
bits |= UF_EXTEND1;
|
||||
|
||||
MSG_WriteByte(msg, bits>>0);
|
||||
if (bits & UF_EXTEND1)
|
||||
MSG_WriteByte(msg, bits>>8);
|
||||
if (bits & UF_EXTEND2)
|
||||
MSG_WriteByte(msg, bits>>16);
|
||||
if (bits & UF_EXTEND3)
|
||||
MSG_WriteByte(msg, bits>>24);
|
||||
|
||||
if (bits & UF_FRAME)
|
||||
{
|
||||
if (bits & UF_16BIT)
|
||||
MSG_WriteShort(msg, state->frame);
|
||||
else
|
||||
MSG_WriteByte(msg, state->frame);
|
||||
}
|
||||
if (bits & UF_ORIGINXY)
|
||||
{
|
||||
MSG_WriteCoord(msg, state->origin[0]);
|
||||
MSG_WriteCoord(msg, state->origin[1]);
|
||||
}
|
||||
if (bits & UF_ORIGINZ)
|
||||
MSG_WriteCoord(msg, state->origin[2]);
|
||||
|
||||
if (bits & UF_PREDINFO)
|
||||
{ /*if we have pred info, use more precise angles*/
|
||||
if (bits & UF_ANGLESXZ)
|
||||
{
|
||||
MSG_WriteAngle16(msg, state->angles[0]);
|
||||
MSG_WriteAngle16(msg, state->angles[2]);
|
||||
}
|
||||
if (bits & UF_ANGLESY)
|
||||
MSG_WriteAngle16(msg, state->angles[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bits & UF_ANGLESXZ)
|
||||
{
|
||||
MSG_WriteAngle(msg, state->angles[0]);
|
||||
MSG_WriteAngle(msg, state->angles[2]);
|
||||
}
|
||||
if (bits & UF_ANGLESY)
|
||||
MSG_WriteAngle(msg, state->angles[1]);
|
||||
}
|
||||
|
||||
if ((bits & (UF_EFFECTS|UF_EFFECTS2)) == (UF_EFFECTS|UF_EFFECTS2))
|
||||
MSG_WriteLong(msg, state->effects);
|
||||
else if (bits & UF_EFFECTS2)
|
||||
MSG_WriteShort(msg, state->effects);
|
||||
else if (bits & UF_EFFECTS)
|
||||
MSG_WriteByte(msg, state->effects);
|
||||
|
||||
if (bits & UF_PREDINFO)
|
||||
{
|
||||
/*movetype is set above somewhere*/
|
||||
if (state->u.q1.movement[0])
|
||||
predbits |= UFP_FORWARD;
|
||||
if (state->u.q1.movement[1])
|
||||
predbits |= UFP_SIDE;
|
||||
if (state->u.q1.movement[2])
|
||||
predbits |= UFP_UP;
|
||||
if (state->u.q1.velocity[0])
|
||||
predbits |= UFP_VELOCITYXY;
|
||||
if (state->u.q1.velocity[1])
|
||||
predbits |= UFP_VELOCITYXY;
|
||||
if (state->u.q1.velocity[2])
|
||||
predbits |= UFP_VELOCITYZ;
|
||||
if (state->u.q1.msec)
|
||||
predbits |= UFP_MSEC;
|
||||
|
||||
MSG_WriteByte(msg, predbits);
|
||||
if (predbits & UFP_FORWARD)
|
||||
MSG_WriteShort(msg, state->u.q1.movement[0]);
|
||||
if (predbits & UFP_SIDE)
|
||||
MSG_WriteShort(msg, state->u.q1.movement[1]);
|
||||
if (predbits & UFP_UP)
|
||||
MSG_WriteShort(msg, state->u.q1.movement[2]);
|
||||
if (predbits & UFP_MOVETYPE)
|
||||
MSG_WriteByte(msg, state->u.q1.pmovetype);
|
||||
if (predbits & UFP_VELOCITYXY)
|
||||
{
|
||||
MSG_WriteShort(msg, state->u.q1.velocity[0]);
|
||||
MSG_WriteShort(msg, state->u.q1.velocity[1]);
|
||||
}
|
||||
if (predbits & UFP_VELOCITYZ)
|
||||
MSG_WriteShort(msg, state->u.q1.velocity[2]);
|
||||
if (predbits & UFP_MSEC)
|
||||
MSG_WriteByte(msg, state->u.q1.msec);
|
||||
}
|
||||
|
||||
if (bits & UF_MODEL)
|
||||
{
|
||||
if (bits & UF_16BIT)
|
||||
MSG_WriteShort(msg, state->modelindex);
|
||||
else
|
||||
MSG_WriteByte(msg, state->modelindex);
|
||||
}
|
||||
if (bits & UF_SKIN)
|
||||
{
|
||||
if (bits & UF_16BIT)
|
||||
MSG_WriteShort(msg, state->skinnum);
|
||||
else
|
||||
MSG_WriteByte(msg, state->skinnum);
|
||||
}
|
||||
if (bits & UF_COLORMAP)
|
||||
MSG_WriteByte(msg, state->colormap);
|
||||
|
||||
if (bits & UF_SOLID)
|
||||
MSG_WriteShort(msg, state->solid);
|
||||
|
||||
if (bits & UF_FLAGS)
|
||||
MSG_WriteByte(msg, state->dpflags);
|
||||
|
||||
if (bits & UF_ALPHA)
|
||||
MSG_WriteByte(msg, state->trans);
|
||||
if (bits & UF_SCALE)
|
||||
MSG_WriteByte(msg, state->scale);
|
||||
if (bits & UF_ABSLIGHT)
|
||||
MSG_WriteByte(msg, state->abslight);
|
||||
if (bits & UF_DRAWFLAGS)
|
||||
MSG_WriteByte(msg, state->hexen2flags);
|
||||
if (bits & UF_TAGINFO)
|
||||
{
|
||||
MSG_WriteShort(msg, state->tagentity);
|
||||
MSG_WriteByte(msg, state->tagindex);
|
||||
}
|
||||
if (bits & UF_LIGHT)
|
||||
{
|
||||
MSG_WriteShort (msg, state->light[0]);
|
||||
MSG_WriteShort (msg, state->light[1]);
|
||||
MSG_WriteShort (msg, state->light[2]);
|
||||
MSG_WriteShort (msg, state->light[3]);
|
||||
MSG_WriteByte (msg, state->lightstyle);
|
||||
MSG_WriteByte (msg, state->lightpflags);
|
||||
}
|
||||
|
||||
if (bits & UF_COLORMOD)
|
||||
{
|
||||
MSG_WriteByte(msg, state->colormod[0]);
|
||||
MSG_WriteByte(msg, state->colormod[1]);
|
||||
MSG_WriteByte(msg, state->colormod[2]);
|
||||
}
|
||||
if (bits & UF_GLOWMOD)
|
||||
{
|
||||
MSG_WriteByte(msg, state->glowmod[0]);
|
||||
MSG_WriteByte(msg, state->glowmod[1]);
|
||||
MSG_WriteByte(msg, state->glowmod[2]);
|
||||
}
|
||||
if (bits & UF_FATNESS)
|
||||
MSG_WriteByte(msg, state->fatness);
|
||||
}
|
||||
|
||||
/*SVFTE_EmitPacketEntities
|
||||
Writes changed entities to the client.
|
||||
Changed ent states will be tracked, even if they're not sent just yet, dropped packets will also re-flag dropped delta bits
|
||||
Only what changed is tracked, via bitmask, its previous value is never tracked.
|
||||
*/
|
||||
void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t *msg)
|
||||
{
|
||||
entity_state_t *o, *n;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int *resend;
|
||||
qboolean reset = (client->delta_sequence == -1) || (client->pendingentbits[0] & UF_REMOVE);
|
||||
|
||||
if (reset)
|
||||
{
|
||||
for (j = 0; j < client->sentents.max_entities; j++)
|
||||
{
|
||||
client->sentents.entities[j].number = 0;
|
||||
client->pendingentbits[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
j = 0;
|
||||
if (to->num_entities)
|
||||
{
|
||||
j = to->entities[to->num_entities-1].number+1;
|
||||
if (j > client->sentents.max_entities)
|
||||
{
|
||||
client->sentents.entities = BZ_Realloc(client->sentents.entities, sizeof(*client->sentents.entities) * j);
|
||||
memset(&client->sentents.entities[client->sentents.max_entities], 0, sizeof(client->sentents.entities[0]) * (j - client->sentents.max_entities));
|
||||
client->sentents.max_entities = j;
|
||||
}
|
||||
}
|
||||
|
||||
/*figure out the bits that changed*/
|
||||
for (i = 0, j = 0; i < to->num_entities; i++)
|
||||
{
|
||||
n = &to->entities[i];
|
||||
/*gaps are dead entities*/
|
||||
for (; j < n->number; j++)
|
||||
{
|
||||
o = &client->sentents.entities[j];
|
||||
if (o->number)
|
||||
{
|
||||
client->pendingentbits[j] = UF_REMOVE;
|
||||
o->number = 0; /*dead*/
|
||||
}
|
||||
}
|
||||
|
||||
o = &client->sentents.entities[j];
|
||||
if (!o->number)
|
||||
{
|
||||
/*forget any remove bits*/
|
||||
client->pendingentbits[j] = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM(svprogfuncs, n->number)->baseline, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->pendingentbits[j] |= SVFTE_DeltaCalcBits(o, n);;
|
||||
}
|
||||
*o = *n;
|
||||
j++;
|
||||
}
|
||||
/*gaps are dead entities*/
|
||||
for (; j < client->sentents.max_entities; j++)
|
||||
{
|
||||
o = &client->sentents.entities[j];
|
||||
if (o->number)
|
||||
{
|
||||
client->pendingentbits[j] = UF_REMOVE;
|
||||
o->number = 0; /*dead*/
|
||||
}
|
||||
}
|
||||
|
||||
resend = client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK].resendentbits;
|
||||
|
||||
MSG_WriteByte (msg, svcfte_updateentities);
|
||||
MSG_WriteFloat(msg, sv.world.physicstime);
|
||||
if (reset)
|
||||
MSG_WriteShort(msg, 0x8000);
|
||||
|
||||
memset(resend, 0, client->sentents.max_entities*sizeof(*resend));
|
||||
|
||||
for(j = 0; j < client->sentents.max_entities; j++)
|
||||
{
|
||||
if (!client->pendingentbits[j])
|
||||
continue;
|
||||
if (msg->cursize + 50 > msg->maxsize)
|
||||
break; /*give up if it gets full*/
|
||||
|
||||
if (client->pendingentbits[j] & UF_REMOVE)
|
||||
{
|
||||
MSG_WriteShort(msg, j | 0x8000);
|
||||
resend[j] = UF_REMOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteShort(msg, j);
|
||||
SVFTE_WriteUpdate(client->pendingentbits[j], &client->sentents.entities[j], msg);
|
||||
resend[j] = client->pendingentbits[j];
|
||||
}
|
||||
client->pendingentbits[j] = 0;
|
||||
}
|
||||
|
||||
MSG_WriteShort(msg, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_EmitPacketEntities
|
||||
SVQW_EmitPacketEntities
|
||||
|
||||
Writes a delta update of a packet_entities_t to the message.
|
||||
|
||||
deltaing is performed from one set of entity states directly to the next
|
||||
=============
|
||||
*/
|
||||
void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
|
||||
void SVQW_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
|
||||
{
|
||||
edict_t *ent;
|
||||
client_frame_t *fromframe;
|
||||
|
@ -732,9 +1128,9 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *
|
|||
{ // delta update from old position
|
||||
//Con_Printf ("delta %i\n", newnum);
|
||||
#ifdef PROTOCOLEXTENSIONS
|
||||
SV_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false, client->fteprotocolextensions);
|
||||
SVQW_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false, client->fteprotocolextensions);
|
||||
#else
|
||||
SV_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false);
|
||||
SVQW_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false);
|
||||
#endif
|
||||
oldindex++;
|
||||
newindex++;
|
||||
|
@ -749,9 +1145,9 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *
|
|||
ent = NULL;
|
||||
//Con_Printf ("baseline %i\n", newnum);
|
||||
#ifdef PROTOCOLEXTENSIONS
|
||||
SV_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true, client->fteprotocolextensions);
|
||||
SVQW_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true, client->fteprotocolextensions);
|
||||
#else
|
||||
SV_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true);
|
||||
SVQW_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true);
|
||||
#endif
|
||||
newindex++;
|
||||
continue;
|
||||
|
@ -1064,8 +1460,6 @@ void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t
|
|||
if (client->protocol == SCP_DARKPLACES7)
|
||||
MSG_WriteLong(msg, client->last_sequence);
|
||||
|
||||
for (newindex = 0; newindex < to->num_entities; newindex++)
|
||||
to->entities[newindex].bitmask = 0;
|
||||
//add in the bitmasks of dropped packets.
|
||||
|
||||
newindex = 0;
|
||||
|
@ -2197,18 +2591,49 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
|
||||
int i;
|
||||
|
||||
#ifdef Q2SERVER
|
||||
state->modelindex2 = 0;
|
||||
state->modelindex3 = 0;
|
||||
state->modelindex4 = 0;
|
||||
state->event = 0;
|
||||
state->solid = 0;
|
||||
state->sound = 0;
|
||||
state->renderfx = 0;
|
||||
state->old_origin[0] = 0;
|
||||
state->old_origin[1] = 0;
|
||||
state->old_origin[2] = 0;
|
||||
#endif
|
||||
state->number = NUM_FOR_EDICT(svprogfuncs, ent);
|
||||
|
||||
state->u.q1.msec = 0;
|
||||
state->u.q1.pmovetype = 0;
|
||||
state->u.q1.movement[0] = 0;
|
||||
state->u.q1.movement[1] = 0;
|
||||
state->u.q1.movement[2] = 0;
|
||||
state->u.q1.velocity[0] = 0;
|
||||
state->u.q1.velocity[1] = 0;
|
||||
state->u.q1.velocity[2] = 0;
|
||||
if ((state->number-1) < (unsigned short)sv.allocated_client_slots && ent->v->movetype)
|
||||
{
|
||||
client_t *cl = &svs.clients[state->number-1];
|
||||
if (cl->isindependant)
|
||||
{
|
||||
state->u.q1.pmovetype = ent->v->movetype;
|
||||
if (cl != client)
|
||||
{ /*only generate movement values if the client doesn't already know them...*/
|
||||
state->u.q1.movement[0] = ent->xv->movement[0];
|
||||
state->u.q1.movement[1] = ent->xv->movement[1];
|
||||
state->u.q1.movement[2] = ent->xv->movement[2];
|
||||
state->u.q1.msec = bound(0, 1000*(sv.time - cl->localtime), 255);
|
||||
}
|
||||
|
||||
state->u.q1.velocity[0] = ent->v->velocity[0] * 8;
|
||||
state->u.q1.velocity[1] = ent->v->velocity[1] * 8;
|
||||
state->u.q1.velocity[2] = ent->v->velocity[2] * 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (ent->v->solid == SOLID_BSP || (ent->v->skin < 0 && ent->v->modelindex))
|
||||
state->solid = ES_SOLID_BSP;
|
||||
else if (ent->v->solid == SOLID_BBOX || ent->v->solid == SOLID_SLIDEBOX || ent->v->skin < 0)
|
||||
{
|
||||
i = bound(0, -ent->v->mins[0]/8, 31);
|
||||
state->solid = i;
|
||||
i = bound(0, -ent->v->mins[2]/8, 31);
|
||||
state->solid |= i<<5;
|
||||
i = bound(0, ((ent->v->maxs[2]+32)/8), 63); /*up can be negative*/
|
||||
state->solid |= i<<10;
|
||||
}
|
||||
else
|
||||
state->solid = 0;
|
||||
|
||||
state->dpflags = 0;
|
||||
if (ent->xv->viewmodelforclient)
|
||||
|
@ -2216,6 +2641,8 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
//if ent->viewmodelforclient == client then:
|
||||
state->dpflags |= RENDER_VIEWMODEL;
|
||||
}
|
||||
if (ent->v->colormap >= 1024)
|
||||
state->dpflags |= RENDER_COLORMAPPED;
|
||||
if (ent->xv->exteriormodeltoclient && client)
|
||||
{
|
||||
if (ent->xv->exteriormodeltoclient == EDICT_TO_PROG(svprogfuncs, client->edict))
|
||||
|
@ -2226,11 +2653,11 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
if (ent->v->movetype == MOVETYPE_STEP)
|
||||
state->dpflags |= RENDER_STEP;
|
||||
|
||||
state->number = NUM_FOR_EDICT(svprogfuncs, ent);
|
||||
state->flags = 0;
|
||||
VectorCopy (ent->v->origin, state->origin);
|
||||
VectorCopy (ent->v->angles, state->angles);
|
||||
state->modelindex = ent->v->modelindex;
|
||||
state->modelindex2 = ent->xv->vw_index;
|
||||
state->frame = ent->v->frame;
|
||||
state->colormap = ent->v->colormap;
|
||||
state->skinnum = ent->v->skin;
|
||||
|
@ -2247,7 +2674,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
state->lightstyle = ent->xv->style;
|
||||
state->lightpflags = ent->xv->pflags;
|
||||
|
||||
if ((int)ent->v->flags & FL_CLASS_DEPENDENT && client->playerclass) //hexen2 wierdness.
|
||||
if (((int)ent->v->flags & FL_CLASS_DEPENDENT) && client->playerclass) //hexen2 wierdness.
|
||||
{
|
||||
char modname[MAX_QPATH];
|
||||
Q_strncpyz(modname, sv.strings.model_precache[state->modelindex], sizeof(modname));
|
||||
|
@ -2306,6 +2733,9 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
i = ent->xv->colormod[1]*(256/8); state->colormod[1] = bound(0, i, 255);
|
||||
i = ent->xv->colormod[2]*(256/8); state->colormod[2] = bound(0, i, 255);
|
||||
}
|
||||
state->glowmod[0] = ent->xv->glowmod[0]*(256/8);
|
||||
state->glowmod[1] = ent->xv->glowmod[1]*(256/8);
|
||||
state->glowmod[2] = ent->xv->glowmod[2]*(256/8);
|
||||
state->glowsize = ent->xv->glow_size*0.25;
|
||||
state->glowcolour = ent->xv->glow_color;
|
||||
if (ent->xv->glow_trail)
|
||||
|
@ -2338,6 +2768,8 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
#ifdef PEXT_FATNESS
|
||||
state->fatness = ent->xv->fatness;
|
||||
#endif
|
||||
|
||||
#pragma warningmsg("TODO: Fix attachments for more vanilla clients")
|
||||
}
|
||||
|
||||
void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, edict_t *clent, qboolean ignorepvs)
|
||||
|
@ -2349,7 +2781,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
|
|||
#define DEPTHOPTIMISE
|
||||
#ifdef DEPTHOPTIMISE
|
||||
vec3_t org;
|
||||
float distances[MAX_EXTENDED_PACKET_ENTITIES];
|
||||
static float distances[32768];
|
||||
float dist;
|
||||
#endif
|
||||
globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
|
||||
|
@ -2401,12 +2833,13 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
|
|||
}
|
||||
|
||||
|
||||
/*legacy qw clients get their players separately*/
|
||||
if (ISQWCLIENT(client) && !(client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))
|
||||
e = sv.allocated_client_slots+1;
|
||||
else
|
||||
e = 1;
|
||||
|
||||
#ifdef NQPROT
|
||||
for (e=(ISQWCLIENT(client)?sv.allocated_client_slots+1:1) ; e<sv.world.num_edicts ; e++)
|
||||
#else
|
||||
for (e=sv.allocated_client_slots+1 ; e<sv.num_edicts ; e++)
|
||||
#endif
|
||||
for ( ; e<sv.world.num_edicts ; e++)
|
||||
{
|
||||
ent = EDICT_NUM(svprogfuncs, e);
|
||||
|
||||
|
@ -2446,7 +2879,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
|
|||
else
|
||||
{
|
||||
// ignore ents without visible models
|
||||
if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC))
|
||||
if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC) && ent->v->skin >= 0)
|
||||
continue;
|
||||
|
||||
pvsflags = ent->xv->pvsflags;
|
||||
|
@ -2698,13 +3131,20 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
}
|
||||
|
||||
host_client = client;
|
||||
pack = &frame->entities;
|
||||
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
{
|
||||
pack = &svs.entstatebuffer;
|
||||
if (pack->max_entities < client->max_net_ents)
|
||||
{
|
||||
pack->max_entities = client->max_net_ents;
|
||||
pack->entities = BZ_Realloc(pack->entities, sizeof(*pack->entities) * pack->max_entities);
|
||||
memset(pack->entities, 0, sizeof(entity_state_t) * pack->max_entities);
|
||||
}
|
||||
}
|
||||
else
|
||||
pack = &frame->entities;
|
||||
SV_Snapshot_Clear(pack);
|
||||
|
||||
// send over the players in the PVS
|
||||
if (svs.gametype != GT_HALFLIFE)
|
||||
SV_WritePlayersToClient (client, frame, clent, pvs, msg);
|
||||
|
||||
// put other visible entities into either a packet_entities or a nails message
|
||||
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
|
@ -2749,7 +3189,41 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
// encode the packet entities as a delta from the
|
||||
// last packetentities acknowledged by the client
|
||||
|
||||
SV_EmitPacketEntities (client, pack, msg);
|
||||
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
|
||||
{
|
||||
SVFTE_EmitPacketEntities(client, pack, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Z_EXT_TIME protocol extension
|
||||
// every now and then, send an update so that extrapolation
|
||||
// on client side doesn't stray too far off
|
||||
if (ISQWCLIENT(client))
|
||||
{
|
||||
if (client->fteprotocolextensions & PEXT_ACCURATETIMINGS && sv.world.physicstime - client->nextservertimeupdate > 0)
|
||||
{ //the fte pext causes the server to send out accurate timings, allowing for perfect interpolation.
|
||||
MSG_WriteByte (msg, svc_updatestatlong);
|
||||
MSG_WriteByte (msg, STAT_TIME);
|
||||
MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000));
|
||||
|
||||
client->nextservertimeupdate = sv.world.physicstime;//+10;
|
||||
}
|
||||
else if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.world.physicstime - client->nextservertimeupdate > 0)
|
||||
{ //the zquake ext causes the server to send out peridoic timings, allowing for moderatly accurate game time.
|
||||
MSG_WriteByte (msg, svc_updatestatlong);
|
||||
MSG_WriteByte (msg, STAT_TIME);
|
||||
MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000));
|
||||
|
||||
client->nextservertimeupdate = sv.world.physicstime+10;
|
||||
}
|
||||
}
|
||||
|
||||
// send over the players in the PVS
|
||||
if (svs.gametype != GT_HALFLIFE)
|
||||
SV_WritePlayersToClient (client, frame, clent, pvs, msg);
|
||||
|
||||
SVQW_EmitPacketEntities (client, pack, msg);
|
||||
}
|
||||
|
||||
SV_EmitCSQCUpdate(client, msg);
|
||||
|
||||
|
|
|
@ -256,6 +256,9 @@ void SV_EdictToEntState (int num, edict_t *ent, entity_state_t *state)
|
|||
if (/*progstype == PROG_H2 &&*/ ent->v->solid == SOLID_BSP)
|
||||
state->angles[0]*=-1;
|
||||
|
||||
if (ent->v->solid == SOLID_BSP)
|
||||
state->solid = ES_SOLID_BSP;
|
||||
|
||||
if (state->effects & EF_FULLBRIGHT)
|
||||
{
|
||||
state->hexen2flags |= MLS_FULLBRIGHT;
|
||||
|
@ -296,6 +299,7 @@ void SVNQ_CreateBaseline (void)
|
|||
{
|
||||
edict_t *svent;
|
||||
int entnum;
|
||||
extern entity_state_t nullentitystate;
|
||||
|
||||
int playermodel = SV_SafeModelIndex("progs/player.mdl");
|
||||
|
||||
|
@ -303,16 +307,9 @@ void SVNQ_CreateBaseline (void)
|
|||
{
|
||||
svent = EDICT_NUM(svprogfuncs, entnum);
|
||||
|
||||
memset(&svent->baseline, 0, sizeof(entity_state_t));
|
||||
memcpy(&svent->baseline, &nullentitystate, sizeof(entity_state_t));
|
||||
svent->baseline.number = entnum;
|
||||
|
||||
#ifdef PEXT_SCALE
|
||||
svent->baseline.scale = 1*16;
|
||||
#endif
|
||||
#ifdef PEXT_TRANS
|
||||
svent->baseline.trans = 255;
|
||||
#endif
|
||||
|
||||
if (svent->isfree)
|
||||
continue;
|
||||
// create baselines for all player slots,
|
||||
|
@ -616,6 +613,7 @@ void SV_UnspawnServer (void) //terminate the running server.
|
|||
*svs.clients[i].namebuf = '\0';
|
||||
svs.clients[i].name = NULL;
|
||||
}
|
||||
SV_FlushLevelCache();
|
||||
NET_CloseServer ();
|
||||
}
|
||||
|
||||
|
@ -836,7 +834,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
Info_SetValueForStarKey(svs.info, "*gamespeed", "", MAX_SERVERINFO_STRING);
|
||||
}
|
||||
//reset the server time.
|
||||
sv.time = 0.1; //some progs don't like time starting at 0.
|
||||
sv.time = 0.01; //some progs don't like time starting at 0.
|
||||
//cos of spawn funcs like self.nextthink = time...
|
||||
//NQ uses 1, QW uses 0. Awkward.
|
||||
sv.starttime = Sys_DoubleTime();
|
||||
|
@ -1098,6 +1096,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
{
|
||||
svs.clients[i].edict = NULL;
|
||||
svs.clients[i].name = svs.clients[i].namebuf;
|
||||
svs.clients[i].team = svs.clients[i].teambuf;
|
||||
}
|
||||
|
|
|
@ -596,6 +596,11 @@ void SV_DropClient (client_t *drop)
|
|||
Z_Free(drop->frameunion.frames);
|
||||
drop->frameunion.frames = NULL;
|
||||
}
|
||||
if (drop->sentents.entities)
|
||||
{
|
||||
Z_Free(drop->sentents.entities);
|
||||
memset(&drop->sentents.entities, 0, sizeof(drop->sentents.entities));
|
||||
}
|
||||
|
||||
if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) //gamecode should do it all for us.
|
||||
{
|
||||
|
@ -1380,30 +1385,45 @@ void SVC_GetChallenge (void)
|
|||
if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM)
|
||||
{
|
||||
#ifdef PROTOCOL_VERSION_FTE
|
||||
unsigned int mask;
|
||||
//tell the client what fte extensions we support
|
||||
if (svs.fteprotocolextensions)
|
||||
mask = Net_PextMask(1);
|
||||
if (mask)
|
||||
{
|
||||
lng = LittleLong(PROTOCOL_VERSION_FTE);
|
||||
memcpy(over, &lng, sizeof(lng));
|
||||
over+=sizeof(lng);
|
||||
|
||||
lng = LittleLong(svs.fteprotocolextensions);
|
||||
lng = LittleLong(mask);
|
||||
memcpy(over, &lng, sizeof(lng));
|
||||
over+=sizeof(lng);
|
||||
}
|
||||
//tell the client what fte extensions we support
|
||||
if (svs.fteprotocolextensions2)
|
||||
mask = Net_PextMask(2);
|
||||
if (mask)
|
||||
{
|
||||
lng = LittleLong(PROTOCOL_VERSION_FTE2);
|
||||
memcpy(over, &lng, sizeof(lng));
|
||||
over+=sizeof(lng);
|
||||
|
||||
lng = LittleLong(svs.fteprotocolextensions2);
|
||||
lng = LittleLong(mask);
|
||||
memcpy(over, &lng, sizeof(lng));
|
||||
over+=sizeof(lng);
|
||||
}
|
||||
#endif
|
||||
|
||||
mask = net_mtu.ival&~7;
|
||||
if (mask > 64)
|
||||
{
|
||||
lng = LittleLong(PROTOCOL_VERSION_FRAGMENT);
|
||||
memcpy(over, &lng, sizeof(lng));
|
||||
over+=sizeof(lng);
|
||||
|
||||
lng = LittleLong(mask);
|
||||
memcpy(over, &lng, sizeof(lng));
|
||||
over+=sizeof(lng);
|
||||
}
|
||||
|
||||
#ifdef HUFFNETWORK
|
||||
compressioncrc = Huff_PreferedCompressionCRC();
|
||||
if (compressioncrc)
|
||||
|
@ -1674,6 +1694,7 @@ client_t *SVC_DirectConnect(void)
|
|||
int version;
|
||||
int challenge;
|
||||
int huffcrc = 0;
|
||||
int mtu = 0;
|
||||
char guid[128] = "";
|
||||
char basic[80];
|
||||
qboolean redirect = false;
|
||||
|
@ -1823,33 +1844,48 @@ client_t *SVC_DirectConnect(void)
|
|||
Con_Printf ("* rejected connect from quakeworld\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while(!msg_badread)
|
||||
|
||||
while(!msg_badread)
|
||||
{
|
||||
Cmd_TokenizeString(MSG_ReadStringLine(), false, false);
|
||||
switch(Q_atoi(Cmd_Argv(0)))
|
||||
{
|
||||
Cmd_TokenizeString(MSG_ReadStringLine(), false, false);
|
||||
switch(Q_atoi(Cmd_Argv(0)))
|
||||
case PROTOCOL_VERSION_FTE:
|
||||
if (protocol == SCP_QUAKEWORLD)
|
||||
{
|
||||
case PROTOCOL_VERSION_FTE:
|
||||
protextsupported = Q_atoi(Cmd_Argv(1));
|
||||
Con_DPrintf("Client supports 0x%x fte extensions\n", protextsupported);
|
||||
break;
|
||||
case PROTOCOL_VERSION_FTE2:
|
||||
}
|
||||
break;
|
||||
case PROTOCOL_VERSION_FTE2:
|
||||
if (protocol == SCP_QUAKEWORLD)
|
||||
{
|
||||
protextsupported2 = Q_atoi(Cmd_Argv(1));
|
||||
Con_DPrintf("Client supports 0x%x fte2 extensions\n", protextsupported2);
|
||||
break;
|
||||
case PROTOCOL_VERSION_HUFFMAN:
|
||||
huffcrc = Q_atoi(Cmd_Argv(1));
|
||||
Con_DPrintf("Client supports huffman compression. crc 0x%x\n", huffcrc);
|
||||
break;
|
||||
case PROTOCOL_INFO_GUID:
|
||||
Q_strncpyz(guid, Cmd_Argv(1), sizeof(guid));
|
||||
Con_DPrintf("GUID %s\n", Cmd_Argv(1));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PROTOCOL_VERSION_HUFFMAN:
|
||||
huffcrc = Q_atoi(Cmd_Argv(1));
|
||||
Con_DPrintf("Client supports huffman compression. crc 0x%x\n", huffcrc);
|
||||
break;
|
||||
case PROTOCOL_VERSION_FRAGMENT:
|
||||
mtu = Q_atoi(Cmd_Argv(1)) & ~7;
|
||||
if (mtu < 64)
|
||||
mtu = 64;
|
||||
Con_DPrintf("Client supports fragmentation. mtu %i.\n", mtu);
|
||||
break;
|
||||
case PROTOCOL_INFO_GUID:
|
||||
Q_strncpyz(guid, Cmd_Argv(1), sizeof(guid));
|
||||
Con_DPrintf("GUID %s\n", Cmd_Argv(1));
|
||||
break;
|
||||
}
|
||||
msg_badread=false;
|
||||
}
|
||||
msg_badread=false;
|
||||
|
||||
|
||||
|
||||
if (protextsupported & PEXT_256PACKETENTITIES)
|
||||
maxpacketentities = MAX_EXTENDED_PACKET_ENTITIES;
|
||||
|
@ -2230,11 +2266,23 @@ client_t *SVC_DirectConnect(void)
|
|||
Z_Free(temp.frameunion.frames);
|
||||
}
|
||||
|
||||
temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP);
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
if ((temp.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))// || ISDPCLIENT(&temp))
|
||||
{
|
||||
temp.frameunion.frames[i].entities.max_entities = maxpacketentities;
|
||||
temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities;
|
||||
temp.frameunion.frames = Z_Malloc(sizeof(client_frame_t)*UPDATE_BACKUP+sizeof(unsigned int)*temp.max_net_ents*UPDATE_BACKUP + sizeof(unsigned int)*temp.max_net_ents);
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
{
|
||||
temp.frameunion.frames[i].resendentbits = (unsigned int*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.max_net_ents;
|
||||
}
|
||||
temp.pendingentbits = (unsigned int*)(temp.frameunion.frames+UPDATE_BACKUP) + UPDATE_BACKUP*temp.max_net_ents;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP);
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
{
|
||||
temp.frameunion.frames[i].entities.max_entities = maxpacketentities;
|
||||
temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2263,6 +2311,8 @@ client_t *SVC_DirectConnect(void)
|
|||
newcl->netchan.compress = true;
|
||||
else
|
||||
newcl->netchan.compress = false;
|
||||
if (mtu >= 0)
|
||||
newcl->netchan.fragmentsize = mtu;
|
||||
|
||||
newcl->protocol = protocol;
|
||||
#ifdef NQPROT
|
||||
|
@ -3257,20 +3307,40 @@ qboolean SV_ReadPackets (float *delay)
|
|||
|
||||
net_from = cl->netchan.remote_address; //not sure if anything depends on this, but lets not screw them up willynilly
|
||||
|
||||
if (Netchan_Process(&cl->netchan))
|
||||
{ // this is a valid, sequenced packet, so process it
|
||||
received++;
|
||||
svs.stats.packets++;
|
||||
if (cl->state > cs_zombie)
|
||||
{ //make sure they didn't already disconnect
|
||||
cl->send_message = true; // reply at end of frame
|
||||
if (ISNQCLIENT(cl))
|
||||
{
|
||||
if (cl->state != cs_zombie)
|
||||
{
|
||||
if (NQNetChan_Process(&cl->netchan))
|
||||
{
|
||||
received++;
|
||||
svs.stats.packets++;
|
||||
SVNQ_ExecuteClientMessage(cl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*QW*/
|
||||
if (Netchan_Process(&cl->netchan))
|
||||
{ // this is a valid, sequenced packet, so process it
|
||||
received++;
|
||||
svs.stats.packets++;
|
||||
if (cl->state > cs_zombie)
|
||||
{ //make sure they didn't already disconnect
|
||||
if (cl->send_message)
|
||||
cl->chokecount++;
|
||||
else
|
||||
cl->send_message = true; // reply at end of frame
|
||||
|
||||
#ifdef Q2SERVER
|
||||
if (cl->protocol == SCP_QUAKE2)
|
||||
SVQ2_ExecuteClientMessage(cl);
|
||||
else
|
||||
#endif
|
||||
SV_ExecuteClientMessage (cl);
|
||||
#ifdef Q2SERVER
|
||||
if (cl->protocol == SCP_QUAKE2)
|
||||
SVQ2_ExecuteClientMessage(cl);
|
||||
else
|
||||
#endif
|
||||
SV_ExecuteClientMessage (cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3328,6 +3398,9 @@ qboolean SV_ReadPackets (float *delay)
|
|||
{
|
||||
if (cl->state != cs_zombie)
|
||||
{
|
||||
if (cl->delay > 0)
|
||||
goto dominping;
|
||||
|
||||
if (NQNetChan_Process(&cl->netchan))
|
||||
{
|
||||
received++;
|
||||
|
@ -3341,17 +3414,7 @@ qboolean SV_ReadPackets (float *delay)
|
|||
|
||||
#ifdef Q3SERVER
|
||||
if (ISQ3CLIENT(cl))
|
||||
{
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("qwoverq3: fixme: this will block qw+q3 clients from the same ip")
|
||||
#endif
|
||||
if (cl->state != cs_zombie)
|
||||
{
|
||||
received++;
|
||||
SVQ3_HandleClient();
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (cl->netchan.qport != qport)
|
||||
|
@ -3364,6 +3427,7 @@ qboolean SV_ReadPackets (float *delay)
|
|||
|
||||
if (cl->delay > 0)
|
||||
{
|
||||
dominping:
|
||||
if (cl->state == cs_zombie)
|
||||
break;
|
||||
if (net_message.cursize > sizeof(svs.free_lagged_packet->data))
|
||||
|
@ -3414,6 +3478,14 @@ qboolean SV_ReadPackets (float *delay)
|
|||
if (i != MAX_CLIENTS)
|
||||
continue;
|
||||
|
||||
#ifdef Q3SERVER
|
||||
if (sv_listen_q3.ival && SVQ3_HandleClient())
|
||||
{
|
||||
received++;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NQPROT
|
||||
SVNQ_ConnectionlessPacket();
|
||||
#endif
|
||||
|
@ -4077,88 +4149,6 @@ void SV_InitLocal (void)
|
|||
for (i=0 ; i<MAX_MODELS ; i++)
|
||||
sprintf (localmodels[i], "*%i", i);
|
||||
|
||||
#ifdef PEXT_SCALE
|
||||
svs.fteprotocolextensions |= PEXT_SCALE;
|
||||
#endif
|
||||
#ifdef PEXT_LIGHTSTYLECOL
|
||||
svs.fteprotocolextensions |= PEXT_LIGHTSTYLECOL;
|
||||
#endif
|
||||
#ifdef PEXT_TRANS
|
||||
svs.fteprotocolextensions |= PEXT_TRANS;
|
||||
#endif
|
||||
#ifdef PEXT_VIEW2
|
||||
svs.fteprotocolextensions |= PEXT_VIEW2;
|
||||
#endif
|
||||
svs.fteprotocolextensions |= PEXT_ACCURATETIMINGS;
|
||||
#ifdef PEXT_ZLIBDL
|
||||
svs.fteprotocolextensions |= PEXT_ZLIBDL;
|
||||
#endif
|
||||
#ifdef PEXT_FATNESS
|
||||
svs.fteprotocolextensions |= PEXT_FATNESS;
|
||||
#endif
|
||||
#ifdef PEXT_HLBSP
|
||||
svs.fteprotocolextensions |= PEXT_HLBSP;
|
||||
#endif
|
||||
#ifdef PEXT_Q2BSP
|
||||
svs.fteprotocolextensions |= PEXT_Q2BSP;
|
||||
#endif
|
||||
#ifdef PEXT_Q3BSP
|
||||
svs.fteprotocolextensions |= PEXT_Q3BSP;
|
||||
#endif
|
||||
#ifdef PEXT_TE_BULLET
|
||||
svs.fteprotocolextensions |= PEXT_TE_BULLET;
|
||||
#endif
|
||||
#ifdef PEXT_HULLSIZE
|
||||
svs.fteprotocolextensions |= PEXT_HULLSIZE;
|
||||
#endif
|
||||
#ifdef PEXT_SETVIEW
|
||||
svs.fteprotocolextensions |= PEXT_SETVIEW;
|
||||
#endif
|
||||
#ifdef PEXT_MODELDBL
|
||||
svs.fteprotocolextensions |= PEXT_MODELDBL;
|
||||
#endif
|
||||
#ifdef PEXT_SOUNDDBL
|
||||
svs.fteprotocolextensions |= PEXT_SOUNDDBL;
|
||||
#endif
|
||||
#ifdef PEXT_FLOATCOORDS
|
||||
svs.fteprotocolextensions |= PEXT_FLOATCOORDS;
|
||||
#endif
|
||||
svs.fteprotocolextensions |= PEXT_SPLITSCREEN;
|
||||
svs.fteprotocolextensions |= PEXT_HEXEN2;
|
||||
svs.fteprotocolextensions |= PEXT_COLOURMOD;
|
||||
svs.fteprotocolextensions |= PEXT_SPAWNSTATIC2;
|
||||
svs.fteprotocolextensions |= PEXT_CUSTOMTEMPEFFECTS;
|
||||
svs.fteprotocolextensions |= PEXT_256PACKETENTITIES;
|
||||
svs.fteprotocolextensions |= PEXT_ENTITYDBL;
|
||||
svs.fteprotocolextensions |= PEXT_ENTITYDBL2;
|
||||
// svs.fteprotocolextensions |= PEXT_64PLAYERS;
|
||||
svs.fteprotocolextensions |= PEXT_SHOWPIC;
|
||||
svs.fteprotocolextensions |= PEXT_SETATTACHMENT;
|
||||
|
||||
#ifdef PEXT_PK3DOWNLOADS
|
||||
svs.fteprotocolextensions |= PEXT_PK3DOWNLOADS;
|
||||
#endif
|
||||
|
||||
#ifdef PEXT_CHUNKEDDOWNLOADS
|
||||
svs.fteprotocolextensions |= PEXT_CHUNKEDDOWNLOADS;
|
||||
#endif
|
||||
|
||||
#ifdef PEXT_CSQC
|
||||
svs.fteprotocolextensions |= PEXT_CSQC;
|
||||
#endif
|
||||
#ifdef PEXT_DPFLAGS
|
||||
svs.fteprotocolextensions |= PEXT_DPFLAGS;
|
||||
#endif
|
||||
|
||||
svs.fteprotocolextensions2 |= PEXT2_PRYDONCURSOR;
|
||||
#ifdef VOICECHAT
|
||||
svs.fteprotocolextensions2 |= PEXT2_VOICECHAT;
|
||||
#endif
|
||||
svs.fteprotocolextensions2 |= PEXT2_SETANGLEDELTA;
|
||||
|
||||
// if (svs.protocolextensions)
|
||||
// Info_SetValueForStarKey (svs.info, "*"DISTRIBUTION"_ext", va("%x", svs.protocolextensions), MAX_SERVERINFO_STRING);
|
||||
|
||||
Info_SetValueForStarKey (svs.info, "*version", version_string(), MAX_SERVERINFO_STRING);
|
||||
|
||||
Info_SetValueForStarKey (svs.info, "*z_ext", va("%i", SUPPORTED_Z_EXTENSIONS), MAX_SERVERINFO_STRING);
|
||||
|
@ -4176,10 +4166,7 @@ void SV_InitLocal (void)
|
|||
svs.log[1].allowoverflow = true;
|
||||
|
||||
|
||||
svs.free_lagged_packet = Hunk_Alloc(1024*sizeof(*svs.free_lagged_packet));
|
||||
for (i = 0; i < 1024-1; i++)
|
||||
svs.free_lagged_packet[i].next = &svs.free_lagged_packet[i+1];
|
||||
svs.free_lagged_packet[i].next = 0;
|
||||
svs.free_lagged_packet = NULL;
|
||||
|
||||
// parse params for cvars
|
||||
p = COM_CheckParm ("-port");
|
||||
|
|
|
@ -1748,6 +1748,8 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
|
|||
MSG_WriteLong (&buf, svs.spawncount);
|
||||
MSG_WriteString (&buf, gamedir);
|
||||
|
||||
if (demo.recorder.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
|
||||
MSG_WriteByte(&buf, MAX_CLIENTS);
|
||||
|
||||
MSG_WriteFloat (&buf, sv.time);
|
||||
|
||||
|
@ -1875,7 +1877,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
|
|||
else if (demo.recorder.fteprotocolextensions & PEXT_SPAWNSTATIC2)
|
||||
{
|
||||
MSG_WriteByte(&buf, svcfte_spawnbaseline2);
|
||||
SV_WriteDelta(&from, state, &buf, true, demo.recorder.fteprotocolextensions);
|
||||
SVQW_WriteDelta(&from, state, &buf, true, demo.recorder.fteprotocolextensions);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -24,11 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "pr_common.h"
|
||||
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("fixme, fix this up before adding to csqc")
|
||||
#endif
|
||||
extern globalptrs_t realpr_global_ptrs;
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
@ -444,16 +439,11 @@ SV_AddGravity
|
|||
|
||||
============
|
||||
*/
|
||||
static void WPhys_AddGravity (wedict_t *ent, float scale)
|
||||
static void WPhys_AddGravity (world_t *w, wedict_t *ent, float scale)
|
||||
{
|
||||
if (!scale
|
||||
#ifndef CLIENTONLY
|
||||
#pragma warningmsg("This doesn't do csqc properly")
|
||||
&& progstype != PROG_QW
|
||||
#endif
|
||||
)
|
||||
scale = 1;
|
||||
ent->v->velocity[2] -= scale * sv_gravity.value/*movevars.gravity*/ * host_frametime;
|
||||
if (!scale)
|
||||
scale = w->defaultgravityscale;
|
||||
ent->v->velocity[2] -= scale * movevars.gravity * host_frametime;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -537,7 +527,7 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
|
|||
int i, e;
|
||||
wedict_t *check, *block;
|
||||
vec3_t mins, maxs;
|
||||
float oldsolid;
|
||||
//float oldsolid;
|
||||
pushed_t *p;
|
||||
vec3_t org, org2, move2, forward, right, up;
|
||||
|
||||
|
@ -577,14 +567,14 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
|
|||
|| check->v->movetype == MOVETYPE_NOCLIP
|
||||
|| check->v->movetype == MOVETYPE_ANGLENOCLIP)
|
||||
continue;
|
||||
|
||||
/*
|
||||
oldsolid = pusher->v->solid;
|
||||
pusher->v->solid = SOLID_NOT;
|
||||
block = World_TestEntityPosition (w, check);
|
||||
pusher->v->solid = oldsolid;
|
||||
if (block)
|
||||
continue;
|
||||
|
||||
*/
|
||||
// if the entity is standing on the pusher, it will definitely be moved
|
||||
if ( ! ( ((int)check->v->flags & FL_ONGROUND)
|
||||
&& PROG_TO_WEDICT(w->progs, check->v->groundentity) == pusher) )
|
||||
|
@ -1103,15 +1093,16 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
|
|||
&& ent->v->movetype != MOVETYPE_FLYMISSILE
|
||||
&& ent->v->movetype != MOVETYPE_BOUNCEMISSILE
|
||||
&& ent->v->movetype != MOVETYPE_H2SWIM)
|
||||
WPhys_AddGravity (ent, 1.0);
|
||||
WPhys_AddGravity (w, ent, 1.0);
|
||||
|
||||
// move angles
|
||||
VectorMA (ent->v->angles, host_frametime, ent->v->avelocity, ent->v->angles);
|
||||
|
||||
// move origin
|
||||
VectorScale (ent->v->velocity, host_frametime, move);
|
||||
if (!DotProduct(move, move))
|
||||
return;
|
||||
VectorCopy(ent->v->origin, temporg);
|
||||
VectorCopy(temporg, ent->v->origin);
|
||||
|
||||
fl = 0;
|
||||
#ifndef CLIENTONLY
|
||||
|
@ -1123,7 +1114,14 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
|
|||
trace = WPhys_PushEntity (w, ent, move, fl);
|
||||
|
||||
if (trace.allsolid)
|
||||
{
|
||||
trace.fraction = 0;
|
||||
|
||||
#pragma warningmsg("These three lines might help boost framerates a lot in rmq, not sure if they violate expected behaviour in other mods though - check that they're safe.")
|
||||
trace.plane.normal[0] = 0;
|
||||
trace.plane.normal[1] = 0;
|
||||
trace.plane.normal[2] = 1;
|
||||
}
|
||||
if (trace.fraction == 1)
|
||||
return;
|
||||
if (ent->isfree)
|
||||
|
@ -1206,7 +1204,7 @@ static void WPhys_Physics_Step (world_t *w, wedict_t *ent)
|
|||
{
|
||||
hitsound = ent->v->velocity[2] < movevars.gravity*-0.1;
|
||||
|
||||
WPhys_AddGravity (ent, 1.0);
|
||||
WPhys_AddGravity (w, ent, 1.0);
|
||||
WPhys_CheckVelocity (w, ent);
|
||||
WPhys_FlyMove (w, ent, host_frametime, NULL);
|
||||
World_LinkEdict (w, ent, true);
|
||||
|
@ -1897,7 +1895,7 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
|
|||
if (!WPhys_RunThink (w, ent))
|
||||
return;
|
||||
if (!WPhys_CheckWater (w, ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
|
||||
WPhys_AddGravity (ent, ent->xv->gravity);
|
||||
WPhys_AddGravity (w, ent, ent->xv->gravity);
|
||||
WPhys_CheckStuck (w, ent);
|
||||
|
||||
WPhys_WalkMove (w, ent);
|
||||
|
@ -2093,6 +2091,8 @@ qboolean SV_Physics (void)
|
|||
qboolean moved = false;
|
||||
int maxtics;
|
||||
|
||||
//keep gravity tracking the cvar properly
|
||||
movevars.gravity = sv_gravity.value;
|
||||
|
||||
if (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM && svs.gametype != GT_HALFLIFE) //make tics multiples of sv_maxtic (defaults to 0.1)
|
||||
{
|
||||
|
@ -2265,7 +2265,6 @@ qboolean SV_Physics (void)
|
|||
|
||||
void SV_SetMoveVars(void)
|
||||
{
|
||||
movevars.gravity = sv_gravity.value;
|
||||
movevars.stopspeed = sv_stopspeed.value;
|
||||
movevars.maxspeed = sv_maxspeed.value;
|
||||
movevars.spectatormaxspeed = sv_spectatormaxspeed.value;
|
||||
|
|
|
@ -1090,7 +1090,7 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
|
|||
MSG_WriteByte(msg, svcfte_choosesplitclient);
|
||||
MSG_WriteByte(msg, pnum);
|
||||
}
|
||||
if (client->fteprotocolextensions2 & PEXT2_SETANGLEDELTA && client->delta_sequence != -1)
|
||||
if (!client->lockangles && (client->fteprotocolextensions2 & PEXT2_SETANGLEDELTA) && client->delta_sequence != -1)
|
||||
{
|
||||
MSG_WriteByte (msg, svcfte_setangledelta);
|
||||
for (i=0 ; i < 3 ; i++)
|
||||
|
@ -1107,7 +1107,10 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
|
|||
MSG_WriteAngle (msg, ent->v->angles[i]);
|
||||
}
|
||||
ent->v->fixangle = 0;
|
||||
client->lockangles = true;
|
||||
}
|
||||
else
|
||||
client->lockangles = false;
|
||||
}
|
||||
|
||||
/*sends the a centerprint string directly to the client*/
|
||||
|
@ -1160,13 +1163,6 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
|
|||
client_t *split;
|
||||
int pnum=0;
|
||||
|
||||
if (client->centerprintstring && ! client->num_backbuf)
|
||||
{
|
||||
SV_WriteCenterPrint(client, client->centerprintstring);
|
||||
Z_Free(client->centerprintstring);
|
||||
client->centerprintstring = NULL;
|
||||
}
|
||||
|
||||
// send the chokecount for r_netgraph
|
||||
if (ISQWCLIENT(client))
|
||||
if (client->chokecount)
|
||||
|
@ -1177,34 +1173,21 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
|
|||
}
|
||||
|
||||
for (split = client; split; split=split->controlled, pnum++)
|
||||
{
|
||||
SV_WriteEntityDataToMessage(split, msg, pnum);
|
||||
|
||||
if (split->centerprintstring && ! client->num_backbuf)
|
||||
{
|
||||
SV_WriteCenterPrint(split, split->centerprintstring);
|
||||
Z_Free(split->centerprintstring);
|
||||
split->centerprintstring = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
MSG_WriteByte (msg, svc_time);
|
||||
MSG_WriteFloat(msg, sv.physicstime);
|
||||
client->nextservertimeupdate = sv.physicstime;
|
||||
*/
|
||||
// Z_EXT_TIME protocol extension
|
||||
// every now and then, send an update so that extrapolation
|
||||
// on client side doesn't stray too far off
|
||||
if (ISQWCLIENT(client))
|
||||
{
|
||||
if (client->fteprotocolextensions & PEXT_ACCURATETIMINGS && sv.world.physicstime - client->nextservertimeupdate > 0)
|
||||
{ //the fte pext causes the server to send out accurate timings, allowing for perfect interpolation.
|
||||
MSG_WriteByte (msg, svc_updatestatlong);
|
||||
MSG_WriteByte (msg, STAT_TIME);
|
||||
MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000));
|
||||
|
||||
client->nextservertimeupdate = sv.world.physicstime;//+10;
|
||||
}
|
||||
else if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.world.physicstime - client->nextservertimeupdate > 0)
|
||||
{ //the zquake ext causes the server to send out peridoic timings, allowing for moderatly accurate game time.
|
||||
MSG_WriteByte (msg, svc_updatestatlong);
|
||||
MSG_WriteByte (msg, STAT_TIME);
|
||||
MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000));
|
||||
|
||||
client->nextservertimeupdate = sv.world.physicstime+10;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NQPROT
|
||||
if (ISQWCLIENT(client))
|
||||
|
@ -1548,9 +1531,9 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
|
|||
statsf[STAT_CELLS] = ent->v->ammo_cells;
|
||||
if (!client->spectator)
|
||||
{
|
||||
statsi[STAT_ACTIVEWEAPON] = ent->v->weapon;
|
||||
statsf[STAT_ACTIVEWEAPON] = ent->v->weapon;
|
||||
if (client->csqcactive || client->protocol != SCP_QUAKEWORLD)
|
||||
statsi[STAT_WEAPONFRAME] = ent->v->weaponframe;
|
||||
statsf[STAT_WEAPONFRAME] = ent->v->weaponframe;
|
||||
}
|
||||
|
||||
// stuff the sigil bits into the high bits of items for sbar
|
||||
|
@ -1574,6 +1557,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
|
|||
|
||||
if (client->protocol == SCP_DARKPLACES7)
|
||||
{
|
||||
/*note: statsf is truncated, which would mess things up*/
|
||||
float *statsfi = (float*)statsi;
|
||||
// statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall
|
||||
statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value;
|
||||
|
@ -1789,7 +1773,7 @@ SV_SendClientDatagram
|
|||
*/
|
||||
qboolean SV_SendClientDatagram (client_t *client)
|
||||
{
|
||||
qbyte buf[MAX_DATAGRAM];
|
||||
qbyte buf[MAX_OVERALLMSGLEN];
|
||||
sizebuf_t msg;
|
||||
unsigned int sentbytes, fnum;
|
||||
|
||||
|
@ -1800,15 +1784,18 @@ qboolean SV_SendClientDatagram (client_t *client)
|
|||
msg.overflowed = false;
|
||||
msg.prim = client->datagram.prim;
|
||||
|
||||
if (!client->netchan.fragmentsize)
|
||||
msg.maxsize = MAX_DATAGRAM;
|
||||
|
||||
if (sv.world.worldmodel && !client->controller)
|
||||
{
|
||||
if (ISQ2CLIENT(client))
|
||||
{
|
||||
SV_BuildClientFrame (client);
|
||||
SVQ2_BuildClientFrame (client);
|
||||
|
||||
// send over all the relevant entity_state_t
|
||||
// and the player_state_t
|
||||
SV_WriteFrameToClient (client, &msg);
|
||||
SVQ2_WriteFrameToClient (client, &msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2306,9 +2293,9 @@ void SV_SendClientMessages (void)
|
|||
SZ_Clear (&c->datagram);
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
|
||||
Con_Printf ("WARNING: reliable overflow for %s\n",c->name);
|
||||
SV_DropClient (c);
|
||||
c->send_message = true;
|
||||
c->netchan.cleartime = 0; // don't choke this message
|
||||
SV_DropClient (c);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ cvar_t sv_antilag_frac = CVARF("sv_antilag_frac", "1", CVAR_SERVERINFO);
|
|||
cvar_t sv_cheatpc = CVAR("sv_cheatpc", "125");
|
||||
cvar_t sv_cheatspeedchecktime = CVAR("sv_cheatspeedchecktime", "30");
|
||||
cvar_t sv_playermodelchecks = CVAR("sv_playermodelchecks", "0");
|
||||
cvar_t sv_ping_ignorepl = CVARD("sv_ping_ignorepl", "0", "If 1, ping times reported for players will ignore the effects of packetloss on ping times. 0 is slightly more honest, but less useful for connection diagnosis.");
|
||||
|
||||
cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password.
|
||||
cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server.
|
||||
|
@ -289,52 +290,77 @@ void SV_New_f (void)
|
|||
ClientReliableWrite_Byte (host_client, 0);
|
||||
ClientReliableWrite_String (host_client, gamedir);
|
||||
|
||||
splitnum = 0;
|
||||
for (split = host_client; split; split = split->controlled)
|
||||
if (host_client->fteprotocolextensions2 & PEXT2_MAXPLAYERS)
|
||||
{
|
||||
switch(svs.gametype)
|
||||
/*is this a sane way to do it? or should we split the spectator thing off entirely?*/
|
||||
ClientReliableWrite_Byte (host_client, sv.allocated_client_slots);
|
||||
splitnum = 0;
|
||||
for (split = host_client, splitnum = 0; split; split = split->controlled)
|
||||
splitnum++;
|
||||
ClientReliableWrite_Byte (host_client, (split->spectator?128:0) | splitnum);
|
||||
for (split = host_client; split; split = split->controlled)
|
||||
{
|
||||
#ifdef HLSERVER
|
||||
case GT_HALFLIFE:
|
||||
playernum = split - svs.clients;
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q2SERVER
|
||||
case GT_QUAKE2:
|
||||
playernum = Q2NUM_FOR_EDICT(split->q2edict)-1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
playernum = NUM_FOR_EDICT(svprogfuncs, split->edict)-1;
|
||||
}
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
if (sv.demostate)
|
||||
{
|
||||
playernum = (MAX_CLIENTS-1-splitnum)|128;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (split->spectator)
|
||||
playernum |= 128;
|
||||
|
||||
if (sv.state == ss_cinematic)
|
||||
playernum = -1;
|
||||
|
||||
if (ISQ2CLIENT(host_client))
|
||||
ClientReliableWrite_Short (host_client, playernum);
|
||||
else
|
||||
if (sv.state == ss_cinematic)
|
||||
playernum = -1;
|
||||
ClientReliableWrite_Byte (host_client, playernum);
|
||||
|
||||
split->state = cs_connected;
|
||||
split->connection_started = realtime;
|
||||
#ifdef SVRANKING
|
||||
split->stats_started = realtime;
|
||||
#endif
|
||||
splitnum++;
|
||||
split->state = cs_connected;
|
||||
split->connection_started = realtime;
|
||||
#ifdef SVRANKING
|
||||
split->stats_started = realtime;
|
||||
splitnum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
splitnum = 0;
|
||||
for (split = host_client; split; split = split->controlled)
|
||||
{
|
||||
switch(svs.gametype)
|
||||
{
|
||||
#ifdef HLSERVER
|
||||
case GT_HALFLIFE:
|
||||
playernum = split - svs.clients;
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q2SERVER
|
||||
case GT_QUAKE2:
|
||||
playernum = Q2NUM_FOR_EDICT(split->q2edict)-1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
playernum = NUM_FOR_EDICT(svprogfuncs, split->edict)-1;
|
||||
}
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
if (sv.demostate)
|
||||
{
|
||||
playernum = (MAX_CLIENTS-1-splitnum)|128;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (split->spectator)
|
||||
playernum |= 128;
|
||||
|
||||
if (host_client->fteprotocolextensions & PEXT_SPLITSCREEN)
|
||||
ClientReliableWrite_Byte (host_client, 128);
|
||||
if (sv.state == ss_cinematic)
|
||||
playernum = -1;
|
||||
|
||||
if (ISQ2CLIENT(host_client))
|
||||
ClientReliableWrite_Short (host_client, playernum);
|
||||
else
|
||||
ClientReliableWrite_Byte (host_client, playernum);
|
||||
|
||||
split->state = cs_connected;
|
||||
split->connection_started = realtime;
|
||||
#ifdef SVRANKING
|
||||
split->stats_started = realtime;
|
||||
#endif
|
||||
splitnum++;
|
||||
}
|
||||
|
||||
if (host_client->fteprotocolextensions & PEXT_SPLITSCREEN)
|
||||
ClientReliableWrite_Byte (host_client, 128);
|
||||
}
|
||||
|
||||
// send full levelname
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
|
@ -1244,7 +1270,7 @@ void SVQW_PreSpawn_f (void)
|
|||
if (state->hexen2flags || state->trans || state->modelindex >= 256 || state->frame > 255 || state->scale || state->abslight)
|
||||
{
|
||||
MSG_WriteByte(&host_client->netchan.message, svc_spawnstatic2);
|
||||
SV_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions);
|
||||
SVQW_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1305,7 +1331,7 @@ void SVQW_PreSpawn_f (void)
|
|||
else if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2)
|
||||
{
|
||||
MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2);
|
||||
SV_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions);
|
||||
SVQW_WriteDelta(&from, state, &host_client->netchan.message, true, host_client->fteprotocolextensions);
|
||||
}
|
||||
else if (state->modelindex < 256)
|
||||
{
|
||||
|
@ -1601,6 +1627,7 @@ void SV_Begin_Core(client_t *split)
|
|||
|
||||
ge->ClientBegin(split->q2edict);
|
||||
split->istobeloaded = false;
|
||||
sv.spawned_client_slots++;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -4751,10 +4778,10 @@ void SV_Pext_f(void)
|
|||
switch(strtoul(tag, NULL, 0))
|
||||
{
|
||||
case PROTOCOL_VERSION_FTE:
|
||||
host_client->fteprotocolextensions = strtoul(val, NULL, 0) & svs.fteprotocolextensions;
|
||||
host_client->fteprotocolextensions = strtoul(val, NULL, 0) & Net_PextMask(1);
|
||||
break;
|
||||
case PROTOCOL_VERSION_FTE2:
|
||||
host_client->fteprotocolextensions2 = strtoul(val, NULL, 0) & svs.fteprotocolextensions2;
|
||||
host_client->fteprotocolextensions2 = strtoul(val, NULL, 0) & Net_PextMask(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5231,14 +5258,14 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
|
||||
if (check->v->owner == pl)
|
||||
continue; // player's own missile
|
||||
if (check->v->solid == SOLID_BSP
|
||||
if (check == player)
|
||||
continue;
|
||||
if ((check->v->solid == SOLID_TRIGGER && check->v->skin < 0) || check->v->solid == SOLID_BSP
|
||||
|| check->v->solid == SOLID_BBOX
|
||||
|| check->v->solid == SOLID_SLIDEBOX
|
||||
//|| (check->v->solid == SOLID_PHASEH2 && progstype == PROG_H2) //logically matches hexen2, but I hate it
|
||||
)
|
||||
{
|
||||
if (check == player)
|
||||
continue;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if (check->v->absmin[i] > pmove_maxs[i]
|
||||
|
@ -5259,6 +5286,28 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
|
||||
VectorCopy (check->v->origin, pe->origin);
|
||||
pe->info = NUM_FOR_EDICT(svprogfuncs, check);
|
||||
pe->nonsolid = check->v->solid == SOLID_TRIGGER;
|
||||
switch((int)check->v->skin)
|
||||
{
|
||||
case Q1CONTENTS_WATER:
|
||||
pe->forcecontentsmask = FTECONTENTS_WATER;
|
||||
break;
|
||||
case Q1CONTENTS_LAVA:
|
||||
pe->forcecontentsmask = FTECONTENTS_LAVA;
|
||||
break;
|
||||
case Q1CONTENTS_SLIME:
|
||||
pe->forcecontentsmask = FTECONTENTS_SLIME;
|
||||
break;
|
||||
case Q1CONTENTS_SKY:
|
||||
pe->forcecontentsmask = FTECONTENTS_SKY;
|
||||
break;
|
||||
case -16:
|
||||
pe->forcecontentsmask = FTECONTENTS_LADDER;
|
||||
break;
|
||||
default:
|
||||
pe->forcecontentsmask = 0;
|
||||
break;
|
||||
}
|
||||
if (check->v->solid == SOLID_BSP)
|
||||
{
|
||||
if(progstype != PROG_H2)
|
||||
|
@ -5709,7 +5758,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
|
|||
pmove.numphysent = 1;
|
||||
pmove.physents[0].model = sv.world.worldmodel;
|
||||
pmove.cmd = *ucmd;
|
||||
pmove.hullnum = SV_HullNumForPlayer(sv_player->xv->hull, sv_player->v->mins, sv_player->v->maxs);
|
||||
pmove.skipent = -1;
|
||||
|
||||
movevars.entgravity = host_client->entgravity/movevars.gravity;
|
||||
movevars.maxspeed = host_client->maxspeed;
|
||||
|
@ -6064,9 +6113,12 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
{ //split screen doesn't always have frames.
|
||||
frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
|
||||
|
||||
if (cl->lastsequence_acknoledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
|
||||
if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
|
||||
{
|
||||
frame->ping_time = realtime - frame->senttime; //no more phenomanally low pings please
|
||||
/*note that if there is packetloss, we can change a single frame's ping_time multiple times
|
||||
this means that the 'ping' is more latency than ping times*/
|
||||
if (frame->ping_time == -1 || !sv_ping_ignorepl.ival)
|
||||
frame->ping_time = realtime - frame->senttime; //no more phenomanally low pings please
|
||||
|
||||
if (cl->spectator)
|
||||
cl->delay = 0;
|
||||
|
@ -6087,15 +6139,18 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
}
|
||||
}
|
||||
#ifdef PEXT_CSQC
|
||||
if (cl->lastsequence_acknoledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
|
||||
if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
|
||||
{
|
||||
for (i = cl->lastsequence_acknoledged+1; i < cl->netchan.incoming_acknowledged; i++)
|
||||
for (i = cl->lastsequence_acknowledged+1; i < cl->netchan.incoming_acknowledged; i++)
|
||||
SV_CSQC_DroppedPacket(cl, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*too much loss, we don't know what was sent when, so reset the entire entity state*/
|
||||
SV_CSQC_DropAll(cl);
|
||||
}
|
||||
#endif
|
||||
cl->lastsequence_acknoledged = cl->netchan.incoming_acknowledged;
|
||||
cl->lastsequence_acknowledged = cl->netchan.incoming_acknowledged;
|
||||
|
||||
if (sv_antilag.ival)
|
||||
{
|
||||
|
@ -6137,6 +6192,7 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
// save time for ping calculations
|
||||
if (cl->frameunion.frames)
|
||||
{ //split screen doesn't always have frames.
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].sequence = cl->netchan.outgoing_sequence;
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
|
||||
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].move_msecs = -1;
|
||||
|
|
|
@ -1533,26 +1533,6 @@ extern vec3_t player_maxs;
|
|||
continue;
|
||||
|
||||
pe = &pmove.physents[pmove.numphysent];
|
||||
if (other->v.modelindex)
|
||||
{
|
||||
pe->model = sv.models[other->v.modelindex];
|
||||
if (pe->model && pe->model->type != mod_brush)
|
||||
pe->model = NULL;
|
||||
}
|
||||
else
|
||||
pe->model = NULL;
|
||||
pmove.numphysent++;
|
||||
pe->info = other - SVHL_Edict;
|
||||
VectorCopy(other->v.origin, pe->origin);
|
||||
VectorCopy(other->v.mins, pe->mins);
|
||||
VectorCopy(other->v.maxs, pe->maxs);
|
||||
VectorCopy(other->v.angles, pe->angles);
|
||||
|
||||
if (other->v.solid == SOLID_NOT || other->v.solid == SOLID_TRIGGER)
|
||||
pe->nonsolid = true;
|
||||
else
|
||||
pe->nonsolid = false;
|
||||
|
||||
switch(other->v.skin)
|
||||
{
|
||||
case Q1CONTENTS_EMPTY:
|
||||
|
@ -1580,6 +1560,30 @@ extern vec3_t player_maxs;
|
|||
pe->forcecontentsmask = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (other->v.solid == SOLID_NOT || other->v.solid == SOLID_TRIGGER)
|
||||
{
|
||||
if (!pe->forcecontentsmask)
|
||||
continue;
|
||||
pe->nonsolid = true;
|
||||
}
|
||||
else
|
||||
pe->nonsolid = false;
|
||||
|
||||
if (other->v.modelindex)
|
||||
{
|
||||
pe->model = sv.models[other->v.modelindex];
|
||||
if (pe->model && pe->model->type != mod_brush)
|
||||
pe->model = NULL;
|
||||
}
|
||||
else
|
||||
pe->model = NULL;
|
||||
pmove.numphysent++;
|
||||
pe->info = other - SVHL_Edict;
|
||||
VectorCopy(other->v.origin, pe->origin);
|
||||
VectorCopy(other->v.mins, pe->mins);
|
||||
VectorCopy(other->v.maxs, pe->maxs);
|
||||
VectorCopy(other->v.angles, pe->angles);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -541,7 +541,7 @@ void SVQ2_WritePlayerstateToClient (q2client_frame_t *from, q2client_frame_t *to
|
|||
SV_WriteFrameToClient
|
||||
==================
|
||||
*/
|
||||
void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg)
|
||||
void SVQ2_WriteFrameToClient (client_t *client, sizebuf_t *msg)
|
||||
{
|
||||
q2client_frame_t *frame, *oldframe;
|
||||
int lastframe;
|
||||
|
@ -602,7 +602,7 @@ copies off the playerstat and areabits.
|
|||
=============
|
||||
*/
|
||||
void SVQ2_Ents_Init(void);
|
||||
void SV_BuildClientFrame (client_t *client)
|
||||
void SVQ2_BuildClientFrame (client_t *client)
|
||||
{
|
||||
int e, i;
|
||||
vec3_t org;
|
||||
|
|
|
@ -736,6 +736,9 @@ qboolean SVQ2_InitGameProgs(void)
|
|||
*/
|
||||
}
|
||||
|
||||
Cvar_ForceSet(Cvar_Get("game", "", CVAR_LATCH, "Q2 compat"), FS_GetGamedir());
|
||||
Cvar_ForceSet(Cvar_Get("basedir", "", CVAR_LATCH, "Q2 compat"), FS_GetBasedir());
|
||||
|
||||
ge = (game_export_t *)Sys_GetGameAPI ((game_import_t*)&import);
|
||||
|
||||
if (!ge)
|
||||
|
|
|
@ -1773,6 +1773,7 @@ void SVQ3_ClientCommand(client_t *cl)
|
|||
void SVQ3_ClientBegin(client_t *cl)
|
||||
{
|
||||
VM_Call(q3gamevm, GAME_CLIENT_BEGIN, (int)(cl-svs.clients));
|
||||
sv.spawned_client_slots++;
|
||||
}
|
||||
|
||||
void SVQ3_ClientThink(client_t *cl)
|
||||
|
@ -2360,7 +2361,7 @@ void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3)
|
|||
q3->apos.trBase[1] = 0;
|
||||
q3->pos.trDelta[2] = 0;
|
||||
q3->apos.trBase[0] = 0;
|
||||
q3->event = q1->event;
|
||||
q3->event = 0;
|
||||
q3->angles2[1] = 0;
|
||||
q3->eType = 0;
|
||||
q3->torsoAnim = q1->skinnum;
|
||||
|
@ -2382,12 +2383,12 @@ void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3)
|
|||
q3->powerups = q1->effects;
|
||||
q3->modelindex = q1->modelindex;
|
||||
q3->otherEntityNum2 = 0;
|
||||
q3->loopSound = q1->sound;
|
||||
q3->loopSound = 0;
|
||||
q3->generic1 = q1->trans;
|
||||
q3->origin2[2] = q1->old_origin[2];
|
||||
q3->origin2[0] = q1->old_origin[0];
|
||||
q3->origin2[1] = q1->old_origin[1];
|
||||
q3->modelindex2 = q1->modelindex2;
|
||||
q3->origin2[2] = 0;//q1->old_origin[2];
|
||||
q3->origin2[0] = 0;//q1->old_origin[0];
|
||||
q3->origin2[1] = 0;//q1->old_origin[1];
|
||||
q3->modelindex2 = 0;//q1->modelindex2;
|
||||
q3->angles[0] = q1->angles[0];
|
||||
q3->time = 0;
|
||||
q3->apos.trTime = 0;
|
||||
|
@ -3068,13 +3069,13 @@ void SVQ3_ParseClientMessage(client_t *client)
|
|||
Con_Printf(CON_WARNING "WARNING: Junk at end of packet for client %s\n", client->name );
|
||||
}
|
||||
};
|
||||
void SVQ3_HandleClient(void)
|
||||
qboolean SVQ3_HandleClient(void)
|
||||
{
|
||||
int i;
|
||||
int qport;
|
||||
|
||||
if (net_message.cursize<6)
|
||||
return; //urm. :/
|
||||
return false; //urm. :/
|
||||
|
||||
MSG_BeginReading(msg_nullnetprim);
|
||||
MSG_ReadBits(32);
|
||||
|
@ -3088,19 +3089,22 @@ void SVQ3_HandleClient(void)
|
|||
continue;
|
||||
if (!NET_CompareBaseAdr(svs.clients[i].netchan.remote_address, net_from))
|
||||
continue;
|
||||
if (!ISQ3CLIENT(&svs.clients[i]))
|
||||
continue;
|
||||
|
||||
//found them.
|
||||
break;
|
||||
}
|
||||
if (i == sv.allocated_client_slots)
|
||||
return; //nope
|
||||
return false; //nope
|
||||
|
||||
if (!SVQ3_Netchan_Process(&svs.clients[i]))
|
||||
{
|
||||
return; // wasn't accepted for some reason
|
||||
return true; // wasn't accepted for some reason
|
||||
}
|
||||
|
||||
SVQ3_ParseClientMessage(&svs.clients[i]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and let the gamecode know of it.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue