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:
Spoike 2012-02-12 05:18:31 +00:00
parent fb35b91e01
commit 9ee7301d32
74 changed files with 3175 additions and 1276 deletions

View File

@ -37,11 +37,13 @@ extern cvar_t cl_nolerp;
extern cvar_t cl_nolerp_netquake;
extern cvar_t r_torch;
extern cvar_t r_shadows;
extern cvar_t r_showbboxes;
extern cvar_t cl_gibfilter, cl_deadbodyfilter;
extern int cl_playerindex;
static struct predicted_player {
static struct predicted_player
{
int flags;
qboolean active;
vec3_t origin; // predicted origin
@ -54,6 +56,9 @@ static struct predicted_player {
} predicted_players[MAX_CLIENTS];
static void CL_LerpNetFrameState(int fsanim, framestate_t *fs, lerpents_t *le);
qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence);
void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int sequence);
extern int cl_playerindex, cl_h_playerindex, cl_rocketindex, cl_grenadeindex, cl_gib1index, cl_gib2index, cl_gib3index;
@ -86,9 +91,11 @@ qboolean CL_FilterModelindex(int modelindex, int frame)
void CL_FreeDlights(void)
{
#ifdef warningmsg
#pragma warningmsg("not freeing shadowmeshes")
#endif
int i;
for (i = 0; i < rtlights_max; i++)
if (cl_dlights[i].worldshadowmesh)
SH_FreeShadowMesh(cl_dlights[i].worldshadowmesh);
rtlights_max = cl_maxdlights = 0;
BZ_Free(cl_dlights);
cl_dlights = NULL;
@ -299,7 +306,7 @@ Can go from either a baseline or a previous packet_entity
==================
*/
//int bitcounts[32]; /// just for protocol profiling
void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean new)
void CLQW_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean new)
{
int i;
#ifdef PROTOCOLEXTENSIONS
@ -330,13 +337,18 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean
morebits |= MSG_ReadByte()<<8;
#endif
if ((morebits & U_ENTITYDBL) && (cls.fteprotocolextensions & PEXT_ENTITYDBL))
to->number += 512;
if ((morebits & U_ENTITYDBL2) && (cls.fteprotocolextensions & PEXT_ENTITYDBL2))
to->number += 1024;
if (bits & U_MODEL)
{
to->modelindex = MSG_ReadByte ();
if (morebits & U_MODELDBL && cls.fteprotocolextensions & PEXT_MODELDBL)
if (morebits & U_MODELDBL && (cls.fteprotocolextensions & PEXT_MODELDBL))
to->modelindex += 256;
}
else if (morebits & U_MODELDBL && cls.fteprotocolextensions & PEXT_MODELDBL)
else if (morebits & U_MODELDBL && (cls.fteprotocolextensions & PEXT_MODELDBL))
to->modelindex = MSG_ReadShort();
if (bits & U_FRAME)
@ -346,7 +358,11 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean
to->colormap = MSG_ReadByte();
if (bits & U_SKIN)
{
to->skinnum = MSG_ReadByte();
if (to->skinnum >= 256-32) /*final 32 skins are taken as a content value instead*/
to->skinnum = (char)to->skinnum;
}
if (bits & U_EFFECTS)
to->effects = (to->effects&0xff00)|MSG_ReadByte();
@ -369,9 +385,10 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean
if (bits & U_ANGLE3)
to->angles[2] = MSG_ReadAngle ();
to->solid = ES_SOLID_BSP;
if (bits & U_SOLID)
{
// FIXME
//doesn't mean anything. solidity is infered instead.
}
#ifdef PEXT_SCALE
@ -399,11 +416,6 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean
to->colormod[2] = MSG_ReadByte();
}
if ((morebits & U_ENTITYDBL) && (cls.fteprotocolextensions & PEXT_ENTITYDBL))
to->number += 512;
if ((morebits & U_ENTITYDBL2) && (cls.fteprotocolextensions & PEXT_ENTITYDBL2))
to->number += 1024;
if (morebits & U_DPFLAGS)// && cls.fteprotocolextensions & PEXT_DPFLAGS)
{
// these are bits for the 'flags' field of the entity_state_t
@ -466,10 +478,324 @@ void FlushEntityPacket (void)
if (!word)
break; // done
CL_ParseDelta (&olde, &newe, word, true);
CLQW_ParseDelta (&olde, &newe, word, true);
}
}
void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *olds, entity_state_t *baseline)
{
unsigned int bits;
bits = MSG_ReadByte();
if (bits & UF_EXTEND1)
bits |= MSG_ReadByte()<<8;
if (bits & UF_EXTEND2)
bits |= MSG_ReadByte()<<16;
if (bits & UF_EXTEND3)
bits |= MSG_ReadByte()<<24;
if (cl_shownet.ival >= 3)
Con_Printf("%3i: Update %4i 0x%x\n", msg_readcount, entnum, bits);
if (bits & UF_RESET)
*news = *baseline;
else if (!olds)
{
Con_DPrintf("New entity without reset\n");
*news = *baseline;
}
else
*news = *olds;
news->number = entnum;
if (bits & UF_FRAME)
{
if (bits & UF_16BIT)
news->frame = MSG_ReadShort();
else
news->frame = MSG_ReadByte();
}
if (bits & UF_ORIGINXY)
{
news->origin[0] = MSG_ReadCoord();
news->origin[1] = MSG_ReadCoord();
}
if (bits & UF_ORIGINZ)
news->origin[2] = MSG_ReadCoord();
if (bits & UF_PREDINFO)
{
/*predicted stuff gets more precise angles*/
if (bits & UF_ANGLESXZ)
{
news->angles[0] = MSG_ReadAngle16();
news->angles[2] = MSG_ReadAngle16();
}
if (bits & UF_ANGLESY)
news->angles[1] = MSG_ReadAngle16();
}
else
{
if (bits & UF_ANGLESXZ)
{
news->angles[0] = MSG_ReadAngle();
news->angles[2] = MSG_ReadAngle();
}
if (bits & UF_ANGLESY)
news->angles[1] = MSG_ReadAngle();
}
if ((bits & (UF_EFFECTS | UF_EFFECTS2)) == (UF_EFFECTS | UF_EFFECTS2))
news->effects = MSG_ReadLong();
else if (bits & UF_EFFECTS2)
news->effects = MSG_ReadShort();
else if (bits & UF_EFFECTS)
news->effects = MSG_ReadByte();
news->u.q1.movement[0] = 0;
news->u.q1.movement[1] = 0;
news->u.q1.movement[2] = 0;
news->u.q1.velocity[0] = 0;
news->u.q1.velocity[1] = 0;
news->u.q1.velocity[2] = 0;
if (bits & UF_PREDINFO)
{
unsigned int predbits;
predbits = MSG_ReadByte();
if (predbits & UFP_FORWARD)
news->u.q1.movement[0] = MSG_ReadShort();
else
news->u.q1.movement[0] = 0;
if (predbits & UFP_SIDE)
news->u.q1.movement[1] = MSG_ReadShort();
else
news->u.q1.movement[1] = 0;
if (predbits & UFP_UP)
news->u.q1.movement[2] = MSG_ReadShort();
else
news->u.q1.movement[2] = 0;
if (predbits & UFP_MOVETYPE)
news->u.q1.pmovetype = MSG_ReadByte();
if (predbits & UFP_VELOCITYXY)
{
news->u.q1.velocity[0] = MSG_ReadShort();
news->u.q1.velocity[1] = MSG_ReadShort();
}
else
{
news->u.q1.velocity[0] = 0;
news->u.q1.velocity[1] = 0;
}
if (predbits & UFP_VELOCITYZ)
news->u.q1.velocity[2] = MSG_ReadShort();
else
news->u.q1.velocity[2] = 0;
if (predbits & UFP_MSEC)
news->u.q1.msec = MSG_ReadByte();
else
news->u.q1.msec = 0;
}
else
{
news->u.q1.pmovetype = 0;
news->u.q1.msec = 0;
}
if (bits & UF_MODEL)
{
if (bits & UF_16BIT)
news->modelindex = MSG_ReadShort();
else
news->modelindex = MSG_ReadByte();
}
if (bits & UF_SKIN)
{
if (bits & UF_16BIT)
news->skinnum = MSG_ReadShort();
else
news->skinnum = MSG_ReadByte();
}
if (bits & UF_COLORMAP)
news->colormap = MSG_ReadByte();
if (bits & UF_SOLID)
news->solid = MSG_ReadShort();
if (bits & UF_FLAGS)
news->dpflags = MSG_ReadByte();
if (bits & UF_ALPHA)
news->trans = MSG_ReadByte();
if (bits & UF_SCALE)
news->scale = MSG_ReadByte();
if (bits & UF_ABSLIGHT)
news->abslight = MSG_ReadByte();
if (bits & UF_DRAWFLAGS)
news->hexen2flags = MSG_ReadByte();
if (bits & UF_TAGINFO)
{
news->tagentity = MSG_ReadShort();
news->tagindex = MSG_ReadByte();
}
if (bits & UF_LIGHT)
{
news->light[0] = MSG_ReadShort();
news->light[1] = MSG_ReadShort();
news->light[1] = MSG_ReadShort();
news->light[1] = MSG_ReadShort();
news->lightstyle = MSG_ReadByte();
news->lightpflags = MSG_ReadByte();
}
if (bits & UF_COLORMOD)
{
news->colormod[0] = MSG_ReadByte();
news->colormod[1] = MSG_ReadByte();
news->colormod[2] = MSG_ReadByte();
}
if (bits & UF_GLOWMOD)
{
news->glowmod[0] = MSG_ReadByte();
news->glowmod[1] = MSG_ReadByte();
news->glowmod[2] = MSG_ReadByte();
}
if (bits & UF_FATNESS)
news->fatness = MSG_ReadByte();
/*update the prediction info if needed*/
if ((bits & UF_PREDINFO) && (news->number-1) < cl.allocated_client_slots)
{
frame_t *fram;
fram = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
CL_PlayerFrameUpdated(&fram->playerstate[news->number-1], news, cls.netchan.incoming_sequence);
}
}
void CLFTE_ParseEntities(void)
{
int oldpacket, newpacket;
packet_entities_t *oldp, *newp, nullp;
unsigned short newnum, oldnum;
int oldindex;
qboolean isvalid = false;
// int i;
// for (i = cl.validsequence+1; i < cls.netchan.incoming_sequence; i++)
// {
// Con_Printf("CL: Dropped %i\n", i);
// }
newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
oldpacket = cl.validsequence&UPDATE_MASK;
newp = &cl.frames[newpacket].packet_entities;
oldp = &cl.frames[oldpacket].packet_entities;
cl.frames[newpacket].invalid = true;
if (cls.netchan.incoming_sequence >= cl.validsequence + UPDATE_BACKUP)
{
oldp = &nullp;
oldp->num_entities = 0;
oldp->max_entities = 0;
}
else
isvalid = true;
newp->servertime = MSG_ReadFloat();
cl.oldgametime = cl.gametime;
cl.oldgametimemark = cl.gametimemark;
cl.gametime = newp->servertime;
cl.gametimemark = realtime;
/*clear all entities*/
newp->num_entities = 0;
oldindex = 0;
while(1)
{
newnum = MSG_ReadShort();
if (!newnum || msg_badread)
{
/*reached the end, don't forget old entities*/
while(oldindex < oldp->num_entities)
{
if (newp->num_entities >= newp->max_entities)
{
newp->max_entities = newp->num_entities+1;
newp->entities = BZ_Realloc(newp->entities, sizeof(entity_state_t)*newp->max_entities);
}
newp->entities[newp->num_entities++] = oldp->entities[oldindex++];
}
break;
}
if (newnum == 0x8000)
{
if (cl_shownet.ival >= 3)
Con_Printf("%3i: Reset all\n", msg_readcount);
newp->num_entities = 0;
isvalid = true;
continue;
}
oldnum = oldindex >= oldp->num_entities ? 0xffff : oldp->entities[oldindex].number;
/*if we skipped some, then they were unchanged*/
while ((newnum&0x7fff) > oldnum)
{
if (newp->num_entities >= newp->max_entities)
{
newp->max_entities = newp->num_entities+1;
newp->entities = BZ_Realloc(newp->entities, sizeof(entity_state_t)*newp->max_entities);
}
newp->entities[newp->num_entities++] = oldp->entities[oldindex++];
oldnum = oldindex >= oldp->num_entities ? 0xffff : oldp->entities[oldindex].number;
}
if (newnum & 0x8000)
{
if (cl_shownet.ival >= 3)
Con_Printf("%3i: Remove %i\n", msg_readcount, (newnum&32767));
if (oldnum == (newnum&0x7fff))
oldindex++;
continue;
}
else
{
if (!CL_CheckBaselines(newnum))
Host_EndGame("CL_ParsePacketEntities: check baselines failed with size %i", newnum);
if (newp->num_entities >= newp->max_entities)
{
newp->max_entities = newp->num_entities+1;
newp->entities = BZ_Realloc(newp->entities, sizeof(entity_state_t)*newp->max_entities);
}
if (oldnum == newnum)
CLFTE_ReadDelta(newnum, &newp->entities[newp->num_entities++], &oldp->entities[oldindex++], cl_baselines + newnum);
else
CLFTE_ReadDelta(newnum, &newp->entities[newp->num_entities++], NULL, cl_baselines + newnum);
}
}
if (isvalid)
{
cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedinputsequence = cl.validsequence;
cl.frames[newpacket].invalid = false;
}
else
cl.validsequence = 0;
/*ackedinputsequence is updated when we have new player prediction info*/
cl.ackedinputsequence = cls.netchan.incoming_sequence;
}
/*
==================
CL_ParsePacketEntities
@ -657,7 +983,7 @@ void CL_ParsePacketEntities (qboolean delta)
if (!CL_CheckBaselines(newnum))
Host_EndGame("CL_ParsePacketEntities: check baselines failed with size %i", newnum);
CL_ParseDelta (cl_baselines + newnum, &newp->entities[newindex], word, true);
CLQW_ParseDelta (cl_baselines + newnum, &newp->entities[newindex], word, true);
newindex++;
continue;
}
@ -685,7 +1011,7 @@ void CL_ParsePacketEntities (qboolean delta)
}
//Con_Printf ("delta %i\n",newnum);
CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word, false);
CLQW_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word, false);
newindex++;
oldindex++;
}
@ -745,9 +1071,10 @@ void DP5_ParseDelta(entity_state_t *s)
s->trans = 255;
s->scale = 16;
s->number = num;
s->colormod[0] = 32;
s->colormod[1] = 32;
s->colormod[2] = 32;
s->colormod[0] = (256)/8;
s->colormod[1] = (256)/8;
s->colormod[2] = (256)/8;
s->solid = ES_SOLID_BSP;
// s->active = true;
}
if (bits & E5_FLAGS)
@ -846,10 +1173,16 @@ void DP5_ParseDelta(entity_state_t *s)
s->colormod[1] = MSG_ReadByte();
s->colormod[2] = MSG_ReadByte();
}
if (bits & E5_GLOWMOD)
{
s->glowmod[0] = MSG_ReadByte();
s->glowmod[1] = MSG_ReadByte();
s->glowmod[2] = MSG_ReadByte();
}
}
int cl_latestframenum;
void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o(
void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o(
{
//the incoming entities do not come in in any order. :(
//well, they come in in order of priorities, but that's not useful to us.
@ -987,7 +1320,7 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o(
void CLNQ_ParseEntity(unsigned int bits)
{
int i;
int num, pnum;
int num;
entity_state_t *state;//, *from;
entity_state_t *base;
static float lasttime;
@ -1045,6 +1378,7 @@ void CLNQ_ParseEntity(unsigned int bits)
base = cl_baselines + num;
state->number = num;
state->solid = ES_SOLID_BSP;
state->dpflags = (bits & NQU_NOLERP)?RENDER_STEP:0;
@ -1426,6 +1760,194 @@ int V_AddLight (int entsource, vec3_t org, float quant, float r, float g, float
return CL_NewDlightRGB (entsource, org, quant, -0.1, r, g, b) - cl_dlights;
}
static void CLQ1_AddCube(shader_t *shader, vec3_t mins, vec3_t maxs, float r, float g, float b, float a)
{
int v;
scenetris_t *t;
if (!r && !g && !b)
return;
if (g && !b)
b = 0;
/*reuse the previous trigroup if its the same shader*/
if (cl_numstris && cl_stris[cl_numstris-1].shader == shader)
t = &cl_stris[cl_numstris-1];
else
{
if (cl_numstris == cl_maxstris)
{
cl_maxstris += 8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = shader;
t->numidx = 0;
t->numvert = 0;
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
}
if (cl_numstrisvert + 8 > cl_maxstrisvert)
{
cl_maxstrisvert = cl_numstrisvert + 8;
cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert);
cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(vec2_t)*cl_maxstrisvert);
cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(vec4_t)*cl_maxstrisvert);
}
if (cl_maxstrisidx < cl_numstrisidx+6*6)
{
cl_maxstrisidx = cl_numstrisidx+6*6 + 64;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
for (v = 0; v < 8; v++)
{
cl_strisvertv[cl_numstrisvert+v][0] = (v & 1)?mins[0]:maxs[0];
cl_strisvertv[cl_numstrisvert+v][1] = (v & 2)?mins[1]:maxs[1];
cl_strisvertv[cl_numstrisvert+v][2] = (v & 4)?mins[2]:maxs[2];
cl_strisvertt[cl_numstrisvert+v][0] = 0;
cl_strisvertt[cl_numstrisvert+v][1] = 0;
cl_strisvertc[cl_numstrisvert+v][0] = r;
cl_strisvertc[cl_numstrisvert+v][1] = g;
cl_strisvertc[cl_numstrisvert+v][2] = b;
cl_strisvertc[cl_numstrisvert+v][3] = a;
}
/*top*/
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+3;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2;
/*bottom*/
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+4;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+5;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+6;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+6;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+5;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+7;
/*'left'*/
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+5;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+4;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+5;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
/*right*/
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+6;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+7;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+7;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+3;
/*urm, the other way*/
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+4;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+6;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+4;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
/*and its oposite*/
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+7;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+5;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+3;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+3;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+5;
t->numvert += 8;
t->numidx = cl_numstrisidx - t->firstidx;
cl_numstrisvert += 8;
}
#include "pr_common.h"
void CLQ1_AddVisibleBBoxes(void)
{
world_t *w;
wedict_t *e;
int i;
shader_t *s;
extern world_t csqc_world;
vec3_t min, max, size;
switch(r_showbboxes.ival & 3)
{
default:
return;
#ifndef CLIENTONLY
case 1:
w = &sv.world;
break;
#endif
#ifdef CSQC_DAT
case 2:
w = &csqc_world;
return;
#endif
}
if (!w->progs)
return;
s = R_RegisterShader("bboxshader",
"{\n"
"polygonoffset\n"
"{\n"
"map $whiteimage\n"
"blendfunc add\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"}\n"
"}\n");
for (i = 1; i < w->num_edicts; i++)
{
e = WEDICT_NUM(w->progs, i);
if (e->isfree)
continue;
if (r_showbboxes.ival & 4)
{
/*mins is easy*/
VectorAdd(e->v->origin, e->v->mins, min);
/*maxs is weeeeird*/
VectorSubtract (e->v->maxs, e->v->mins, size);
if (size[0] < 3)
VectorCopy(min, max);
else if (size[0] <= 32)
{
max[0] = min[0] + 32;
max[1] = min[1] + 32;
max[2] = min[2] + 56;
}
else
{
max[0] = min[0] + 64;
max[1] = min[1] + 64;
max[2] = min[2] + 88;
}
}
else
{
VectorCopy(e->v->absmin, min);
VectorCopy(e->v->absmax, max);
}
CLQ1_AddCube(s, min, max, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
}
}
void CLQ1_AddShadow(entity_t *ent)
{
float radius;
@ -1671,6 +2193,8 @@ void CL_LinkStaticEntities(void *pvs)
ent->framestate.g[FS_REG].frametime[0] = cl.time;
ent->framestate.g[FS_REG].frametime[1] = cl.time;
ent->shaderRGBAf[3] = 0.7;
// emit particles for statics (we don't need to cheat check statics)
if (clmodel->particleeffect >= 0 && gl_part_flame.ival)
{
@ -1696,7 +2220,7 @@ void R_FlameTrail(vec3_t start, vec3_t end, float seperation);
/*
Interpolates the two packets by the given time, writes its results into the lerpentities array.
*/
static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entities_t *oldpack, float servertime)
static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newpack, packet_entities_t *oldpack, float servertime)
{
lerpents_t *le;
entity_state_t *snew, *sold;
@ -1757,7 +2281,17 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit
VectorClear(move);
}
if (sold == snew)
VectorCopy(le->origin, le->lastorigin);
if (snew->u.q1.pmovetype && CL_PredictPlayer(le, snew, newsequence))
{
if (sold == snew)
{
/*keep trails correct*/
le->isnew = true;
VectorCopy(le->origin, le->lastorigin);
}
}
else if (sold == snew)
{
//new this frame (or we noticed something changed significantly)
VectorCopy(snew->origin, le->origin);
@ -1776,8 +2310,6 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit
}
else
{
VectorCopy(le->origin, le->lastorigin);
if (snew->dpflags & RENDER_STEP)
{
float lfrac;
@ -1946,7 +2478,7 @@ void CL_TransitionEntities (void)
packnew = &cl.frames[newf].packet_entities;
packold = &cl.frames[oldf].packet_entities;
CL_TransitionPacketEntities(packnew, packold, servertime);
CL_TransitionPacketEntities(newff, packnew, packold, servertime);
cl.currentpacktime = servertime;
cl.currentpackentities = packnew;
@ -1973,7 +2505,9 @@ void CL_TransitionEntities (void)
for (p = 0; p < cl.allocated_client_slots; p++, pnew++, pold++)
{
if (pnew->messagenum != newff)
{
continue;
}
le = &cl.lerpplayers[p];
VectorSubtract(pnew->predorigin, pold->predorigin, move);
@ -2205,10 +2739,11 @@ void CL_LinkPacketEntities (void)
//set scale
ent->scale = state->scale/16.0;
#endif
ent->shaderRGBAf[0] = (state->colormod[0]*8.0f)/255;
ent->shaderRGBAf[1] = (state->colormod[1]*8.0f)/255;
ent->shaderRGBAf[2] = (state->colormod[2]*8.0f)/255;
ent->shaderRGBAf[0] = (state->colormod[0]*8.0f)/256;
ent->shaderRGBAf[1] = (state->colormod[1]*8.0f)/256;
ent->shaderRGBAf[2] = (state->colormod[2]*8.0f)/256;
ent->shaderRGBAf[3] = state->trans/255.0f;
#ifdef PEXT_FATNESS
//set trans
ent->fatness = state->fatness/16.0;
@ -2238,6 +2773,7 @@ void CL_LinkPacketEntities (void)
AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]);
VectorInverse(ent->axis[1]);
/*if this entity is in a player's slot...*/
if (ent->keynum <= cl.allocated_client_slots)
{
if (!cl.nolocalplayer[0])
@ -2347,6 +2883,8 @@ void CL_LinkPacketEntities (void)
#ifdef CSQC_DAT
CSQC_DeltaEnd();
#endif
CLQ1_AddVisibleBBoxes();
}
/*
@ -2614,7 +3152,8 @@ void CL_ParsePlayerinfo (void)
if (flags & DF_WEAPONFRAME)
state->weaponframe = MSG_ReadByte ();
state->hullnum = 1;
VectorSet(state->szmins, -16, -16, -24);
VectorSet(state->szmaxs, 16, 16, 32);
state->scale = 1;
state->alpha = 255;
state->fatness = 0;
@ -2729,10 +3268,8 @@ void CL_ParsePlayerinfo (void)
else
state->weaponframe = 0;
if (cl.worldmodel && cl.worldmodel->fromgame == fg_quake)
state->hullnum = 1;
else
state->hullnum = 56;
VectorSet(state->szmins, -16, -16, -24);
VectorSet(state->szmaxs, 16, 16, 32);
state->scale = 1;
state->alpha = 255;
state->fatness = 0;
@ -2750,15 +3287,31 @@ void CL_ParsePlayerinfo (void)
state->fatness = (float)MSG_ReadChar();
#endif
#ifdef PEXT_HULLSIZE
if (cls.fteprotocolextensions & PEXT_HULLSIZE)
if ((cls.fteprotocolextensions & PEXT_HULLSIZE) && (flags & PF_HULLSIZE_Z))
{
if (flags & PF_HULLSIZE_Z)
state->hullnum = MSG_ReadByte();
int num;
num = MSG_ReadByte();
if (cl.worldmodel->fromgame != fg_quake)
{
VectorScale(state->szmins, num/56.0f, state->szmins);
VectorScale(state->szmaxs, num/56.0f, state->szmaxs);
}
else
{
VectorCopy(cl.worldmodel->hulls[num&(MAX_MAP_HULLSM-1)].clip_mins, state->szmins);
VectorCopy(cl.worldmodel->hulls[num&(MAX_MAP_HULLSM-1)].clip_maxs, state->szmaxs);
}
if (num & 128)
{ //this hack is for hexen2.
state->szmaxs[2] -= state->szmins[2];
state->szmins[2] = 0;
}
}
//should be passed to player move func.
#endif
if (cls.fteprotocolextensions & PEXT_COLOURMOD && flags & PF_COLOURMOD)
if (cls.fteprotocolextensions & PEXT_COLOURMOD && (flags & PF_COLOURMOD))
{
state->colourmod[0] = MSG_ReadByte();
state->colourmod[1] = MSG_ReadByte();
@ -2836,7 +3389,7 @@ guess_pm_type:
state->command.msec = msec;
CL_SetSolidEntities();
CL_SetSolidPlayers (num);
CL_SetSolidPlayers();
CL_PredictUsercmd (0, state, &exact, &state->command); //uses player 0's maxspeed/grav...
VectorCopy (exact.origin, state->predorigin);
}
@ -3191,7 +3744,7 @@ void CL_LinkPlayers (void)
//Con_DPrintf ("predict: %i\n", msec);
oldphysent = pmove.numphysent;
CL_SetSolidPlayers (j);
CL_SetSolidPlayers ();
CL_PredictUsercmd (0, state, &exact, &state->command); //uses player 0's maxspeed/grav...
pmove.numphysent = oldphysent;
VectorCopy (exact.origin, ent->origin);
@ -3363,6 +3916,7 @@ void CL_SetSolidEntities (void)
frame_t *frame;
packet_entities_t *pak;
entity_state_t *state;
physent_t *pent;
memset(&pmove.physents[0], 0, sizeof(physent_t));
pmove.physents[0].model = cl.worldmodel;
@ -3377,22 +3931,67 @@ void CL_SetSolidEntities (void)
{
state = &pak->entities[i];
if (state->modelindex <= 0)
if (!state->solid && !state->skinnum)
continue;
if (!cl.model_precache[state->modelindex])
continue;
if (*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels)
if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode)
if (state->solid == 31)
{ /*bsp model size*/
if (state->modelindex <= 0)
continue;
if (!cl.model_precache[state->modelindex])
continue;
/*this makes non-inline bsp objects non-solid for prediction*/
if ((*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels) && cl.model_precache[state->modelindex]->hulls[1].firstclipnode)
{
pent = &pmove.physents[pmove.numphysent];
memset(pent, 0, sizeof(physent_t));
pent->model = cl.model_precache[state->modelindex];
VectorCopy (state->angles, pent->angles);
pent->angles[0]*=-1;
}
else
continue;
}
else
{
memset(&pmove.physents[pmove.numphysent], 0, sizeof(physent_t));
pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex];
VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin);
VectorCopy (state->angles, pmove.physents[pmove.numphysent].angles);
// VectorCopy (cl.lerpents[state->number].origin, pmove.physents[pmove.numphysent].origin);
// VectorCopy (cl.lerpents[state->number].angles, pmove.physents[pmove.numphysent].angles);
pmove.physents[pmove.numphysent].angles[0]*=-1;
if (++pmove.numphysent == MAX_PHYSENTS)
break;
pent = &pmove.physents[pmove.numphysent];
memset(pent, 0, sizeof(physent_t));
pent->info = state->number;
/*don't bother with angles*/
pent->maxs[0] = pent->maxs[1] = 8*(state->solid & 31);
pent->mins[0] = pent->mins[1] = -pent->maxs[0];
pent->mins[2] = -8*((state->solid>>5) & 31);
pent->maxs[2] = 8*((state->solid>>10) & 63) - 32;
}
if (++pmove.numphysent == MAX_PHYSENTS)
break;
VectorCopy(state->origin, pent->origin);
pent->info = state->number;
switch((int)state->skinnum)
{
case 0:
break;
case -16:
pent->nonsolid = true;
pent->forcecontentsmask = FTECONTENTS_LADDER;
break;
case Q1CONTENTS_SKY:
pent->nonsolid = true;
pent->forcecontentsmask = FTECONTENTS_SKY;
break;
case Q1CONTENTS_LAVA:
pent->nonsolid = true;
pent->forcecontentsmask = FTECONTENTS_LAVA;
break;
case Q1CONTENTS_SLIME:
pent->nonsolid = true;
pent->forcecontentsmask = FTECONTENTS_SLIME;
break;
case Q1CONTENTS_WATER:
pent->nonsolid = true;
pent->forcecontentsmask = FTECONTENTS_WATER;
break;
}
}
@ -3500,7 +4099,7 @@ pmove must be setup with world and solid entity hulls before calling
(via CL_PredictMove)
===============
*/
void CL_SetSolidPlayers (int playernum)
void CL_SetSolidPlayers (void)
{
int j;
extern vec3_t player_mins;
@ -3521,10 +4120,6 @@ void CL_SetSolidPlayers (int playernum)
if (!pplayer->active)
continue; // not present this frame
// the player object never gets added
if (j == playernum)
continue;
if (pplayer->flags & PF_DEAD)
continue; // dead players aren't solid

View File

@ -48,7 +48,7 @@ usercmd_t independantphysics[MAX_SPLITS];
vec3_t mousemovements[MAX_SPLITS];
/*kinda a hack...*/
int con_splitmodifier;
static int con_splitmodifier;
cvar_t cl_forcesplitclient = CVAR("cl_forcesplitclient", "0");
extern cvar_t cl_splitscreen;
int CL_TargettedSplit(qboolean nowrap)
@ -96,6 +96,22 @@ void CL_Split_f(void)
}
con_splitmodifier = tmp;
}
void CL_SplitA_f(void)
{
int tmp;
char *c, *args;
c = Cmd_Argv(0);
args = COM_Parse(Cmd_Args());
while(*args == ' ' || *args == '\t')
args++;
tmp = con_splitmodifier;
con_splitmodifier = atoi(com_token);
if (*c == '+' || *c == '-')
Cmd_ExecuteString(va("%c%s", *c, args), Cmd_ExecLevel);
else
Cmd_ExecuteString(args, Cmd_ExecLevel);
con_splitmodifier = tmp;
}
/*
===============================================================================
@ -1748,6 +1764,11 @@ void CL_InitInput (void)
in_mlook.state[sp] = 1;
#endif
}
/*then alternative arged ones*/
Cmd_AddCommand ("p", CL_SplitA_f);
Cmd_AddCommand ("+p", CL_SplitA_f);
Cmd_AddCommand ("-p", CL_SplitA_f);
Cmd_AddCommand ("+moveup", IN_UpDown);
Cmd_AddCommand ("-moveup", IN_UpUp);

View File

@ -318,85 +318,8 @@ void CL_SupportedFTEExtensions(int *pext1, int *pext2)
unsigned int fteprotextsupported = 0;
unsigned int fteprotextsupported2 = 0;
#ifdef PEXT_SCALE //dmw - protocol extensions
fteprotextsupported |= PEXT_SCALE;
#endif
#ifdef PEXT_LIGHTSTYLECOL
fteprotextsupported |= PEXT_LIGHTSTYLECOL;
#endif
#ifdef PEXT_TRANS
fteprotextsupported |= PEXT_TRANS;
#endif
#ifdef PEXT_VIEW2
fteprotextsupported |= PEXT_VIEW2;
#endif
#ifdef PEXT_ACCURATETIMINGS
fteprotextsupported |= PEXT_ACCURATETIMINGS;
#endif
#ifdef PEXT_ZLIBDL
fteprotextsupported |= PEXT_ZLIBDL;
#endif
#ifdef PEXT_FATNESS
fteprotextsupported |= PEXT_FATNESS;
#endif
#ifdef PEXT_HLBSP
fteprotextsupported |= PEXT_HLBSP;
#endif
#ifdef PEXT_Q2BSP
fteprotextsupported |= PEXT_Q2BSP;
#endif
#ifdef PEXT_Q3BSP
fteprotextsupported |= PEXT_Q3BSP;
#endif
#ifdef PEXT_TE_BULLET
fteprotextsupported |= PEXT_TE_BULLET;
#endif
#ifdef PEXT_HULLSIZE
fteprotextsupported |= PEXT_HULLSIZE;
#endif
#ifdef PEXT_SETVIEW
fteprotextsupported |= PEXT_SETVIEW;
#endif
#ifdef PEXT_MODELDBL
fteprotextsupported |= PEXT_MODELDBL;
#endif
#ifdef PEXT_SOUNDDBL
fteprotextsupported |= PEXT_SOUNDDBL;
#endif
#ifdef PEXT_VWEAP
fteprotextsupported |= PEXT_VWEAP;
#endif
#ifdef PEXT_FLOATCOORDS
fteprotextsupported |= PEXT_FLOATCOORDS;
#endif
fteprotextsupported |= PEXT_SPAWNSTATIC2;
fteprotextsupported |= PEXT_COLOURMOD;
fteprotextsupported |= PEXT_SPLITSCREEN;
fteprotextsupported |= PEXT_HEXEN2;
fteprotextsupported |= PEXT_CUSTOMTEMPEFFECTS;
fteprotextsupported |= PEXT_256PACKETENTITIES;
fteprotextsupported |= PEXT_ENTITYDBL;
fteprotextsupported |= PEXT_ENTITYDBL2;
// fteprotextsupported |= PEXT_64PLAYERS;
fteprotextsupported |= PEXT_SHOWPIC;
fteprotextsupported |= PEXT_SETATTACHMENT;
#ifdef PEXT_CHUNKEDDOWNLOADS
fteprotextsupported |= PEXT_CHUNKEDDOWNLOADS;
#endif
#ifdef PEXT_CSQC
fteprotextsupported |= PEXT_CSQC;
#endif
#ifdef PEXT_DPFLAGS
fteprotextsupported |= PEXT_DPFLAGS;
#endif
fteprotextsupported2 |= PEXT2_PRYDONCURSOR;
#ifdef PEXT2_VOICECHAT
fteprotextsupported2 |= PEXT2_VOICECHAT;
#endif
fteprotextsupported2 |= PEXT2_SETANGLEDELTA;
fteprotextsupported = Net_PextMask(1);
fteprotextsupported2 = Net_PextMask(2);
fteprotextsupported &= strtoul(cl_pext_mask.string, NULL, 16);
// fteprotextsupported2 &= strtoul(cl_pext2_mask.string, NULL, 16);
@ -467,7 +390,7 @@ CL_SendConnectPacket
called by CL_Connect_f and CL_CheckResend
======================
*/
void CL_SendConnectPacket (
void CL_SendConnectPacket (int mtu,
#ifdef PROTOCOL_VERSION_FTE
int ftepext, int ftepext2,
#endif
@ -608,6 +531,19 @@ void CL_SendConnectPacket (
Q_strncatz(data, va("0x%x 0x%x\n", PROTOCOL_VERSION_FTE2, fteprotextsupported2), sizeof(data));
#endif
if (mtu >= 0)
{
if (adr.type == NA_LOOPBACK)
mtu = 8192;
else if (net_mtu.ival > 64 && mtu > net_mtu.ival)
mtu = net_mtu.ival;
mtu &= ~7;
Q_strncatz(data, va("0x%x %i\n", PROTOCOL_VERSION_FRAGMENT, mtu), sizeof(data));
cls.netchan.fragmentsize = mtu;
}
else
cls.netchan.fragmentsize = 0;
#ifdef HUFFNETWORK
if (compressioncrc && Huff_CompressionCRC(compressioncrc))
{
@ -732,7 +668,7 @@ void CL_CheckForResend (void)
CL_ConnectToDarkPlaces("", adr);
}
else
CL_SendConnectPacket (svs.fteprotocolextensions, svs.fteprotocolextensions2, false);
CL_SendConnectPacket (8192-16, Net_PextMask(1), Net_PextMask(2), false);
return;
}
#endif
@ -1156,7 +1092,7 @@ void CL_ClearState (void)
cl.fog_colour[1] = 0.3;
cl.fog_colour[2] = 0.3;
cl.allocated_client_slots = MAX_CLIENTS;
cl.allocated_client_slots = QWMAX_CLIENTS;
#ifndef CLIENTONLY
if (sv.state)
cl.allocated_client_slots = sv.allocated_client_slots;
@ -2299,7 +2235,7 @@ void CL_ConnectionlessPacket (void)
{
static unsigned int lasttime = 0xdeadbeef;
unsigned int curtime = Sys_Milliseconds();
unsigned long pext = 0, pext2 = 0, huffcrc=0;
unsigned long pext = 0, pext2 = 0, huffcrc=0, mtu=0;
Con_TPrintf (TLC_S2C_CHALLENGE);
s = MSG_ReadString ();
@ -2317,7 +2253,7 @@ void CL_ConnectionlessPacket (void)
cls.protocol = CP_QUAKE3;
cls.challenge = atoi(s+17);
CL_SendConnectPacket (0, 0, 0/*, ...*/);
CL_SendConnectPacket (0, 0, 0, 0/*, ...*/);
}
else
{
@ -2412,6 +2348,8 @@ void CL_ConnectionlessPacket (void)
pext = MSG_ReadLong ();
else if (c == PROTOCOL_VERSION_FTE2)
pext2 = MSG_ReadLong ();
else if (c == PROTOCOL_VERSION_FRAGMENT)
mtu = MSG_ReadLong ();
else if (c == PROTOCOL_VERSION_VARLENGTH)
{
int len = MSG_ReadLong();
@ -2421,14 +2359,14 @@ void CL_ConnectionlessPacket (void)
MSG_ReadSkip(len); /*payload*/
}
#ifdef HUFFNETWORK
else if (c == (('H'<<0) + ('U'<<8) + ('F'<<16) + ('F' << 24)))
else if (c == PROTOCOL_VERSION_HUFFMAN)
huffcrc = MSG_ReadLong ();
#endif
//else if (c == PROTOCOL_VERSION_...)
else
MSG_ReadLong ();
}
CL_SendConnectPacket (pext, pext2, huffcrc/*, ...*/);
CL_SendConnectPacket (mtu, pext, pext2, huffcrc/*, ...*/);
return;
}
#ifdef Q2CLIENT
@ -2523,6 +2461,7 @@ void CL_ConnectionlessPacket (void)
if (c == S2C_CONNECTION)
{
int compress;
int mtu;
#ifdef Q2CLIENT
client_connect: //fixme: make function
#endif
@ -2535,9 +2474,11 @@ client_connect: //fixme: make function
return;
}
compress = cls.netchan.compress;
mtu = cls.netchan.fragmentsize;
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.qport);
CL_ParseEstablished();
cls.netchan.fragmentsize = mtu;
cls.netchan.compress = compress;
CL_ParseEstablished();
#ifdef Q3CLIENT
if (cls.protocol != CP_QUAKE3)
#endif
@ -2813,7 +2754,6 @@ void CL_ReadPackets (void)
case CP_QUAKEWORLD:
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
player_state_t *n,*o;
MSG_BeginReading(cls.netchan.netprim);
cls.netchan.last_received = realtime;
cls.netchan.outgoing_sequence = cls.netchan.incoming_sequence;

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cl_ignore.h"
void CL_GetNumberedEntityInfo (int num, float *org, float *ang);
void CLNQ_ParseDarkPlaces5Entities(void);
void CLDP_ParseDarkPlaces5Entities(void);
void CL_SetStatInt (int pnum, int stat, int value);
static qboolean CL_CheckModelResources (char *name);
@ -101,8 +101,8 @@ char *svc_strings[] =
"svc_serverinfo",
"svc_updatepl",
"MVD svc_nails2",
"BAD svc_unused",
"FTE svc_view2",
"svcfte_soundextended",
"svcfte_soundlistshort",
"FTE svc_lightstylecol",
"FTE svc_bulletentext", // obsolete
"FTE svc_lightnings",
@ -140,7 +140,7 @@ char *svc_strings[] =
"svcfte_cgamepacket",
"svcfte_voicechat",
"svcfte_setangledelta",
"???",
"svcfte_updateentities",
"???",
"???",
"???",
@ -280,7 +280,7 @@ int CL_CalcNet (void)
else if (frame->invalid)
packet_latency[i&NET_TIMINGSMASK] = 9998; // invalid delta
else
packet_latency[i&NET_TIMINGSMASK] = (frame->receivedtime - frame->senttime)*20;
packet_latency[i&NET_TIMINGSMASK] = (frame->receivedtime - frame->senttime)*60;
}
lost = 0;
@ -322,6 +322,7 @@ int CL_CalcNet (void)
//returns true if the download is going to be downloaded after the call.
qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags)
{
char *ext;
downloadlist_t *dl;
qboolean webdl = false;
if (localname && !strncmp(filename, "http://", 7))
@ -336,8 +337,8 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags)
if (cls.demoplayback && cls.demoplayback != DPB_EZTV)
return false;
}
if (strchr(localname, '\\') || strchr(localname, ':') || strstr(localname, ".."))
ext = COM_FileExtension(localname);
if (!stricmp(localname, "dll") || !stricmp(localname, "so") || strchr(localname, '\\') || strchr(localname, ':') || strstr(localname, ".."))
{
Con_Printf("Denying download of \"%s\"\n", filename);
return false;
@ -658,7 +659,6 @@ Returns true if the file exists, returns false if it triggered a download.
qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname, unsigned int flags)
{ //returns false if we don't have the file yet.
if (flags & DLLF_NONGAME)
{
/*pak/pk3 downloads have an explicit leading package/ as an internal/network marker*/
@ -1758,6 +1758,29 @@ void CL_ParseDownload (void)
size = MSG_ReadShort ();
percent = MSG_ReadByte ();
if (size == -2)
{
/*quakeforge*/
MSG_ReadString();
return;
}
if (size == -3)
{
char *localname;
Q_strncpyz(name, MSG_ReadString(), sizeof(name));
localname = MSG_ReadString();
/*quakeforge http download redirection*/
if (cls.downloadqw)
{
Con_TPrintf (TL_CLS_DOWNLOAD_ISSET);
VFS_CLOSE (cls.downloadqw);
cls.downloadqw = NULL;
}
CL_DownloadFailed(cls.downloadremotename);
CL_CheckOrEnqueDownloadFile(name, localname, DLLF_IGNOREFAILED);
return;
}
if (cls.demoplayback && cls.demoplayback != DPB_EZTV)
{
if (size > 0)
@ -2244,6 +2267,7 @@ void CLQW_ParseServerData (void)
// game directory
str = MSG_ReadString ();
Con_DPrintf("Server is using gamedir \"%s\"\n", str);
if (!*str)
str = "qw";
@ -2275,13 +2299,26 @@ void CLQW_ParseServerData (void)
Wads_Flush();
}
/*mvds have different parsing*/
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
int i,j;
MSG_ReadFloat();
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
cl.allocated_client_slots = MSG_ReadByte();
if (cl.allocated_client_slots > MAX_CLIENTS)
cl.allocated_client_slots = MAX_CLIENTS;
}
cl.gametime = MSG_ReadFloat();
cl.gametimemark = realtime;
cl.oldgametime = cl.gametime;
cl.oldgametimemark = realtime;
for (j = 0; j < MAX_SPLITS; j++)
{
cl.playernum[j] = MAX_CLIENTS + j;
cl.playernum[j] = cl.allocated_client_slots + j;
for (i = 0; i < UPDATE_BACKUP; i++)
{
cl.frames[i].playerstate[cl.playernum[j]].pm_type = PM_SPECTATOR;
@ -2292,7 +2329,32 @@ void CLQW_ParseServerData (void)
cl.splitclients = 1;
}
else
else if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
cl.allocated_client_slots = MSG_ReadByte();
if (cl.allocated_client_slots > MAX_CLIENTS)
{
cl.allocated_client_slots = MAX_CLIENTS;
Host_EndGame("Server sent us too many alternate clients\n");
}
/*parsing here is slightly different to allow us 255 max players instead of 127*/
cl.splitclients = MSG_ReadByte();
if (cl.splitclients & 128)
{
cl.spectator = true;
cl.splitclients &= ~128;
}
if (cl.splitclients > MAX_SPLITS)
Host_EndGame("Server sent us too many alternate clients\n");
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
cl.playernum[pnum] = MSG_ReadByte();
if (cl.playernum[pnum] >= cl.allocated_client_slots)
Host_EndGame("unsupported local player slot\n");
}
}
else
{
// parse player slot, high bit means spectator
pnum = MSG_ReadByte ();
@ -2305,6 +2367,9 @@ void CLQW_ParseServerData (void)
cl.playernum[clnum] &= ~128;
}
if (cl.playernum[clnum] >= cl.allocated_client_slots)
Host_EndGame("unsupported local player slot\n");
if (!(cls.fteprotocolextensions & PEXT_SPLITSCREEN))
break;
@ -2884,7 +2949,7 @@ void CLNQ_ParseClientdata (void)
}
else if (CPNQ_IS_DP)
{
/*nothing*/
/*nothing in dp6+*/
}
else
{
@ -2935,7 +3000,7 @@ void CLNQ_ParseClientdata (void)
}
}
if (CPNQ_IS_DP || cls.protocol_nq == CPNQ_DP5)
if (CPNQ_IS_DP)
{
if (bits & DPSU_VIEWZOOM)
{
@ -3313,7 +3378,7 @@ void CL_ParseBaseline2 (void)
{
entity_state_t es;
CL_ParseDelta(&nullentitystate, &es, (unsigned short)MSG_ReadShort(), true);
CLQW_ParseDelta(&nullentitystate, &es, (unsigned short)MSG_ReadShort(), true);
if (!CL_CheckBaselines(es.number))
Host_EndGame("CL_ParseBaseline2: check baselines failed with size %i", es.number);
memcpy(cl_baselines + es.number, &es, sizeof(es));
@ -3379,7 +3444,7 @@ void CL_ParseStatic (int version)
}
else
{
CL_ParseDelta(&nullentitystate, &es, MSG_ReadShort(), true);
CLQW_ParseDelta(&nullentitystate, &es, MSG_ReadShort(), true);
es.number+=MAX_EDICTS;
for (i = 0; i < cl.num_statics; i++)
@ -3416,14 +3481,24 @@ void CL_ParseStatic (int version)
#ifdef PEXT_SCALE
ent->scale = es.scale/16.0;
#endif
ent->shaderRGBAf[0] = (8.0f/255.0f)*es.colormod[0];
ent->shaderRGBAf[1] = (8.0f/255.0f)*es.colormod[1];
ent->shaderRGBAf[2] = (8.0f/255.0f)*es.colormod[2];
ent->shaderRGBAf[3] = es.trans/255;
ent->shaderRGBAf[0] = (8.0f/256.0f)*es.colormod[0];
ent->shaderRGBAf[1] = (8.0f/256.0f)*es.colormod[1];
ent->shaderRGBAf[2] = (8.0f/256.0f)*es.colormod[2];
ent->shaderRGBAf[3] = es.trans/255.0f;
ent->fatness = es.fatness/16.0;
ent->abslight = es.abslight;
ent->flags = es.flags;
if (es.effects & NQEF_ADDITIVE)
ent->flags |= Q2RF_ADDITIVE;
if (es.effects & EF_NODEPTHTEST)
ent->flags |= RF_NODEPTHTEST;
if (es.effects & DPEF_NOSHADOW)
ent->flags |= RF_NOSHADOW;
if (es.trans != 0xff)
ent->flags |= Q2RF_TRANSLUCENT;
VectorCopy (es.origin, ent->origin);
VectorCopy (es.angles, ent->angles);
es.angles[0]*=-1;
@ -4102,8 +4177,8 @@ void CL_MuzzleFlash (int destsplit)
dl = CL_AllocDlight (-i);
VectorCopy (pl->origin, dl->origin); //set it's origin
if (pl->hullnum & 0x80) /*hull is 0-based, so origin is bottom of model, move the light up slightly*/
dl->origin[2] += 24;
if (pl->szmins[2] == 0) /*hull is 0-based, so origin is bottom of model, move the light up slightly*/
dl->origin[2] += pl->szmaxs[2]/2;
AngleVectors(pl->viewangles, dl->axis[0], dl->axis[1], dl->axis[2]);
AngleVectors (pl->viewangles, fv, rv, uv); //shift it up a little
@ -4977,8 +5052,8 @@ void CL_DumpPacket(void)
}
}
#define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
#define SHOWNET2(x, y) if(cl_shownet.value==2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x);
#define SHOWNET(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
#define SHOWNET2(x, y) if(cl_shownet.value>=2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x);
/*
=====================
CL_ParseServerMessage
@ -5006,7 +5081,7 @@ void CLQW_ParseServerMessage (void)
//
if (cl_shownet.value == 1)
Con_TPrintf (TL_INT_SPACE,net_message.cursize);
else if (cl_shownet.value == 2)
else if (cl_shownet.value >= 2)
Con_TPrintf (TLC_LINEBREAK_MINUS);
@ -5421,6 +5496,9 @@ void CLQW_ParseServerMessage (void)
CL_ParsePacketEntities (true);
cl.ackedinputsequence = cl.validsequence;
break;
case svcfte_updateentities:
CLFTE_ParseEntities();
break;
case svc_maxspeed:
cl.maxspeed[destsplit] = MSG_ReadFloat();
@ -6216,7 +6294,7 @@ void CLNQ_ParseServerMessage (void)
CLNQ_SignonReply ();
}
//well, it's really any protocol, but we're only going to support version 5.
CLNQ_ParseDarkPlaces5Entities();
CLDP_ParseDarkPlaces5Entities();
break;
#ifdef PEXT_CSQC

View File

@ -26,14 +26,14 @@ cvar_t cl_pushlatency = SCVAR("pushlatency","-999");
extern frame_t *view_frame;
#define MAX_PARSE_ENTITIES 1024
extern entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
extern float pm_airaccelerate;
extern usercmd_t independantphysics[MAX_SPLITS];
#ifdef Q2CLIENT
#define MAX_PARSE_ENTITIES 1024
extern entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
char *Get_Q2ConfigString(int i);
#ifdef Q2BSPS
@ -121,7 +121,7 @@ void CLQ2_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t en
if (ent->number == cl.playernum[0]+1)
continue;
if (ent->solid == 31)
if (ent->solid == ES_SOLID_BSP)
{ // special value for bmodel
cmodel = cl.model_precache[ent->modelindex];
if (!cmodel)
@ -395,35 +395,15 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user
pmove.pm_type = from->pm_type;
pmove.cmd = *u;
pmove.skipent = cl.playernum[pnum]+1;
movevars.entgravity = cl.entgravity[pnum];
movevars.maxspeed = cl.maxspeed[pnum];
movevars.bunnyspeedcap = cl.bunnyspeedcap;
pmove.onladder = false;
pmove.hullnum = from->hullnum;
if (cl.worldmodel->fromgame != fg_quake)
{
player_mins[0] = -16;
player_mins[1] = -16;
player_mins[2] = -24;
player_maxs[0] = 16;
player_maxs[1] = 16;
player_maxs[2] = 32;
VectorScale(player_mins, pmove.hullnum/56.0f, player_mins);
VectorScale(player_maxs, pmove.hullnum/56.0f, player_maxs);
}
else
{
VectorCopy(cl.worldmodel->hulls[pmove.hullnum&(MAX_MAP_HULLSM-1)].clip_mins, player_mins);
VectorCopy(cl.worldmodel->hulls[pmove.hullnum&(MAX_MAP_HULLSM-1)].clip_maxs, player_maxs);
}
if (pmove.hullnum & 128)
{ //this hack is for hexen2.
player_maxs[2] -= player_mins[2];
player_mins[2] = 0;
}
VectorCopy(from->szmins, player_mins);
VectorCopy(from->szmaxs, player_maxs);
PM_PlayerMove (cl.gamespeed);
@ -439,7 +419,9 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user
to->weaponframe = from->weaponframe;
to->pm_type = from->pm_type;
to->hullnum = from->hullnum;
VectorCopy(player_mins, to->szmins);
VectorCopy(player_maxs, to->szmaxs);
}
@ -750,6 +732,109 @@ void CL_CalcClientTime(void)
}
}
static void CL_DecodeStateSize(unsigned short solid, int modelindex, vec3_t mins, vec3_t maxs)
{
if (solid == ES_SOLID_BSP)
{
if (modelindex < MAX_MODELS && cl.model_precache[modelindex] && !cl.model_precache[modelindex]->needload)
{
VectorCopy(cl.model_precache[modelindex]->mins, mins);
VectorCopy(cl.model_precache[modelindex]->maxs, maxs);
}
else
{
VectorClear(mins);
VectorClear(maxs);
}
}
else if (solid)
{
mins[0] = -8*(solid&31);
mins[1] = -8*(solid&31);
mins[2] = -8*((solid>>5)&31);
maxs[0] = 8*(solid&31);
maxs[1] = 8*(solid&31);
maxs[2] = 8*((solid>>10)&63) - 32;
}
else
{
VectorClear(mins);
VectorClear(maxs);
}
}
/*called on packet reception*/
void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int sequence)
{
/*update the prediction info*/
int pmtype;
if (state->u.q1.pmovetype == MOVETYPE_NOCLIP)
{
if (cls.z_ext & Z_EXT_PM_TYPE_NEW)
pmtype = PM_SPECTATOR;
else
pmtype = PM_OLD_SPECTATOR;
}
else if (state->u.q1.pmovetype == MOVETYPE_FLY)
pmtype = PM_FLY;
else if (state->u.q1.pmovetype == MOVETYPE_NONE)
pmtype = PM_NONE;
else if (state->u.q1.pmovetype == MOVETYPE_BOUNCE || state->u.q1.pmovetype == MOVETYPE_TOSS)
pmtype = PM_DEAD;
else
pmtype = PM_NORMAL;
plstate->pm_type = pmtype;
VectorCopy(state->origin, plstate->origin);
VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity);
plstate->messagenum = sequence;
CL_DecodeStateSize(state->solid, state->modelindex, plstate->szmins, plstate->szmaxs);
}
/*called once every rendered frame*/
qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence)
{
int msec, oldphysent;
usercmd_t cmd;
player_state_t start, exact;
int pnum;
if (state->number-1 > cl.allocated_client_slots || cl.intermission)
return false;
/*local players just interpolate for now. the prediction code will move it to the right place afterwards*/
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
if (state->number-1 == cl.playernum[pnum])
return false;
}
memset(&cmd, 0, sizeof(cmd));
memset(&start, 0, sizeof(start));
CL_PlayerFrameUpdated(&start, state, sequence);
msec = 500*(realtime - cls.latency + 0.02 - cl.frames[sequence & UPDATE_MASK].receivedtime);
cmd.msec = bound(0, msec, 255);
cmd.forwardmove = state->u.q1.movement[0];
cmd.sidemove = state->u.q1.movement[1];
cmd.upmove = state->u.q1.movement[2];
oldphysent = pmove.numphysent;
pmove.skipent = state->number-1;
CL_PredictUsercmd (0, &start, &exact, &cmd); //uses player 0's maxspeed/grav...
pmove.numphysent = oldphysent;
/*need to update the entity's angles and origin so the linkentities function puts it in the correct predicted place*/
le->angles[0] = state->angles[0];
le->angles[1] = state->angles[1];
le->angles[2] = state->angles[2];
VectorCopy (exact.origin, le->origin);
return true;
}
/*
==============
CL_PredictMove
@ -769,7 +854,7 @@ void CL_PredictMovePNum (int pnum)
float *org;
float stepheight = 0;
cl.nolocalplayer[pnum] = false;
cl.nolocalplayer[pnum] = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS);
#ifdef Q2CLIENT
if (cls.protocol == CP_QUAKE2)
@ -874,7 +959,8 @@ fixedorg:
// predict forward until cl.time <= to->senttime
oldphysent = pmove.numphysent;
CL_SetSolidPlayers (cl.playernum[pnum]);
CL_SetSolidPlayers();
pmove.skipent = cl.playernum[pnum]+1;
to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK];
@ -940,8 +1026,6 @@ fixedorg:
cls.netchan.outgoing_sequence; i++)
{
to = &cl.frames[(cl.ackedinputsequence+i) & UPDATE_MASK];
if (cl.intermission)
to->playerstate->pm_type = PM_FLY;
CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]]
, &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]);
@ -965,6 +1049,14 @@ fixedorg:
cl.onground[pnum] = pmove.onground;
}
stepheight = to->playerstate[cl.playernum[pnum]].origin[2] - from->playerstate[cl.playernum[pnum]].origin[2];
if (cl.nolocalplayer[pnum])
{
//keep the entity tracking the prediction position, so mirrors don't go all weird
VectorCopy(to->playerstate[cl.playernum[pnum]].origin, cl.lerpents[cl.playernum[pnum]+1].origin);
VectorScale(to->cmd[pnum].angles, 360.0f / 0xffff, cl.lerpents[cl.playernum[pnum]+1].angles);
cl.lerpents[cl.playernum[pnum]+1].angles[0] *= -0.333;
}
}
pmove.numphysent = oldphysent;

View File

@ -73,7 +73,7 @@ typedef struct
qboolean onground;
qboolean jump_held;
int jump_msec; // hack for fixing bunny-hop flickering on non-ZQuake servers
int hullnum;
vec3_t szmins, szmaxs;
float lerpstarttime;
int oldframe;
@ -347,7 +347,7 @@ typedef struct
{
CPNQ_ID,
CPNQ_PROQUAKE3_4,
CPNQ_FITZ666,
CPNQ_FITZ666, /*and rmqe999 protocol*/
CPNQ_DP5,
CPNQ_DP6,
CPNQ_DP7
@ -462,6 +462,7 @@ typedef struct {
//previous rendering frame (for trails)
vec3_t lastorigin;
qboolean isnew;
qboolean isplayer;
//intermediate values for frame lerping
float framelerpdeltatime;
@ -773,7 +774,7 @@ dlight_t *CL_NewDlightRGB (int key, const vec3_t origin, float radius, float tim
dlight_t *CL_NewDlightCube (int key, const vec3_t origin, vec3_t angles, float radius, float time, vec3_t colours);
void CL_DecayLights (void);
void CL_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int bits, qboolean);
void CLQW_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int bits, qboolean);
void CL_Init (void);
void Host_WriteConfiguration (void);
@ -1000,7 +1001,7 @@ void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, struct model_s *model, int sta
//
// cl_ents.c
//
void CL_SetSolidPlayers (int playernum);
void CL_SetSolidPlayers (void);
void CL_SetUpPlayerPrediction(qboolean dopred);
void CL_LinkStaticEntities(void *pvs);
void CL_TransitionEntities (void); /*call at the start of the frame*/
@ -1008,6 +1009,7 @@ void CL_EmitEntities (void);
void CL_ClearProjectiles (void);
void CL_ParseProjectiles (int modelindex, qboolean nails2);
void CL_ParsePacketEntities (qboolean delta);
void CLFTE_ParseEntities (void);
void CL_SetSolidEntities (void);
void CL_ParsePlayerinfo (void);
void CL_ParseClientPersist(void);
@ -1057,9 +1059,10 @@ void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd);
void CSQC_WorldLoaded(void);
qboolean CSQC_ParseTempEntity(unsigned char firstbyte);
qboolean CSQC_ConsoleCommand(char *cmd);
qboolean CSQC_KeyPress(int key, int unicode, qboolean down);
qboolean CSQC_MouseMove(float xdelta, float ydelta);
qboolean CSQC_MousePosition(float xabs, float yabs);
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid);
qboolean CSQC_MouseMove(float xdelta, float ydelta, int devid);
qboolean CSQC_MousePosition(float xabs, float yabs, int devid);
qboolean CSQC_Accelerometer(float x, float y, float z);
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation);
void CSQC_ParseEntities(void);
qboolean CSQC_SettingListener(void);

View File

@ -562,7 +562,7 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
// set everything to the state we are delta'ing from
*to = *from;
VectorCopy (from->origin, to->old_origin);
VectorCopy (from->origin, to->u.q2.old_origin);
to->number = number;
if (bits & Q2U_MODEL)
@ -570,9 +570,9 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
if (bits & Q2U_MODEL2)
to->modelindex2 = MSG_ReadByte ();
if (bits & Q2U_MODEL3)
to->modelindex3 = MSG_ReadByte ();
to->u.q2.modelindex3 = MSG_ReadByte ();
if (bits & Q2U_MODEL4)
to->modelindex4 = MSG_ReadByte ();
to->u.q2.modelindex4 = MSG_ReadByte ();
if (bits & Q2U_FRAME8)
to->frame = MSG_ReadByte ();
@ -594,11 +594,11 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
to->effects = MSG_ReadShort();
if ( (bits & (Q2U_RENDERFX8|Q2U_RENDERFX16)) == (Q2U_RENDERFX8|Q2U_RENDERFX16) )
to->renderfx = MSG_ReadLong();
to->u.q2.renderfx = MSG_ReadLong();
else if (bits & Q2U_RENDERFX8)
to->renderfx = MSG_ReadByte();
to->u.q2.renderfx = MSG_ReadByte();
else if (bits & Q2U_RENDERFX16)
to->renderfx = MSG_ReadShort();
to->u.q2.renderfx = MSG_ReadShort();
if (bits & Q2U_ORIGIN1)
to->origin[0] = MSG_ReadCoord ();
@ -615,15 +615,15 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
to->angles[2] = MSG_ReadAngle();
if (bits & Q2U_OLDORIGIN)
MSG_ReadPos (to->old_origin);
MSG_ReadPos (to->u.q2.old_origin);
if (bits & Q2U_SOUND)
to->sound = MSG_ReadByte ();
to->u.q2.sound = MSG_ReadByte ();
if (bits & Q2U_EVENT)
to->event = MSG_ReadByte ();
to->u.q2.event = MSG_ReadByte ();
else
to->event = 0;
to->u.q2.event = 0;
if (bits & Q2U_SOLID)
to->solid = MSG_ReadShort ();
@ -653,13 +653,13 @@ void CLQ2_DeltaEntity (q2frame_t *frame, int newnum, entity_state_t *old, int bi
// some data changes will force no lerping
if (state->modelindex != ent->current.modelindex
|| state->modelindex2 != ent->current.modelindex2
|| state->modelindex3 != ent->current.modelindex3
|| state->modelindex4 != ent->current.modelindex4
|| state->u.q2.modelindex3 != ent->current.u.q2.modelindex3
|| state->u.q2.modelindex4 != ent->current.u.q2.modelindex4
|| abs(state->origin[0] - ent->current.origin[0]) > 512
|| abs(state->origin[1] - ent->current.origin[1]) > 512
|| abs(state->origin[2] - ent->current.origin[2]) > 512
|| state->event == Q2EV_PLAYER_TELEPORT
|| state->event == Q2EV_OTHER_TELEPORT
|| state->u.q2.event == Q2EV_PLAYER_TELEPORT
|| state->u.q2.event == Q2EV_OTHER_TELEPORT
)
{
ent->serverframe = -99;
@ -672,15 +672,15 @@ void CLQ2_DeltaEntity (q2frame_t *frame, int newnum, entity_state_t *old, int bi
// duplicate the current state so lerping doesn't hurt anything
ent->prev = *state;
if (state->event == Q2EV_OTHER_TELEPORT)
if (state->u.q2.event == Q2EV_OTHER_TELEPORT)
{
VectorCopy (state->origin, ent->prev.origin);
VectorCopy (state->origin, ent->lerp_origin);
}
else
{
VectorCopy (state->old_origin, ent->prev.origin);
VectorCopy (state->old_origin, ent->lerp_origin);
VectorCopy (state->u.q2.old_origin, ent->prev.origin);
VectorCopy (state->u.q2.old_origin, ent->lerp_origin);
}
}
else
@ -975,7 +975,7 @@ void CLQ2_FireEntityEvents (q2frame_t *frame)
{
num = (frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1);
s1 = &cl_parse_entities[num];
if (s1->event)
if (s1->u.q2.event)
CLQ2_EntityEvent (s1);
// EF_TELEPORTER acts like an event, but is not cleared each frame
@ -1197,7 +1197,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
cent = &cl_entities[s1->number];
effects = s1->effects;
renderfx = s1->renderfx;
renderfx = s1->u.q2.renderfx;
ent.rtype = RT_MODEL;
ent.keynum = s1->number;
@ -1207,6 +1207,9 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
ent.shaderRGBAf[1] = 1;
ent.shaderRGBAf[2] = 1;
ent.shaderRGBAf[3] = 1;
ent.glowmod[0] = 1;
ent.glowmod[1] = 1;
ent.glowmod[2] = 1;
ent.fatness = 0;
ent.scoreboard = NULL;
@ -1260,7 +1263,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
{ // step origin discretely, because the frames
// do the animation properly
VectorCopy (cent->current.origin, ent.origin);
VectorCopy (cent->current.old_origin, ent.oldorigin);
VectorCopy (cent->current.u.q2.old_origin, ent.oldorigin);
}
else
{ // interpolate origin
@ -1558,14 +1561,14 @@ void CLQ2_AddPacketEntities (q2frame_t *frame)
ent.shaderRGBAf[3] = 1;
//PGM
}
if (s1->modelindex3)
if (s1->u.q2.modelindex3)
{
ent.model = cl.model_precache[s1->modelindex3];
ent.model = cl.model_precache[s1->u.q2.modelindex3];
V_AddEntity (&ent);
}
if (s1->modelindex4)
if (s1->u.q2.modelindex4)
{
ent.model = cl.model_precache[s1->modelindex4];
ent.model = cl.model_precache[s1->u.q2.modelindex4];
V_AddEntity (&ent);
}

View File

@ -148,7 +148,7 @@ char *ReadGreyTargaFile (qbyte *data, int flen, tgaheader_t *tgahead, int asgrey
}
//remember to free it
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey)
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *hasalpha, int asgrey)
{
unsigned char *data;
@ -221,6 +221,8 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey
{
if (tgaheader.bpp == 8)
return NULL;
*hasalpha = (tgaheader.bpp==32);
}
if (tgaheader.version == 11)
{
@ -256,6 +258,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey
palette[row][2] = *data++;
palette[row][3] = *data++;
}
*hasalpha = true;
break;
}
}
@ -502,6 +505,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey
return NULL;
mul = tgaheader.bpp/8;
*hasalpha = mul==4;
//flip +convert to 32 bit
if (asgrey)
outrow = &initbuf[(int)(0)*tgaheader.width];
@ -887,7 +891,7 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i
if (!(png_ptr = qpng_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
{
fclose(fp);
return false;
return false;
}
if (!(info_ptr = qpng_create_info_struct(png_ptr)))
@ -899,6 +903,7 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i
if (setjmp(png_jmpbuf(png_ptr)))
{
err:
qpng_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return false;
@ -920,6 +925,8 @@ int Image_WritePNG (char *filename, int compression, qbyte *pixels, int width, i
qpng_write_info(png_ptr, info_ptr);
row_pointers = BZ_Malloc (sizeof(png_byte *) * height);
if (!row_pointers)
goto err;
for (i = 0; i < height; i++)
row_pointers[height - i - 1] = pixels + i * width * 3;
qpng_write_image(png_ptr, row_pointers);
@ -2262,10 +2269,10 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
#endif
//returns r8g8b8a8
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, char *fname)
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean *hasalpha, char *fname)
{
qbyte *data;
if ((data = ReadTargaFile(buf, len, width, height, false)))
if ((data = ReadTargaFile(buf, len, width, height, hasalpha, false)))
{
TRACE(("dbg: Read32BitImageFile: tga\n"));
return data;
@ -2350,6 +2357,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
texid_t tex;
// int h;
char fname[MAX_QPATH], nicename[MAX_QPATH];
qboolean hasalpha;
int i, e;
@ -2411,12 +2419,12 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
if (buf)
{
if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, fname)))
hasalpha = false;
if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, &hasalpha, fname)))
{
extern cvar_t vid_hardwaregamma;
if (!(flags&IF_NOGAMMA) && !vid_hardwaregamma.value)
BoostGamma(data, image_width, image_height);
tex = R_LoadTexture32 (name, image_width, image_height, data, (flags | IF_REPLACE) + (i << IF_TEXTYPESHIFT));
BZ_Free(data);
@ -2484,13 +2492,16 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
return tex;
}
#endif
if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, fname)))
hasalpha = false;
if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, &hasalpha, fname)))
{
extern cvar_t vid_hardwaregamma;
if (!(flags&IF_NOGAMMA) && !vid_hardwaregamma.value)
BoostGamma(data, image_width, image_height);
if (!(flags & IF_NOALPHA))
if (hasalpha)
flags &= ~IF_NOALPHA;
else if (!(flags & IF_NOALPHA))
{
unsigned int alpha_width, alpha_height, p;
char aname[MAX_QPATH];
@ -2502,7 +2513,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
snprintf(aname, sizeof(aname)-1, tex_path[i].path, nicename, va("_alpha%s", tex_extensions[e].name));
if ((alph = COM_LoadFile (aname, 5)))
{
if ((alphadata = Read32BitImageFile(alph, com_filesize, &alpha_width, &alpha_height, aname)))
if ((alphadata = Read32BitImageFile(alph, com_filesize, &alpha_width, &alpha_height, &hasalpha, aname)))
{
if (alpha_width == image_width && alpha_height == image_height)
{
@ -2589,6 +2600,7 @@ texid_t R_LoadBumpmapTexture(char *name, char *subpath)
texid_t tex;
// int h;
char fname[MAX_QPATH], nicename[MAX_QPATH];
qboolean hasalpha;
static char *extensions[] =
{//reverse order of preference - (match commas with optional file types)
@ -2635,7 +2647,7 @@ texid_t R_LoadBumpmapTexture(char *name, char *subpath)
if ((buf = COM_LoadFile (fname, 5)))
{
if ((data = ReadTargaFile(buf, com_filesize, &image_width, &image_height, 2))) //Only load a greyscale image.
if ((data = ReadTargaFile(buf, com_filesize, &image_width, &image_height, &hasalpha, 2))) //Only load a greyscale image.
{
TRACE(("dbg: Mod_LoadBumpmapTexture: tga %s loaded\n", name));
TEXASSIGNF(tex, R_LoadTexture8Bump(name, image_width, image_height, data, IF_NOALPHA|IF_NOGAMMA));

View File

@ -68,7 +68,7 @@ typedef struct {
HANDLE rawinputhandle;
} handles;
int playerid;
int qdeviceid;
} keyboard_t;
typedef struct {
@ -77,7 +77,7 @@ typedef struct {
} handles;
int numbuttons;
int playerid;
int qdeviceid; /*the device id controls which player slot it controls, if splitscreen splits it that way*/
volatile int buttons;
volatile int oldbuttons;
@ -976,7 +976,7 @@ void IN_RawInput_Init(void)
rawmice[rawmicecount].handles.rawinputhandle = pRawInputDeviceList[i].hDevice;
rawmice[rawmicecount].numbuttons = 10;
rawmice[rawmicecount].pos[0] = RI_INVALID_POS;
rawmice[rawmicecount].playerid = rawmicecount;
rawmice[rawmicecount].qdeviceid = rawmicecount;
rawmicecount++;
break;
case RIM_TYPEKEYBOARD:
@ -984,7 +984,7 @@ void IN_RawInput_Init(void)
continue;
rawkbd[rawkbdcount].handles.rawinputhandle = pRawInputDeviceList[i].hDevice;
rawkbd[rawkbdcount].playerid = rawmicecount;
rawkbd[rawkbdcount].qdeviceid = rawkbdcount;
rawkbdcount++;
break;
default:
@ -1238,6 +1238,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
int i;
/*each device will be processed when its player comes to be processed*/
int wpnum;
wpnum = cl.splitclients;
if (wpnum < 1)
@ -1245,7 +1246,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
if (cl_forcesplitclient.ival)
wpnum = (cl_forcesplitclient.ival-1) % wpnum;
else
wpnum = mouse->playerid % wpnum;
wpnum = mouse->qdeviceid % wpnum;
if (wpnum != pnum)
return;
@ -1255,13 +1256,13 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
if ( (mouse->buttons & (1<<i)) &&
!(mouse->oldbuttons & (1<<i)) )
{
Key_Event (pnum, K_MOUSE1 + i, 0, true);
Key_Event (mouse->qdeviceid, K_MOUSE1 + i, 0, true);
}
if ( !(mouse->buttons & (1<<i)) &&
(mouse->oldbuttons & (1<<i)) )
{
Key_Event (pnum, K_MOUSE1 + i, 0, false);
Key_Event (mouse->qdeviceid, K_MOUSE1 + i, 0, false);
}
}
mouse->oldbuttons = mouse->buttons;
@ -1273,15 +1274,15 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
{
while(mouse->wheeldelta <= -mfwt)
{
Key_Event (pnum, K_MWHEELUP, 0, true);
Key_Event (pnum, K_MWHEELUP, 0, false);
Key_Event (mouse->qdeviceid, K_MWHEELUP, 0, true);
Key_Event (mouse->qdeviceid, K_MWHEELUP, 0, false);
mouse->wheeldelta += mfwt;
}
while(mouse->wheeldelta >= mfwt)
{
Key_Event (pnum, K_MWHEELDOWN, 0, true);
Key_Event (pnum, K_MWHEELDOWN, 0, false);
Key_Event (mouse->qdeviceid, K_MWHEELDOWN, 0, true);
Key_Event (mouse->qdeviceid, K_MWHEELDOWN, 0, false);
mouse->wheeldelta -= mfwt;
}
}
@ -1319,7 +1320,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
mx=my=0;
#ifdef PEXT_CSQC
CSQC_MousePosition(mousecursor_x, mousecursor_y);
CSQC_MousePosition(mousecursor_x, mousecursor_y, mouse->qdeviceid);
#endif
}
else
@ -1335,7 +1336,7 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum)
#ifdef PEXT_CSQC
if (mx || my)
if (CSQC_MouseMove(mx, my))
if (CSQC_MouseMove(mx, my, mouse->qdeviceid))
{
mx = 0;
my = 0;
@ -1642,8 +1643,8 @@ void IN_Accumulate (void)
#ifdef USINGRAWINPUT
void IN_RawInput_MouseRead(void)
{
int pnum;
int i, tbuttons, j;
mouse_t *mouse;
// find mouse in our mouse list
for (i = 0; i < rawmicecount; i++)
@ -1654,14 +1655,7 @@ void IN_RawInput_MouseRead(void)
if (i == rawmicecount) // we're not tracking this device
return;
pnum = cl.splitclients;
if (pnum < 1)
pnum = 1;
if (cl_forcesplitclient.ival)
pnum = (cl_forcesplitclient.ival-1) % pnum;
else
pnum = rawmice[i].playerid % pnum;
mouse = &rawmice[i];
// movement
if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
@ -1683,38 +1677,38 @@ void IN_RawInput_MouseRead(void)
// buttons
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN)
Key_Event(pnum, K_MOUSE1, 0, true);
Key_Event(mouse->qdeviceid, K_MOUSE1, 0, true);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP)
Key_Event(pnum, K_MOUSE1, 0, false);
Key_Event(mouse->qdeviceid, K_MOUSE1, 0, false);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN)
Key_Event(pnum, K_MOUSE2, 0, true);
Key_Event(mouse->qdeviceid, K_MOUSE2, 0, true);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP)
Key_Event(pnum, K_MOUSE2, 0, false);
Key_Event(mouse->qdeviceid, K_MOUSE2, 0, false);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN)
Key_Event(pnum, K_MOUSE3, 0, true);
Key_Event(mouse->qdeviceid, K_MOUSE3, 0, true);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP)
Key_Event(pnum, K_MOUSE3, 0, false);
Key_Event(mouse->qdeviceid, K_MOUSE3, 0, false);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN)
Key_Event(pnum, K_MOUSE4, 0, true);
Key_Event(mouse->qdeviceid, K_MOUSE4, 0, true);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP)
Key_Event(pnum, K_MOUSE4, 0, false);
Key_Event(mouse->qdeviceid, K_MOUSE4, 0, false);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN)
Key_Event(pnum, K_MOUSE5, 0, true);
Key_Event(mouse->qdeviceid, K_MOUSE5, 0, true);
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP)
Key_Event(pnum, K_MOUSE5, 0, false);
Key_Event(mouse->qdeviceid, K_MOUSE5, 0, false);
// mouse wheel
if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
{ // If the current message has a mouse_wheel message
if ((SHORT)raw->data.mouse.usButtonData > 0)
{
Key_Event(pnum, K_MWHEELUP, 0, true);
Key_Event(pnum, K_MWHEELUP, 0, false);
Key_Event(mouse->qdeviceid, K_MWHEELUP, 0, true);
Key_Event(mouse->qdeviceid, K_MWHEELUP, 0, false);
}
if ((SHORT)raw->data.mouse.usButtonData < 0)
{
Key_Event(pnum, K_MWHEELDOWN, 0, true);
Key_Event(pnum, K_MWHEELDOWN, 0, false);
Key_Event(mouse->qdeviceid, K_MWHEELDOWN, 0, true);
Key_Event(mouse->qdeviceid, K_MWHEELDOWN, 0, false);
}
}
@ -1724,12 +1718,12 @@ void IN_RawInput_MouseRead(void)
{
if ( (tbuttons & (1<<j)) && !(rawmice[i].buttons & (1<<j)) )
{
Key_Event (pnum, K_MOUSE1 + j, 0, true);
Key_Event (mouse->qdeviceid, K_MOUSE1 + j, 0, true);
}
if ( !(tbuttons & (1<<j)) && (rawmice[i].buttons & (1<<j)) )
{
Key_Event (pnum, K_MOUSE1 + j, 0, false);
Key_Event (mouse->qdeviceid, K_MOUSE1 + j, 0, false);
}
}
@ -1741,7 +1735,6 @@ void IN_RawInput_MouseRead(void)
void IN_RawInput_KeyboardRead(void)
{
int i;
int pnum;
qboolean down;
WPARAM wParam;
LPARAM lParam;
@ -1759,15 +1752,7 @@ void IN_RawInput_KeyboardRead(void)
wParam = (-down) & 0xC0000000;
lParam = MapVirtualKey(raw->data.keyboard.VKey, 0)<<16;
pnum = cl.splitclients;
if (pnum < 1)
pnum = 1;
if (cl_forcesplitclient.ival)
pnum = (cl_forcesplitclient.ival-1) % pnum;
else
pnum = rawkbd[i].playerid % pnum;
IN_TranslateKeyEvent(wParam, lParam, down, pnum);
IN_TranslateKeyEvent(wParam, lParam, down, rawkbd[i].qdeviceid);
}
void IN_RawInput_Read(HANDLE in_device_handle)
@ -2397,7 +2382,7 @@ static int MapKey (int vkey)
return scantokey[key];
}
void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int pnum)
void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int qdeviceid)
{
extern cvar_t in_builtinkeymap;
int qcode;
@ -2419,5 +2404,5 @@ void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int pnum)
}
}
Key_Event (pnum, qcode, unicode, down);
Key_Event (qdeviceid, qcode, unicode, down);
}

View File

@ -1338,9 +1338,10 @@ Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt!
===================
*/
void Key_Event (int pnum, int key, unsigned int unicode, qboolean down)
void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
{
char *kb;
char p[16];
char cmd[1024];
int keystate, oldstate;
@ -1459,7 +1460,7 @@ void Key_Event (int pnum, int key, unsigned int unicode, qboolean down)
if (key_dest == key_game)
{
#ifdef CSQC_DAT
if (CSQC_KeyPress(key, unicode, down)) //give csqc a chance to handle it.
if (CSQC_KeyPress(key, unicode, down, devid)) //give csqc a chance to handle it.
return;
#endif
#ifdef VM_CG
@ -1555,40 +1556,24 @@ void Key_Event (int pnum, int key, unsigned int unicode, qboolean down)
return;
deltaused[key][keystate] = false;
kb = keybindings[key][keystate];
if (pnum)
{
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-p%i %s %i\n", pnum+1, kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
if (keyshift[key] != key)
{
kb = keybindings[keyshift[key]][keystate];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-p%i %s %i\n", pnum+1, kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
}
}
if (devid)
Q_snprintfz (p, sizeof(p), "p %i ", devid+1);
else
*p = 0;
kb = keybindings[key][keystate];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s%s %i\n", p, kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
if (keyshift[key] != key)
{
kb = keybindings[keyshift[key]][keystate];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s %i\n", kb+1, key+oldstate*256);
Q_snprintfz (cmd, sizeof(cmd), "-%s%s %i\n", p, kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
if (keyshift[key] != key)
{
kb = keybindings[keyshift[key]][keystate];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s %i\n", kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
}
}
return;
}
@ -1623,37 +1608,25 @@ void Key_Event (int pnum, int key, unsigned int unicode, qboolean down)
return;
deltaused[key][keystate] = true;
kb = keybindings[key][keystate];
if (pnum)
{
if (kb)
{
if (kb[0] == '+')
{ // button commands add keynum as a parm
Q_snprintfz (cmd, sizeof(cmd), "+p%i %s %i\n", pnum+1, kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
else
{
Q_snprintfz (cmd, sizeof(cmd), "p%i %s\n", pnum+1, kb);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
}
}
if (devid)
Q_snprintfz (p, sizeof(p), "p %i ", devid+1);
else
*p = 0;
kb = keybindings[key][keystate];
if (kb)
{
if (kb)
if (kb[0] == '+')
{ // button commands add keynum as a parm
Q_snprintfz (cmd, sizeof(cmd), "+%s%s %i\n", p, kb+1, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
else
{
if (kb[0] == '+')
{ // button commands add keynum as a parm
Q_snprintfz (cmd, sizeof(cmd), "%s %i\n", kb, key+oldstate*256);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
}
else
{
Cbuf_AddText (kb, bindcmdlevel[key][keystate]);
Cbuf_AddText ("\n", bindcmdlevel[key][keystate]);
}
if (*p)Cbuf_AddText (p, bindcmdlevel[key][keystate]);
Cbuf_AddText (kb, bindcmdlevel[key][keystate]);
Cbuf_AddText ("\n", bindcmdlevel[key][keystate]);
}
}

View File

@ -1464,6 +1464,7 @@ cin_t *Media_Static_TryLoad(char *name)
qbyte *staticfilmimage;
int imagewidth;
int imageheight;
qboolean hasalpha;
int fsize;
char fullname[MAX_QPATH];
@ -1480,7 +1481,7 @@ cin_t *Media_Static_TryLoad(char *name)
}
if ((staticfilmimage = ReadPCXFile(file, fsize, &imagewidth, &imageheight)) || //convert to 32 rgba if not corrupt
(staticfilmimage = ReadTargaFile(file, fsize, &imagewidth, &imageheight, false)) ||
(staticfilmimage = ReadTargaFile(file, fsize, &imagewidth, &imageheight, &hasalpha, false)) ||
#ifdef AVAIL_JPEGLIB
(staticfilmimage = ReadJPEGFile(file, fsize, &imagewidth, &imageheight)) ||
#endif

View File

@ -858,7 +858,7 @@ void M_Menu_Lighting_f (void)
{
"Disabled",
"Enabled",
"Generated",
"Generate",
NULL
};
static const char *loadlitvalues[] =

View File

@ -596,10 +596,7 @@ void Master_AddMaster (char *address, int type, char *description)
return;
}
#ifdef warningmsg
#pragma warningmsg("Master_AddMaster: add ipv6. don't care about tcp/irc.")
#endif
if (adr.type != NA_IP && adr.type != NA_IPX)
if (adr.type != NA_IP && adr.type != NA_IPV6 && adr.type != NA_IPX)
{
Con_Printf("Fixme: unable to poll address family for \"%s\"\n", address);
return;
@ -806,10 +803,6 @@ void NET_SendPollPacket(int len, void *data, netadr_t to)
int ret;
struct sockaddr_qstorage addr;
#ifdef warningmsg
#pragma warningmsg("NET_SendPollPacket: no support for ipv6")
#endif
NetadrToSockadr (&to, &addr);
#ifdef USEIPX
if (((struct sockaddr*)&addr)->sa_family == AF_IPX)

View File

@ -2138,7 +2138,6 @@ static void QCBUILTIN PF_cs_runplayerphysics (progfuncs_t *prinst, struct global
VectorCopy(csqcg.pmove_maxs, player_maxs);
VectorCopy(csqcg.pmove_mins, player_mins);
}
pmove.hullnum = 1;
CL_SetSolidEntities();
@ -3515,9 +3514,8 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
ent->xv->entnum = src->number;
ent->v->modelindex = src->modelindex;
// ent->v->bitmask = src->bitmask;
ent->v->flags = src->flags;
// ent->v->effects = src->effects;
// ent->v->flags = src->flags;
ent->v->effects = src->effects;
//we ignore the q2 state fields
@ -3527,22 +3525,46 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
// ent->v->glowcolor = src->glowcolour;
ent->xv->scale = src->scale/16.0f;
ent->xv->fatness = src->fatness/16.0f;
// ent->v->hexen2flags = src->hexen2flags;
// ent->v->abslight = src->abslight;
// ent->xv->drawflags = src->hexen2flags;
// ent->xv->abslight = src->abslight;
// ent->v->dpflags = src->dpflags;
// ent->v->colormod[0] = (src->colormod[0]/255.0f)*8;
// ent->v->colormod[1] = (src->colormod[1]/255.0f)*8;
// ent->v->colormod[2] = (src->colormod[2]/255.0f)*8;
ent->xv->colormod[0] = src->colormod[0]*(8/256.0f);
ent->xv->colormod[1] = src->colormod[1]*(8/256.0f);
ent->xv->colormod[2] = src->colormod[2]*(8/256.0f);
ent->xv->alpha = src->trans/255.0f;
// ent->v->lightstyle = src->lightstyle;
// ent->v->lightpflags = src->lightpflags;
// ent->xv->style = src->lightstyle;
// ent->xv->pflags = src->lightpflags;
// ent->v->solid = src->solid;
// ent->v->light[0] = src->light[0];
// ent->v->light[1] = src->light[1];
// ent->v->light[2] = src->light[2];
// ent->v->light[3] = src->light[3];
// ent->v->tagentity = src->tagentity;
// ent->v->tagindex = src->tagindex;
// ent->v->color[0] = src->light[0];
// ent->v->color[1] = src->light[1];
// ent->v->color[2] = src->light[2];
// ent->v->light_lev = src->light[3];
// ent->xv->tagentity = src->tagentity;
// ent->xv->tagindex = src->tagindex;
if (src->solid == ES_SOLID_BSP)
{
ent->v->solid = SOLID_BSP;
VectorCopy(model->mins, ent->v->mins);
VectorCopy(model->maxs, ent->v->maxs);
}
else if (src->solid)
{
ent->v->solid = SOLID_BBOX;
ent->v->mins[0] = 8*(src->solid & 31);
ent->v->maxs[0] = ent->v->mins[0];
ent->v->mins[1] = ent->v->mins[0];
ent->v->maxs[1] = ent->v->mins[0];
ent->v->mins[2] = 8*((src->solid>>5) & 31);
ent->v->maxs[2] = 8*((src->solid>>10) & 63) - 32;
}
else
ent->v->solid = SOLID_NOT;
ent->v->movetype = src->u.q1.pmovetype;
ent->v->velocity[0] = src->u.q1.velocity[0];
ent->v->velocity[1] = src->u.q1.velocity[1];
ent->v->velocity[2] = src->u.q1.velocity[2];
if (model)
{
@ -3581,9 +3603,9 @@ void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent)
//ent->v->fatness = srcp->fatness;
ent->xv->alpha = srcp->alpha/255.0f;
// ent->v->colormod[0] = (srcp->colormod[0]/255.0f)*8;
// ent->v->colormod[1] = (srcp->colormod[1]/255.0f)*8;
// ent->v->colormod[2] = (srcp->colormod[2]/255.0f)*8;
// ent->v->colormod[0] = srcp->colormod[0]*(8/256.0f);
// ent->v->colormod[1] = srcp->colormod[1]*(8/256.0f);
// ent->v->colormod[2] = srcp->colormod[2]*(8/256.0f);
// ent->v->effects = srcp->effects;
}
@ -4788,7 +4810,7 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum)
csprogs_checksum = checksum;
csqc_usinglistener = false;
csqc_singlecheats = false;
csqc_singlecheats = cls.demoplayback;
#ifndef CLIENTONLY
if ((sv.state == ss_active && sv.allocated_client_slots == 1) || atoi(Info_ValueForKey(cl.serverinfo, "*cheats")))
csqc_singlecheats = true;
@ -4870,6 +4892,7 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum)
csqc_world.Event_Think = CSQC_Event_Think;
csqc_world.Get_CModel = CSQC_World_ModelForIndex;
csqc_world.Get_FrameState = CSQC_World_GetFrameState;
csqc_world.defaultgravityscale = 1;
World_ClearWorld(&csqc_world);
CSQC_InitFields(); //let the qclib know the field order that the engine needs.
@ -5259,7 +5282,7 @@ qboolean CSQC_DrawView(void)
return true;
}
qboolean CSQC_KeyPress(int key, int unicode, qboolean down)
qboolean CSQC_KeyPress(int key, int unicode, qboolean down, int devid)
{
void *pr_globals;
@ -5267,15 +5290,16 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down)
return false;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = !down;
G_FLOAT(OFS_PARM0) = down?CSIE_KEYDOWN:CSIE_KEYUP;
G_FLOAT(OFS_PARM1) = MP_TranslateFTEtoDPCodes(key);
G_FLOAT(OFS_PARM2) = unicode;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram (csqcprogs, csqcg.input_event);
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_MousePosition(float xabs, float yabs)
qboolean CSQC_MousePosition(float xabs, float yabs, int devid)
{
void *pr_globals;
@ -5283,15 +5307,16 @@ qboolean CSQC_MousePosition(float xabs, float yabs)
return false;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = 3;
G_FLOAT(OFS_PARM0) = CSIE_MOUSEABS;
G_FLOAT(OFS_PARM1) = xabs;
G_FLOAT(OFS_PARM2) = yabs;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram (csqcprogs, csqcg.input_event);
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_MouseMove(float xdelta, float ydelta)
qboolean CSQC_MouseMove(float xdelta, float ydelta, int devid)
{
void *pr_globals;
@ -5299,15 +5324,31 @@ qboolean CSQC_MouseMove(float xdelta, float ydelta)
return false;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = 2;
G_FLOAT(OFS_PARM0) = CSIE_MOUSEDELTA;
G_FLOAT(OFS_PARM1) = xdelta;
G_FLOAT(OFS_PARM2) = ydelta;
G_FLOAT(OFS_PARM3) = devid;
PR_ExecuteProgram (csqcprogs, csqcg.input_event);
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_Accelerometer(float x, float y, float z)
{
void *pr_globals;
if (!csqcprogs || !csqcg.input_event)
return false;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = CSIE_ACCELEROMETER;
G_FLOAT(OFS_PARM1) = x;
G_FLOAT(OFS_PARM2) = y;
G_FLOAT(OFS_PARM3) = z;
PR_ExecuteProgram (csqcprogs, csqcg.input_event);
return G_FLOAT(OFS_RETURN);
}
qboolean CSQC_ConsoleCommand(char *cmd)
{
void *pr_globals;

View File

@ -105,13 +105,13 @@ int MP_TranslateFTEtoDPCodes(int code)
case K_MOUSE1: return 512;
case K_MOUSE2: return 513;
case K_MOUSE3: return 514;
case K_MOUSE4: return 515;
case K_MOUSE5: return 516;
// case K_MOUSE6: return 517;
// case K_MOUSE7: return 518;
// case K_MOUSE8: return 519;
// case K_MOUSE9: return 520;
// case K_MOUSE10: return 521;
case K_MOUSE4: return 517;
case K_MOUSE5: return 518;
case K_MOUSE6: return 519;
case K_MOUSE7: return 520;
case K_MOUSE8: return 521;
case K_MOUSE9: return 522;
case K_MOUSE10: return 523;
case K_MWHEELDOWN: return 515;//K_MOUSE4;
case K_MWHEELUP: return 516;//K_MOUSE5;
default: return code;
@ -208,13 +208,13 @@ int MP_TranslateDPtoFTECodes(int code)
case 512: return K_MOUSE1;
case 513: return K_MOUSE2;
case 514: return K_MOUSE3;
// case 515: return K_MOUSE4;
// case 516: return K_MOUSE5;
case 517: return K_MOUSE6;
case 518: return K_MOUSE7;
case 519: return K_MOUSE8;
// case 520: return K_MOUSE9;
// case 521: return K_MOUSE10;
case 517: return K_MOUSE4;
case 518: return K_MOUSE5;
case 519: return K_MOUSE6;
case 520: return K_MOUSE7;
case 521: return K_MOUSE8;
case 522: return K_MOUSE9;
case 523: return K_MOUSE10;
case 515: return K_MWHEELDOWN;//K_MOUSE4;
case 516: return K_MWHEELUP;//K_MOUSE5;
default: return code;

View File

@ -1734,6 +1734,7 @@ void Surf_SetupFrame(void)
R_AnimateLight();
r_framecount++;
r_viewcontents = 0;
if (r_refdef.flags & Q2RDF_NOWORLDMODEL)
{
}
@ -1778,6 +1779,8 @@ void Surf_SetupFrame(void)
(leaf->cluster != r_viewcluster2) )
r_viewcluster2 = leaf->cluster;
}
r_viewcontents = leaf->contents;
}
#endif
else if (cl.worldmodel && cl.worldmodel->fromgame == fg_doom3)
@ -1822,8 +1825,38 @@ void Surf_SetupFrame(void)
r_viewleaf2 = NULL;
if (r_viewleaf)
V_SetContentsColor (r_viewleaf->contents);
{
switch(r_viewleaf->contents)
{
case Q1CONTENTS_WATER:
r_viewcontents |= FTECONTENTS_WATER;
break;
case Q1CONTENTS_LAVA:
r_viewcontents |= FTECONTENTS_LAVA;
break;
case Q1CONTENTS_SLIME:
r_viewcontents |= FTECONTENTS_SLIME;
break;
case Q1CONTENTS_SKY:
r_viewcontents |= FTECONTENTS_SKY;
break;
}
}
}
/*pick up any extra water entities*/
{
extern vec3_t player_maxs, player_mins;
vec3_t t1,t2;
VectorCopy(player_mins, t1);
VectorCopy(player_maxs, t2);
VectorClear(player_maxs);
VectorClear(player_mins);
r_viewcontents |= PM_ExtraBoxContents(r_origin);
VectorCopy(t1, player_mins);
VectorCopy(t2, player_maxs);
}
V_SetContentsColor (r_viewcontents);
}
@ -2019,11 +2052,6 @@ void Surf_DrawWorld (void)
currentmodel = cl.worldmodel;
currententity = &r_worldentity;
#ifdef MAP_DOOM
if (currentmodel->fromgame == fg_doom)
GLR_DoomWorld();
else
#endif
{
RSpeedRemark();
@ -2067,6 +2095,12 @@ void Surf_DrawWorld (void)
}
else
#endif
if (currentmodel->fromgame == fg_doom)
{
vis = NULL;
GLR_DoomWorld();
}
else
#ifdef TERRAIN
if (currentmodel->type == mod_heightmap)
{

View File

@ -384,7 +384,7 @@ void CLQ2_BlasterTrail2(vec3_t oldorg, vec3_t neworg);
void WritePCXfile (const char *filename, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.
qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height);
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey);
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean *hasalpha, int asgrey);
qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height);
qbyte *ReadPNGFile(qbyte *buf, int length, int *width, int *height, const char *name);
qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out);

View File

@ -305,6 +305,7 @@ cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0",
CVAR_ARCHIVE);
cvar_t r_shadows = SCVARF ("r_shadows", "0",
CVAR_ARCHIVE);
cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground.");
cvar_t r_lightprepass = CVARFD("r_lightprepass", "0", CVAR_SHADERSYSTEM, "Experimental. Attempt to use a different lighting mechanism.");
cvar_t r_shadow_bumpscale_basetexture = SCVAR ("r_shadow_bumpscale_basetexture", "4");
@ -624,6 +625,7 @@ void Renderer_Init(void)
Cvar_Register (&r_replacemodels, GRAPHICALNICETIES);
Cvar_Register (&r_showbboxes, GLRENDEREROPTIONS);
Cvar_Register (&r_polygonoffset_submodel_factor, GLRENDEREROPTIONS);
Cvar_Register (&r_polygonoffset_submodel_offset, GLRENDEREROPTIONS);

View File

@ -2459,8 +2459,8 @@ void Sbar_Draw (void)
{
if (sb_showscores || sb_showteamscores || cl.stats[pnum][STAT_HEALTH] <= 0)
Sbar_SoloScoreboard ();
else if (cls.gamemode != GAME_DEATHMATCH)
Sbar_CoopScoreboard ();
// else if (cls.gamemode != GAME_DEATHMATCH)
// Sbar_CoopScoreboard ();
else
Sbar_DrawNormal (pnum);

View File

@ -418,6 +418,7 @@ qbyte *Skin_Cache32 (skin_t *skin)
qbyte *raw;
qbyte *out, *pix;
char *path;
qboolean hasalpha;
if (noskins.value==1) // JACK: So NOSKINS > 1 will show skins, but
return NULL; // not download new ones.
@ -441,7 +442,7 @@ qbyte *Skin_Cache32 (skin_t *skin)
raw = COM_LoadTempFile (name);
if (raw)
{
pix = ReadTargaFile(raw, com_filesize, &skin->width, &skin->height, false);
pix = ReadTargaFile(raw, com_filesize, &skin->width, &skin->height, &hasalpha, false);
if (pix)
{
out = Cache_Alloc(&skin->cache, skin->width*skin->height*4, name);

View File

@ -26,13 +26,22 @@ static qboolean sys_running = false;
static void *sys_memheap;
static unsigned int sys_lastframe;
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject obj)
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_frame(JNIEnv *env, jobject obj,
jfloat ax, jfloat ay, jfloat az)
{
static vec3_t oac;
#ifdef SERVERONLY
SV_Frame();
#else
unsigned int now = Sys_Milliseconds();
double tdelta = (now - sys_lastframe) * 0.001;
if (oac[0] != ax || oac[1] != ay || oac[2] != az)
{
CSQC_Accelerometer(ax, ay, az);
oac[0] = ax;
oac[1] = ay;
oac[2] = az;
}
Host_Frame(tdelta);
sys_lastframe = now;
#endif
@ -47,11 +56,11 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o
Cmd_ExecuteString("vid_restart\n", RESTRICT_LOCAL);
else
{
char *args [] =
const char *args [] =
{
"ftedroid",
"-basepack",
(*env)->GetStringUTFChars(env, path, 0),
(*env)->GetStringUTFChars(env, path, NULL),
"",
""
//we should do this somewhere... (*env)->ReleaseStringUTFChars(env, path, parms.basedir);
@ -60,8 +69,8 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o
parms.basedir = "/sdcard/fte";
parms.argc = 3;
parms.argv = args;
parms.memsize = sys_memheap = 8*1024*1024;
parms.membase = malloc(parms.memsize);
parms.memsize = 8*1024*1024;
parms.membase = sys_memheap = malloc(parms.memsize);
if (!parms.membase)
{
Sys_Printf("Unable to alloc heap\n");
@ -89,26 +98,36 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_keypress(JNIEnv *env, jobje
int mousecursor_x, mousecursor_y;
float mouse_x, mouse_y;
static float omouse_x, omouse_y;
static vec2_t omouse[8];
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject obj,
jint act, jfloat x, jfloat y)
jint act, jint ptrid, jfloat x, jfloat y)
{
static float totalmoved;
static qboolean down;
float dx, dy;
static float totalmoved[8];
static qboolean down[8];
float d[2];
dx = x - omouse_x;
dy = y - omouse_y;
omouse_x = x;
omouse_y = y;
if (!act && CSQC_MousePosition(x, y, ptrid))
return;
/*note that these events are not directly useful, so trigger mouse2 leaving mouse1 clean for tap events (and bypass any binds for it)*/
if (act == 1 && CSQC_KeyPress(K_MOUSE2, 0, true, ptrid))
return;
if (act == 2 && CSQC_KeyPress(K_MOUSE2, 0, false, ptrid))
return;
ptrid &= 7;
d[0] = x - omouse[ptrid][0];
d[1] = y - omouse[ptrid][1];
omouse[ptrid][0] = x;
omouse[ptrid][1] = y;
mousecursor_x = x;
mousecursor_y = y;
if (down)
if (down[ptrid])
{
mouse_x += dx;
mouse_y += dy;
totalmoved += fabs(dx) + fabs(dy);
mouse_x += d[0];
mouse_y += d[1];
totalmoved[ptrid] += fabs(d[0]) + fabs(d[1]);
}
switch(act)
@ -116,13 +135,13 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject
case 0: /*move*/
break;
case 1: /*down*/
totalmoved = 0;
down = true;
totalmoved[ptrid] = 0;
down[ptrid] = true;
break;
case 2: /*up*/
down = false;
down[ptrid] = false;
/*if it didn't move far, treat it as a regular click, if it did move a little then sorry if you just wanted a small turn!*/
if (totalmoved < 3)
if (totalmoved[ptrid] < 3)
{
Key_Event(0, K_MOUSE1, 0, 1);
Key_Event(0, K_MOUSE1, 0, 0);
@ -130,11 +149,6 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject
break;
}
}
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_accelerometer(JNIEnv *env, jobject obj,
jfloat x, jfloat y, jfloat z)
{
// Con_Printf("Accelerometer: %f %f %f\n", x, y, z);
}
static int secbase;
double Sys_DoubleTime(void)

View File

@ -1376,19 +1376,142 @@ typedef struct IPropertyStore
IPropertyStore * This);
} *lpVtbl;
} IPropertyStore;
#endif
#endif
static const IID IID_IPropertyStore = {0x886d8eeb, 0x8cf2, 0x4446, {0x8d, 0x02, 0xcd, 0xba, 0x1d, 0xbd, 0xcf, 0x99}};
#ifndef MINGW
#if !defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 7600
#define IObjectArray IUnknown
#endif
#endif
static const IID IID_IObjectArray = {0x92ca9dcd, 0x5622, 0x4bba, {0xa8,0x05,0x5e,0x9f,0x54,0x1b,0xd8,0xc9}};
#ifndef MINGW
#if !defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 7600
typedef struct IObjectCollection
{
struct IObjectCollectionVtbl
{
HRESULT ( __stdcall *QueryInterface )(
/* [in] IShellLink*/ void *This,
/* [in] */ const GUID * const riid,
/* [out] */ void **ppvObject);
ULONG ( __stdcall *AddRef )(
/* [in] IShellLink*/ void *This);
ULONG ( __stdcall *Release )(
/* [in] IShellLink*/ void *This);
HRESULT ( __stdcall *GetCount )(
/* [in] IShellLink*/ void *This,
/* [out] */ UINT *pcObjects);
HRESULT ( __stdcall *GetAt )(
/* [in] IShellLink*/ void *This,
/* [in] */ UINT uiIndex,
/* [in] */ const GUID * const riid,
/* [iid_is][out] */ void **ppv);
HRESULT ( __stdcall *AddObject )(
/* [in] IShellLink*/ void *This,
/* [in] */ void *punk);
HRESULT ( __stdcall *AddFromArray )(
/* [in] IShellLink*/ void *This,
/* [in] */ IObjectArray *poaSource);
HRESULT ( __stdcall *RemoveObjectAt )(
/* [in] IShellLink*/ void *This,
/* [in] */ UINT uiIndex);
HRESULT ( __stdcall *Clear )(
/* [in] IShellLink*/ void *This);
} *lpVtbl;
} IObjectCollection;
#endif
#endif
static const IID IID_IObjectCollection = {0x5632b1a4, 0xe38a, 0x400a, {0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}};
static const CLSID CLSID_EnumerableObjectCollection = {0x2d3468c1, 0x36a7, 0x43b6, {0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}};
#ifndef MINGW
#if !defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 7600
typedef struct ICustomDestinationList
{
struct ICustomDestinationListVtbl
{
HRESULT ( __stdcall *QueryInterface ) (
/* [in] ICustomDestinationList*/ void *This,
/* [in] */ const GUID * const riid,
/* [out] */ void **ppvObject);
ULONG ( __stdcall *AddRef )(
/* [in] ICustomDestinationList*/ void *This);
ULONG ( __stdcall *Release )(
/* [in] ICustomDestinationList*/ void *This);
HRESULT ( __stdcall *SetAppID )(
/* [in] ICustomDestinationList*/ void *This,
/* [string][in] */ LPCWSTR pszAppID);
HRESULT ( __stdcall *BeginList )(
/* [in] ICustomDestinationList*/ void *This,
/* [out] */ UINT *pcMinSlots,
/* [in] */ const GUID * const riid,
/* [out] */ void **ppv);
HRESULT ( __stdcall *AppendCategory )(
/* [in] ICustomDestinationList*/ void *This,
/* [string][in] */ LPCWSTR pszCategory,
/* [in] IObjectArray*/ void *poa);
HRESULT ( __stdcall *AppendKnownCategory )(
/* [in] ICustomDestinationList*/ void *This,
/* [in] KNOWNDESTCATEGORY*/ int category);
HRESULT ( __stdcall *AddUserTasks )(
/* [in] ICustomDestinationList*/ void *This,
/* [in] IObjectArray*/ void *poa);
HRESULT ( __stdcall *CommitList )(
/* [in] ICustomDestinationList*/ void *This);
HRESULT ( __stdcall *GetRemovedDestinations )(
/* [in] ICustomDestinationList*/ void *This,
/* [in] */ const IID * const riid,
/* [out] */ void **ppv);
HRESULT ( __stdcall *DeleteList )(
/* [in] ICustomDestinationList*/ void *This,
/* [string][unique][in] */ LPCWSTR pszAppID);
HRESULT ( __stdcall *AbortList )(
/* [in] ICustomDestinationList*/ void *This);
} *lpVtbl;
} ICustomDestinationList;
#endif
#endif
static const IID IID_ICustomDestinationList = {0x6332debf, 0x87b5, 0x4670, {0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}};
static const CLSID CLSID_DestinationList = {0x77f10cf0, 0x3db5, 0x4966, {0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}};
#endif
#if _MSC_VER > 1200
#define WIN7_APPNAME L"FTEQuake"
void Sys_RecentServer(char *command, char *target, char *title, char *desc)
static IShellLinkW *CreateShellLink(char *command, char *target, char *title, char *desc)
{
HRESULT hr;
IShellLinkW *link;
IPropertyStore *prop_store;
SHARDAPPIDINFOLINK appinfo;
WCHAR buf[1024];
char tmp[1024], *s;
@ -1396,9 +1519,12 @@ void Sys_RecentServer(char *command, char *target, char *title, char *desc)
// Get a pointer to the IShellLink interface.
hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, &link);
if (FAILED(hr))
return;
swprintf(buf, sizeof(buf), L"%S", exename);
return NULL;
GetModuleFileNameW(NULL, buf, sizeof(buf)/sizeof(wchar_t)-1);
IShellLinkW_SetIconLocation(link, buf, 0); /*grab the first icon from our exe*/
IShellLinkW_SetPath(link, buf); /*program to run*/
Q_strncpyz(tmp, com_quakedir, sizeof(tmp));
/*normalize the gamedir, so we don't end up with the same thing multiple times*/
for(s = tmp; *s; s++)
@ -1413,6 +1539,7 @@ void Sys_RecentServer(char *command, char *target, char *title, char *desc)
swprintf(buf, sizeof(buf), L"%S", desc);
IShellLinkW_SetDescription(link, buf); /*tooltip*/
hr = IShellLinkW_QueryInterface(link, &IID_IPropertyStore, &prop_store);
#ifndef MINGW
@ -1430,6 +1557,18 @@ void Sys_RecentServer(char *command, char *target, char *title, char *desc)
}
#endif
return link;
}
void Sys_RecentServer(char *command, char *target, char *title, char *desc)
{
SHARDAPPIDINFOLINK appinfo;
IShellLinkW *link;
link = CreateShellLink(command, target, title, desc);
if (!link)
return;
appinfo.pszAppID=WIN7_APPNAME;
appinfo.psl=link;
SHAddToRecentDocs(SHARD_APPIDINFOLINK, &appinfo);
@ -1449,6 +1588,81 @@ void Win7_Init(void)
pSetCurrentProcessExplicitAppUserModelID(WIN7_APPNAME);
}
}
void Win7_TaskListInit(void)
{
ICustomDestinationList *cdl;
IObjectCollection *col;
IObjectArray *arr;
IShellLinkW *link;
CoInitialize(NULL);
if (SUCCEEDED(CoCreateInstance(&CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, &IID_ICustomDestinationList, &cdl)))
{
UINT minslots;
IUnknown *removed;
cdl->lpVtbl->BeginList(cdl, &minslots, &IID_IObjectArray, &removed);
if (SUCCEEDED(CoCreateInstance(&CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, &IID_IObjectCollection, &col)))
{
switch(M_GameType())
{
case MGT_QUAKE1:
link = CreateShellLink("+menu_servers", "", "Server List", "Pick a multiplayer server to join");
if (link)
{
col->lpVtbl->AddObject(col, link);
link->lpVtbl->Release(link);
}
link = CreateShellLink("+map start", "", "Start New Game (Quake)", "Begin a new single-player game");
if (link)
{
col->lpVtbl->AddObject(col, link);
link->lpVtbl->Release(link);
}
break;
case MGT_QUAKE2:
link = CreateShellLink("+menu_servers", "", "Quake2 Server List", "Pick a multiplayer server to join");
if (link)
{
col->lpVtbl->AddObject(col, link);
link->lpVtbl->Release(link);
}
link = CreateShellLink("+map unit1", "", "Start New Game (Quake2)", "Begin a new game");
if (link)
{
col->lpVtbl->AddObject(col, link);
link->lpVtbl->Release(link);
}
break;
case MGT_HEXEN2:
link = CreateShellLink("+menu_servers", "", "Hexen2 Server List", "Pick a multiplayer server to join");
if (link)
{
col->lpVtbl->AddObject(col, link);
link->lpVtbl->Release(link);
}
link = CreateShellLink("+map demo1", "", "Start New Game (Hexen2)", "Begin a new game");
if (link)
{
col->lpVtbl->AddObject(col, link);
link->lpVtbl->Release(link);
}
break;
}
if (SUCCEEDED(col->lpVtbl->QueryInterface(col, &IID_IObjectArray, &arr)))
{
cdl->lpVtbl->AddUserTasks(cdl, arr);
arr->lpVtbl->Release(arr);
}
col->lpVtbl->Release(col);
}
cdl->lpVtbl->AppendKnownCategory(cdl, 1);
cdl->lpVtbl->CommitList(cdl);
cdl->lpVtbl->Release(cdl);
}
}
#endif
@ -1678,21 +1892,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
#ifndef MINGW
#if _MSC_VER > 1200
switch(M_GameType())
{
case MGT_QUAKE1:
Sys_RecentServer("+menu_servers", "", "Server List", "Pick a server to play on");
Sys_RecentServer("+map start", "", "Start New Game (Quake)", "Begin a new game");
break;
case MGT_QUAKE2:
Sys_RecentServer("+menu_servers", "", "Server List", "Pick a server to play on");
Sys_RecentServer("+map unit1", "", "Start New Game (Quake2)", "Begin a new game");
break;
case MGT_HEXEN2:
Sys_RecentServer("+menu_servers", "", "Server List", "Pick a server to play on");
Sys_RecentServer("+map demo1", "", "Start New Game (Hexen2)", "Begin a new game");
break;
}
Win7_TaskListInit();
#endif
#endif

View File

@ -554,21 +554,14 @@ FIXME: Uses Q1 contents
void V_SetContentsColor (int contents)
{
int i;
switch (contents)
{
case Q1CONTENTS_EMPTY:
cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
break;
case Q1CONTENTS_LAVA:
if (contents & FTECONTENTS_LAVA)
cl.cshifts[CSHIFT_CONTENTS] = cshift_lava;
break;
case Q1CONTENTS_SOLID:
case Q1CONTENTS_SLIME:
else if (contents & (FTECONTENTS_SLIME | FTECONTENTS_SOLID))
cl.cshifts[CSHIFT_CONTENTS] = cshift_slime;
break;
default:
else if (contents & FTECONTENTS_WATER)
cl.cshifts[CSHIFT_CONTENTS] = cshift_water;
}
else
cl.cshifts[CSHIFT_CONTENTS] = cshift_empty;
cl.cshifts[CSHIFT_CONTENTS].percent *= v_contentblend.value;

View File

@ -169,8 +169,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define INTERQUAKEMODELS
#define HUFFNETWORK //huffman network compression
//#define DOOMWADS //doom wad/sprite support
//#define MAP_DOOM //doom map support
#define DOOMWADS //doom wad/sprite support
#define MAP_DOOM //doom map support
#define MAP_PROC //doom3/quake4 map support
//#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet)
#define Q2BSPS //quake 2 bsp support
@ -494,8 +494,7 @@ STAT_VIEW2 = 20,
#endif
STAT_VIEWZOOM = 21, // DP
//note that hexen2 stats are only used in hexen2 gamemodes, and can be read by csqc without further server changes.
//when running hexen2 mods, the server specifically sets up these stats for the csqc.
//these stats are used only when running a hexen2 mod/hud, and will never be used for a quake mod/hud/generic code.
STAT_H2_LEVEL = 32, // changes stat bar
STAT_H2_INTELLIGENCE, // changes stat bar
STAT_H2_WISDOM, // changes stat bar
@ -553,25 +552,41 @@ STAT_H2_OBJECTIVE1,
STAT_H2_OBJECTIVE2,
STAT_MOVEVARS_WALLFRICTION = 237, // DP
STAT_MOVEVARS_FRICTION = 238, // DP
STAT_MOVEVARS_WATERFRICTION = 239, // DP
STAT_MOVEVARS_TICRATE = 240, // DP
STAT_MOVEVARS_TIMESCALE = 241, // DP
STAT_MOVEVARS_GRAVITY = 242, // DP
STAT_MOVEVARS_STOPSPEED = 243, // DP
STAT_MOVEVARS_MAXSPEED = 244, // DP
STAT_MOVEVARS_SPECTATORMAXSPEED = 245, // DP
STAT_MOVEVARS_ACCELERATE = 246, // DP
STAT_MOVEVARS_AIRACCELERATE = 247, // DP
STAT_MOVEVARS_WATERACCELERATE = 248, // DP
STAT_MOVEVARS_ENTGRAVITY = 249, // DP
STAT_MOVEVARS_JUMPVELOCITY = 250, // DP
STAT_MOVEVARS_EDGEFRICTION = 251, // DP
STAT_MOVEVARS_MAXAIRSPEED = 252, // DP
STAT_MOVEVARS_STEPHEIGHT = 253, // DP
STAT_MOVEVARS_AIRACCEL_QW = 254, // DP
STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR = 220, // DP
STAT_MOVEVARS_AIRCONTROL_PENALTY = 221, // DP
STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222, // DP
STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223, // DP
STAT_MOVEVARS_AIRCONTROL_POWER = 224, // DP
STAT_MOVEFLAGS = 225, // DP
STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL = 226, // DP
STAT_MOVEVARS_WARSOWBUNNY_ACCEL = 227, // DP
STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED = 228, // DP
STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL = 229, // DP
STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO = 230, // DP
STAT_MOVEVARS_AIRSTOPACCELERATE = 231, // DP
STAT_MOVEVARS_AIRSTRAFEACCELERATE = 232, // DP
STAT_MOVEVARS_MAXAIRSTRAFESPEED = 233, // DP
STAT_MOVEVARS_AIRCONTROL = 234, // DP
STAT_FRAGLIMIT = 235, // DP
STAT_TIMELIMIT = 236, // DP
STAT_MOVEVARS_WALLFRICTION = 237, // DP
STAT_MOVEVARS_FRICTION = 238, // DP
STAT_MOVEVARS_WATERFRICTION = 239, // DP
STAT_MOVEVARS_TICRATE = 240, // DP
STAT_MOVEVARS_TIMESCALE = 241, // DP
STAT_MOVEVARS_GRAVITY = 242, // DP
STAT_MOVEVARS_STOPSPEED = 243, // DP
STAT_MOVEVARS_MAXSPEED = 244, // DP
STAT_MOVEVARS_SPECTATORMAXSPEED = 245, // DP
STAT_MOVEVARS_ACCELERATE = 246, // DP
STAT_MOVEVARS_AIRACCELERATE = 247, // DP
STAT_MOVEVARS_WATERACCELERATE = 248, // DP
STAT_MOVEVARS_ENTGRAVITY = 249, // DP
STAT_MOVEVARS_JUMPVELOCITY = 250, // DP
STAT_MOVEVARS_EDGEFRICTION = 251, // DP
STAT_MOVEVARS_MAXAIRSPEED = 252, // DP
STAT_MOVEVARS_STEPHEIGHT = 253, // DP
STAT_MOVEVARS_AIRACCEL_QW = 254, // DP
STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255, // DP
MAX_CL_STATS = 256

View File

@ -504,7 +504,7 @@ typedef struct
#define FTECONTENTS_LAVA 8
#define FTECONTENTS_SLIME 16
#define FTECONTENTS_WATER 32
//#define FTECONTENTS_LADDER 32
#define FTECONTENTS_LADDER 0x00004000
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
#define FTECONTENTS_PLAYERCLIP 0x00010000
#define FTECONTENTS_BODY 0x02000000

View File

@ -2161,18 +2161,21 @@ void Mod_ParseQ3SkinFile(char *out, char *surfname, char *modelname, int skinnum
}
#if defined(D3DQUAKE) || defined(GLQUAKE)
void Mod_LoadSkinFile(texnums_t *texnum, char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette)
shader_t *Mod_LoadSkinFile(shader_t **shaders, char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette)
{
shader_t *shader;
char shadername[MAX_QPATH];
Q_strncpyz(shadername, surfacename, sizeof(shadername));
Mod_ParseQ3SkinFile(shadername, surfacename, loadmodel->name, skinnumber, NULL);
texnum->shader = R_RegisterSkin(shadername, loadmodel->name);
shader = R_RegisterSkin(shadername, loadmodel->name);
R_BuildDefaultTexnums(texnum, texnum->shader);
if (texnum->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name);
R_BuildDefaultTexnums(&shader->defaulttextures, shader);
if (shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", shader->name, loadmodel->name);
return shader;
}
#endif
@ -2424,7 +2427,7 @@ static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha)
#if defined(GLQUAKE) || defined(D3DQUAKE)
static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintranstype)
{
texnums_t *texnums;
shader_t **shaders;
char skinname[MAX_QPATH];
int i;
int s, t;
@ -2485,8 +2488,8 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
if (!TEXVALID(texture) || (loadmodel->engineflags & MDLF_NOTREPLACEMENTS))
{
//we're not using 24bits
texnums = Hunk_Alloc(sizeof(*texnums)+s);
saved = (qbyte*)(texnums+1);
shaders = Hunk_Alloc(sizeof(*shaders)+s);
saved = (qbyte*)(shaders+1);
outskin->ofstexels = (qbyte *)(saved) - (qbyte *)outskin;
memcpy(saved, pskintype+1, s);
Mod_FloodFillSkin(saved, outskin->skinwidth, outskin->skinheight);
@ -2523,16 +2526,16 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
}
}
else
texnums = Hunk_Alloc(sizeof(*texnums));
outskin->texnums=1;
shaders = Hunk_Alloc(sizeof(*shaders));
outskin->numshaders=1;
outskin->ofstexnums = (char *)texnums - (char *)outskin;
outskin->ofsshaders = (char *)shaders - (char *)outskin;
Q_snprintfz(skinname, sizeof(skinname), "%s_%i", loadname, i);
if (skintranstype == 4)
texnums->shader = R_RegisterShader(skinname,
shaders[0] = R_RegisterShader(skinname,
"{\n"
"{\n"
"map $diffuse\n"
@ -2543,7 +2546,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
"}\n"
"}\n");
else if (skintranstype == 3)
texnums->shader = R_RegisterShader(skinname,
shaders[0] = R_RegisterShader(skinname,
"{\n"
"{\n"
"map $diffuse\n"
@ -2553,7 +2556,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
"}\n"
"}\n");
else if (skintranstype)
texnums->shader = R_RegisterShader(skinname,
shaders[0] = R_RegisterShader(skinname,
"{\n"
"{\n"
"map $diffuse\n"
@ -2563,26 +2566,24 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
"}\n"
"}\n");
else
texnums->shader = R_RegisterSkin(skinname, loadmodel->name);
R_BuildDefaultTexnums(texnums, texnums->shader);
shaders[0] = R_RegisterSkin(skinname, loadmodel->name);
texnums->loweroverlay = r_nulltex;
texnums->upperoverlay = r_nulltex;
texnums->base = texture;
texnums->fullbright = fbtexture;
texnums->bump = bumptexture;
shaders[0]->defaulttextures.base = texture;
shaders[0]->defaulttextures.fullbright = fbtexture;
shaders[0]->defaulttextures.bump = bumptexture;
//13/4/08 IMPLEMENTME
if (r_skin_overlays.ival)
{
snprintf(skinname, sizeof(skinname), "%s_%i_pants", loadname, i);
texnums->loweroverlay = R_LoadReplacementTexture(skinname, "models", 0);
shaders[0]->defaulttextures.loweroverlay = R_LoadReplacementTexture(skinname, "models", 0);
snprintf(skinname, sizeof(skinname), "%s_%i_shirt", loadname, i);
texnums->upperoverlay = R_LoadReplacementTexture(skinname, "models", 0);
shaders[0]->defaulttextures.upperoverlay = R_LoadReplacementTexture(skinname, "models", 0);
}
R_BuildDefaultTexnums(&shaders[0]->defaulttextures, shaders[0]);
pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s);
break;
@ -2591,17 +2592,17 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
outskin->skinheight = pq1inmodel->skinheight;
count = (daliasskingroup_t*)(pskintype+1);
intervals = (daliasskininterval_t *)(count+1);
outskin->texnums = LittleLong(count->numskins);
data = (qbyte *)(intervals + outskin->texnums);
texnums = Hunk_Alloc(sizeof(*texnums)*outskin->texnums);
outskin->ofstexnums = (char *)texnums - (char *)outskin;
outskin->numshaders = LittleLong(count->numskins);
data = (qbyte *)(intervals + outskin->numshaders);
shaders = Hunk_Alloc(sizeof(*shaders)*outskin->numshaders);
outskin->ofsshaders = (char *)shaders - (char *)outskin;
outskin->ofstexels = 0;
sinter = LittleFloat(intervals[0].interval);
if (sinter <= 0)
sinter = 0.1;
outskin->skinspeed = 1/sinter;
for (t = 0; t < outskin->texnums; t++,data+=s, texnums++)
for (t = 0; t < outskin->numshaders; t++,data+=s)
{
texture = r_nulltex;
fbtexture = r_nulltex;
@ -2659,14 +2660,14 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
}
Q_snprintfz(skinname, sizeof(skinname), "%s_%i_%i", loadname, i, t);
texnums->shader = R_RegisterSkin(skinname, loadmodel->name);
shaders[t] = R_RegisterSkin(skinname, loadmodel->name);
TEXASSIGN(texnums->base, texture);
TEXASSIGN(texnums->fullbright, fbtexture);
TEXASSIGN(texnums->loweroverlay, r_nulltex);
TEXASSIGN(texnums->upperoverlay, r_nulltex);
TEXASSIGN(shaders[t]->defaulttextures.base, texture);
TEXASSIGN(shaders[t]->defaulttextures.fullbright, fbtexture);
TEXASSIGN(shaders[t]->defaulttextures.loweroverlay, r_nulltex);
TEXASSIGN(shaders[t]->defaulttextures.upperoverlay, r_nulltex);
R_BuildDefaultTexnums(texnums, texnums->shader);
R_BuildDefaultTexnums(&shaders[t]->defaulttextures, shaders[t]);
}
pskintype = (daliasskintype_t *)data;
break;
@ -3034,19 +3035,19 @@ static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins)
{
#ifndef SERVERONLY
int i;
texnums_t *texnums;
shader_t **shaders;
galiasskin_t *outskin = (galiasskin_t *)((char *)galias + galias->ofsskins);
for (i = 0; i < LittleLong(pq2inmodel->num_skins); i++, outskin++)
{
texnums = Hunk_Alloc(sizeof(*texnums));
outskin->ofstexnums = (char *)texnums - (char *)outskin;
outskin->texnums=1;
shaders = Hunk_Alloc(sizeof(*shaders));
outskin->ofsshaders = (char *)shaders - (char *)outskin;
outskin->numshaders=1;
COM_CleanUpPath(skins); //blooming tanks.
TEXASSIGN(texnums->base, R_LoadReplacementTexture(skins, "models", IF_NOALPHA));
texnums->shader = R_RegisterSkin(skins, loadmodel->name);
R_BuildDefaultTexnums(texnums, texnums->shader);
shaders[0] = R_RegisterSkin(skins, loadmodel->name);
TEXASSIGN(shaders[0]->defaulttextures.base, R_LoadReplacementTexture(skins, "models", IF_NOALPHA));
R_BuildDefaultTexnums(NULL, shaders[0]);
outskin->skinwidth = 0;
outskin->skinheight = 0;
@ -3057,20 +3058,19 @@ static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins)
#endif
galias->numskins = LittleLong(pq2inmodel->num_skins);
/*
#ifndef SERVERONLY
outskin = (galiasskin_t *)((char *)galias + galias->ofsskins);
outskin += galias->numskins - 1;
if (galias->numskins)
{
texnums = (texnums_t*)((char *)outskin +outskin->ofstexnums);
if (TEXVALID(texnums->base))
return;
if (texnums->shader)
if (*(shader_t**)((char *)outskin + outskin->ofstexnums))
return;
galias->numskins--;
}
#endif
*/
}
#define MD2_MAX_TRIANGLES 4096
@ -3831,7 +3831,7 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
{
#ifndef SERVERONLY
galiasskin_t *skin;
texnums_t *texnum;
shader_t **shaders;
float lat, lng;
md3St_t *inst;
vec3_t *normals;
@ -3992,14 +3992,14 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
//extern int gl_bumpmappingpossible; // unused variable
char shadname[1024];
skin = Hunk_Alloc((LittleLong(surf->numShaders)+externalskins)*((sizeof(galiasskin_t)+sizeof(texnums_t))));
skin = Hunk_Alloc((LittleLong(surf->numShaders)+externalskins)*((sizeof(galiasskin_t)+sizeof(shader_t*))));
galias->ofsskins = (qbyte *)skin - (qbyte *)galias;
texnum = (texnums_t *)(skin + LittleLong(surf->numShaders)+externalskins);
shaders = (shader_t **)(skin + LittleLong(surf->numShaders)+externalskins);
inshader = (md3Shader_t *)((qbyte *)surf + LittleLong(surf->ofsShaders));
for (i = 0; i < externalskins; i++)
{
skin->texnums = 1;
skin->ofstexnums = (qbyte *)texnum - (qbyte *)skin;
skin->numshaders = 1;
skin->ofsshaders = (qbyte *)&shaders[i] - (qbyte *)skin;
skin->ofstexels = 0;
skin->skinwidth = 0;
skin->skinheight = 0;
@ -4021,16 +4021,15 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
if (qrenderer != QR_NONE)
{
texnum->shader = R_RegisterSkin(shadname, mod->name);
R_BuildDefaultTexnums(texnum, texnum->shader);
shaders[i] = R_RegisterSkin(shadname, mod->name);
R_BuildDefaultTexnums(NULL, shaders[i]);
if (texnum->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name);
if (shaders[i]->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", shaders[i]->name, loadmodel->name);
}
inshader++;
skin++;
texnum++;
}
galias->numskins = i;
}
@ -4181,7 +4180,7 @@ qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer)
{
#ifndef SERVERONLY
galiasskin_t *skin;
texnums_t *texnum;
shader_t **shaders;
int skinfiles;
int j;
#endif
@ -4366,14 +4365,14 @@ qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer)
root[i].ofs_st_array = (char*)stcoords - (char*)&root[i];
root[i].numskins = skinfiles;
skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(texnums_t))*skinfiles);
texnum = (texnums_t*)(skin+skinfiles);
for (j = 0; j < skinfiles; j++, texnum++)
skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(shader_t*))*skinfiles);
shaders = (shader_t**)(skin+skinfiles);
for (j = 0; j < skinfiles; j++, shaders++)
{
skin[j].texnums = 1; //non-sequenced skins.
skin[j].ofstexnums = (char *)texnum - (char *)&skin[j];
skin[j].numshaders = 1; //non-sequenced skins.
skin[j].ofsshaders = (char *)shaders - (char *)&skin[j];
Mod_LoadSkinFile(texnum, surfname, j, NULL, 0, 0, NULL);
Mod_LoadSkinFile(shaders, surfname, j, NULL, 0, 0, NULL);
}
root[i].ofsskins = (char *)skin - (char *)&root[i];
@ -4566,7 +4565,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
#ifndef SERVERONLY
float *stcoord;
galiasskin_t *skin;
texnums_t *gtexnums;
shader_t **gshaders;
#endif
galiasbone_t *bones;
galiasgroup_t *group;
@ -5034,25 +5033,28 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
group->isheirachical = false;
}
for (i = 0; i < num_matt; i++)
{
#ifndef SERVERONLY
skin = Hunk_Alloc(sizeof(galiasskin_t) + sizeof(texnums_t));
gtexnums = (texnums_t*)(skin+1);
skin->ofstexnums = sizeof(*skin);
skin->texnums = 1;
skin = Hunk_Alloc(num_matt * (sizeof(galiasskin_t) + sizeof(shader_t*)));
gshaders = (shader_t**)(skin + num_matt);
for (i = 0; i < num_matt; i++, skin++)
{
skin->ofsshaders = (char*)&gshaders[i] - (char*)skin;
skin->numshaders = 1;
skin->skinspeed = 10;
Q_strncpyz(skin->name, matt[i].name, sizeof(skin->name));
gtexnums->shader = R_RegisterSkin(matt[i].name, mod->name);
R_BuildDefaultTexnums(gtexnums, gtexnums->shader);
if (gtexnums->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", gtexnums->shader->name, loadmodel->name);
gshaders[i] = R_RegisterSkin(matt[i].name, mod->name);
R_BuildDefaultTexnums(NULL, gshaders[i]);
if (gshaders[i]->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", gshaders[i]->name, loadmodel->name);
gmdl[i].ofsskins = (char*)skin - (char*)&gmdl[i];
gmdl[i].numskins = 1;
gmdl[i].ofs_st_array = (char*)stcoord - (char*)&gmdl[i];
gmdl[i].numverts = num_vtxw;
#else
for (i = 0; i < num_matt; i++, skin++, gshaders++)
{
#endif
gmdl[i].groupofs = (char*)group - (char*)&gmdl[i];
@ -5223,7 +5225,7 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer)
{
#ifndef SERVERONLY
galiasskin_t *skin;
texnums_t *texnum;
shader_t **shaders;
int skinfiles;
float *inst;
float *outst;
@ -5440,14 +5442,14 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer)
#else
m->numskins = skinfiles;
skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(texnums_t))*skinfiles);
texnum = (texnums_t*)(skin+skinfiles);
for (j = 0; j < skinfiles; j++, texnum++)
skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(shader_t*))*skinfiles);
shaders = (shader_t**)(skin+skinfiles);
for (j = 0; j < skinfiles; j++, shaders++)
{
skin[j].texnums = 1; //non-sequenced skins.
skin[j].ofstexnums = (char *)texnum - (char *)&skin[j];
skin[j].numshaders = 1; //non-sequenced skins.
skin[j].ofsshaders = (char *)shaders - (char *)&skin[j];
Mod_LoadSkinFile(texnum, mesh->shadername, j, NULL, 0, 0, NULL);
Mod_LoadSkinFile(shaders, mesh->shadername, j, NULL, 0, 0, NULL);
}
m->ofsskins = (char *)skin - (char *)m;
@ -5667,7 +5669,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
#endif
galiasgroup_t *fgroup;
galiasbone_t *bones;
texnums_t *texnum;
shader_t **shaders;
index_t *idx;
float basepose[12 * MAX_BONES];
qboolean baseposeonly;
@ -5736,7 +5738,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
/*allocate a nice big block of memory and figure out where stuff is*/
gai = Hunk_Alloc(sizeof(*gai)*h->num_meshes +
#ifndef SERVERONLY
sizeof(*skin)*h->num_meshes + sizeof(*texnum)*h->num_meshes +
sizeof(*skin)*h->num_meshes + sizeof(*shaders)*h->num_meshes +
#endif
sizeof(*fgroup)*(baseposeonly?1:h->num_anims) + sizeof(float)*12*(baseposeonly?h->num_joints:(h->num_poses*h->num_frames)) + sizeof(*bones)*h->num_joints +
(sizeof(*opos) + sizeof(*onorm) + sizeof(*otcoords) + (noweights?0:(sizeof(*oindex)+sizeof(*oweight)))) * h->num_vertexes);
@ -5759,7 +5761,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
opose = (float*)(fgroup + (baseposeonly?1:h->num_anims));
#ifndef SERVERONLY
skin = (galiasskin_t*)(opose + 12*(baseposeonly?h->num_joints:h->num_poses*h->num_frames));
texnum = (texnums_t*)(skin + h->num_meshes);
shaders = (shader_t**)(skin + h->num_meshes);
#endif
//no code to load animations or bones
@ -5900,12 +5902,12 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
skin[i].skinheight = 1;
skin[i].ofstexels = 0; /*doesn't support 8bit colourmapping*/
skin[i].skinspeed = 10; /*something to avoid div by 0*/
skin[i].texnums = 1;
skin[i].ofstexnums = (char*)&texnum[i] - (char*)&skin[i];
texnum[i].shader = R_RegisterSkin(skin[i].name, mod->name);
R_BuildDefaultTexnums(&texnum[i], texnum[i].shader);
if (texnum[i].shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum[i].shader->name, loadmodel->name);
skin[i].numshaders = 1;
skin[i].ofsshaders = (char*)&shaders[i] - (char*)&skin[i];
shaders[i] = R_RegisterSkin(skin[i].name, mod->name);
R_BuildDefaultTexnums(NULL, shaders[i]);
if (shaders[i]->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", shaders[i]->name, loadmodel->name);
gai[i].ofs_st_array = (char*)(otcoords+offset) - (char*)&gai[i];
#endif
@ -6229,7 +6231,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer, char *modname)
float *posedata;
#ifndef SERVERONLY
galiasskin_t *skin;
texnums_t *texnum;
shader_t **shaders;
#endif
char *filestart = buffer;
@ -6389,12 +6391,12 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer, char *modname)
#ifndef SERVERONLY
skin = Hunk_Alloc(sizeof(*skin));
texnum = Hunk_Alloc(sizeof(*texnum));
shaders = Hunk_Alloc(sizeof(*shaders));
inf->numskins = 1;
inf->ofsskins = (char*)skin - (char*)inf;
skin->texnums = 1;
skin->numshaders = 1;
skin->skinspeed = 1;
skin->ofstexnums = (char*)texnum - (char*)skin;
skin->ofsshaders = (char*)shaders - (char*)skin;
#endif
EXPECT("{");
for(;;)
@ -6407,10 +6409,11 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer, char *modname)
{
buffer = COM_Parse(buffer);
#ifndef SERVERONLY
texnum->shader = R_RegisterSkin(com_token, modname);
R_BuildDefaultTexnums(texnum, texnum->shader);
if (texnum->shader->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name);
//FIXME: we probably want to support multiple skins some time
shaders[0] = R_RegisterSkin(com_token, modname);
R_BuildDefaultTexnums(NULL, shaders[0]);
if (shaders[0]->flags & SHADER_NOIMAGE)
Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", shaders[0]->name, loadmodel->name);
#endif
}
else if (!strcmp(com_token, "numverts"))

View File

@ -108,8 +108,8 @@ typedef struct {
int skinheight;
int ofstexels; //this is 8bit for frame 0 only. only valid in q1 models without replacement textures, used for colourising player skins.
float skinspeed;
int texnums;
int ofstexnums;
int numshaders;
int ofsshaders;
char name [MAX_QPATH];
} galiasskin_t;

View File

@ -1681,7 +1681,7 @@ char *COM_FileExtension (const char *in)
{
static char exten[8];
int i;
char *dot;
const char *dot;
for (dot = in + strlen(in); dot >= in && *dot != '.'; dot--)
;
@ -3371,9 +3371,13 @@ void COM_Init (void)
nullentitystate.colormod[0] = 32;
nullentitystate.colormod[1] = 32;
nullentitystate.colormod[2] = 32;
nullentitystate.glowmod[0] = 32;
nullentitystate.glowmod[1] = 32;
nullentitystate.glowmod[2] = 32;
nullentitystate.trans = 255;
nullentitystate.scale = 16;
nullentitystate.abslight = 255;
nullentitystate.solid = 0;//ES_SOLID_BSP;
}

View File

@ -403,6 +403,7 @@ void COM_InitFilesystem (void);
void FS_Shutdown(void);
void COM_Gamedir (const char *dir);
char *FS_GetGamedir(void);
void *FS_GetBasedir(void);
qbyte *FS_LoadMallocFile (const char *path);
int FS_LoadFile(char *name, void **file);

View File

@ -1576,6 +1576,11 @@ char *FS_GetGamedir(void)
{
return gamedirfile;
}
/*unsafe - provided only for gamecode compat, should not be used for internal features*/
char *FS_GetBasedir(void)
{
return com_quakedir;
}
/*
================
COM_Gamedir
@ -1779,8 +1784,8 @@ const gamemode_info_t gamemode_info[] = {
{"FTE-JK2", "jk2", "-jk2", {"base/assets0.pk3"}, NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"},
{"FTE-HalfLife", "hl", "-halflife", {"valve/liblist.gam"}, NULL, {"valve", "ftehl"}, "Half-Life"},
{"FTE-Doom", "doom", "-doom", {"doom.wad"}, NULL, { "ftedoom"}, "Doom"},
{"FTE-Doom2", "doom2", "-doom2", {"doom2.wad"}, NULL, { "ftedoom"}, "Doom2"},
{"FTE-Doom", "doom", "-doom", {"doom.wad"}, NULL, {"*doom.wad", "ftedoom"}, "Doom"},
{"FTE-Doom2", "doom2", "-doom2", {"doom2.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"},
{NULL}
};
@ -2023,24 +2028,6 @@ char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum)
return buffer;
}
#ifdef DOOMWADS
void FS_AddRootWads(void)
{
vfsfile_t *vfs;
char *fname = "doom.wad";
void *pak;
extern searchpathfuncs_t doomwadfilefuncs;
vfs = FS_OpenVFS(fname, "rb", FS_ROOT);
pak = doomwadfilefuncs.OpenNew(vfs, fname);
if (!pak)
return;
FS_AddPathHandle(fname, fname, &doomwadfilefuncs, pak, true, false, true, (unsigned int)-1);
}
#endif
/*
================
FS_ReloadPackFiles
@ -2084,10 +2071,6 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
com_base_searchpaths = NULL;
#ifdef DOOMWADS
FS_AddRootWads();
#endif
while(oldpaths)
{
next = oldpaths->nextpure;
@ -2390,9 +2373,47 @@ void FS_Shutdown(void)
}
void FS_AddGamePack(const char *pakname)
{
int j;
char *ext = COM_FileExtension(pakname);
vfsfile_t *vfs = VFSOS_Open(pakname, "rb");
void *pak;
if (!vfs)
Con_Printf("Unable to open %s - missing?\n", pakname);
else
{
for (j = 0; j < sizeof(searchpathformats)/sizeof(searchpathformats[0]); j++)
{
if (!searchpathformats[j].extension || !searchpathformats[j].funcs || !searchpathformats[j].funcs->OpenNew)
continue;
if (!strcmp(ext, searchpathformats[j].extension))
{
pak = searchpathformats[j].funcs->OpenNew(vfs, pakname);
if (pak)
{
FS_AddPathHandle("", pakname, searchpathformats[j].funcs, pak, true, false, true, (unsigned int)-1);
}
else
{
Con_Printf("Unable to open %s - corrupt?\n", pakname);
VFS_CLOSE(vfs);
}
vfs = NULL;
break;
}
}
if (vfs)
{
VFS_CLOSE(vfs);
Con_Printf("Unable to open %s - unsupported?\n", pakname);
}
}
}
void FS_StartupWithGame(int gamenum)
{
int i, j;
int i;
#ifdef AVAIL_ZLIB
LibZ_Init();
@ -2401,48 +2422,11 @@ void FS_StartupWithGame(int gamenum)
Cvar_Set(&com_protocolname, gamemode_info[gamenum].protocolname);
Cvar_ForceSet(&fs_gamename, gamemode_info[gamenum].poshname);
#ifdef DOOMWADS
FS_AddRootWads();
#endif
i = COM_CheckParm ("-basepack");
while (i && i < com_argc-1)
{
// Con_Printf("found -basepack: %s\n", com_argv[i+1]);
char *ext = COM_FileExtension(com_argv[i+1]);
vfsfile_t *vfs = VFSOS_Open(com_argv[i+1], "rb");
void *pak;
if (!vfs)
Con_Printf("Unable to open %s - missing?\n", com_argv[i+1]);
else
{
for (j = 0; j < sizeof(searchpathformats)/sizeof(searchpathformats[0]); j++)
{
if (!searchpathformats[j].extension || !searchpathformats[j].funcs || !searchpathformats[j].funcs->OpenNew)
continue;
if (!strcmp(ext, searchpathformats[j].extension))
{
pak = searchpathformats[j].funcs->OpenNew(vfs, com_argv[i+1]);
if (pak)
{
FS_AddPathHandle("", com_argv[i+1], searchpathformats[j].funcs, pak, true, false, true, (unsigned int)-1);
}
else
{
Con_Printf("Unable to open %s - corrupt?\n", com_argv[i+1]);
VFS_CLOSE(vfs);
}
vfs = NULL;
break;
}
}
if (vfs)
{
VFS_CLOSE(vfs);
Con_Printf("Unable to open %s - unsupported?\n", com_argv[i+1]);
}
}
FS_AddGamePack(com_argv[i+1]);
i = COM_CheckNextParm ("-basepack", i);
}
@ -2466,7 +2450,13 @@ void FS_StartupWithGame(int gamenum)
{
for (i = 0; i < sizeof(gamemode_info[gamenum].dir)/sizeof(gamemode_info[gamenum].dir[0]); i++)
{
if (gamemode_info[gamenum].dir[i])
if (gamemode_info[gamenum].dir[i] && *gamemode_info[gamenum].dir[i] == '*')
{
char buf[MAX_OSPATH];
snprintf(buf, sizeof(buf), "%s%s", com_quakedir, gamemode_info[gamenum].dir[i]+1);
FS_AddGamePack(buf);
}
else if (gamemode_info[gamenum].dir[i])
{
FS_AddGameDirectory (gamemode_info[gamenum].dir[i], va("%s%s", com_quakedir, gamemode_info[gamenum].dir[i]), ~0);
if (*com_homedir)

View File

@ -120,6 +120,7 @@ typedef struct
qboolean nqreliable_allowed;
#endif
struct netprim_s netprim;
int fragmentsize;
float last_received; // for timeouts
@ -181,6 +182,8 @@ void VARGS Netchan_OutOfBandPrint (netsrc_t sock, netadr_t adr, char *format, ..
void VARGS Netchan_OutOfBandTPrintf (netsrc_t sock, netadr_t adr, int language, translation_t text, ...);
qboolean Netchan_Process (netchan_t *chan);
void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport);
unsigned int Net_PextMask(int maskset);
extern cvar_t net_mtu;
qboolean Netchan_CanPacket (netchan_t *chan, int rate);
void Netchan_Block (netchan_t *chan, int bytes, int rate);

View File

@ -36,7 +36,9 @@ packet header
1 does this message contain a reliable payload
31 acknowledge sequence
1 acknowledge receipt of even/odd message
16 qport
16 qport (only from client)
15 fragoffset (extension)
1 lastfrag (extension)
The remote connection never knows if it missed a reliable message, the
local side detects that it has been dropped by seeing a sequence acknowledge
@ -74,6 +76,7 @@ If the base part of the net address matches and the qport matches, then the
channel matches even if the IP port differs. The IP port should be updated
to the new value before sending out any replies.
fragmentation works like IP, offset and morefrags. offset is *8 (decode: (offset&~1)<<2 to avoid stomping on the morefrags flag, this allows really jumbo packets with 18 bits of length)
*/
@ -81,6 +84,106 @@ int net_drop;
cvar_t showpackets = SCVAR("showpackets", "0");
cvar_t showdrop = SCVAR("showdrop", "0");
cvar_t qport = SCVAR("qport", "0");
cvar_t net_mtu = CVARD("mtu", "1450", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
cvar_t pext_replacementdeltas = CVAR("debug_pext_replacementdeltas", "0"); /*rename once the extension is finalized*/
/*returns the bitmask of supported+enabled extensions*/
unsigned int Net_PextMask(int maskset)
{
unsigned int mask = 0;
if (maskset == 1) /*FTEX*/
{
#ifdef PEXT_SCALE //dmw - protocol extensions
mask |= PEXT_SCALE;
#endif
#ifdef PEXT_LIGHTSTYLECOL
mask |= PEXT_LIGHTSTYLECOL;
#endif
#ifdef PEXT_TRANS
mask |= PEXT_TRANS;
#endif
#ifdef PEXT_VIEW2
mask |= PEXT_VIEW2;
#endif
#ifdef PEXT_ACCURATETIMINGS
mask |= PEXT_ACCURATETIMINGS;
#endif
#ifdef PEXT_ZLIBDL
mask |= PEXT_ZLIBDL;
#endif
#ifdef PEXT_FATNESS
mask |= PEXT_FATNESS;
#endif
#ifdef PEXT_HLBSP
mask |= PEXT_HLBSP;
#endif
#ifdef PEXT_Q2BSP
mask |= PEXT_Q2BSP;
#endif
#ifdef PEXT_Q3BSP
mask |= PEXT_Q3BSP;
#endif
#ifdef PEXT_TE_BULLET
mask |= PEXT_TE_BULLET;
#endif
#ifdef PEXT_HULLSIZE
mask |= PEXT_HULLSIZE;
#endif
#ifdef PEXT_SETVIEW
mask |= PEXT_SETVIEW;
#endif
#ifdef PEXT_MODELDBL
mask |= PEXT_MODELDBL;
#endif
#ifdef PEXT_SOUNDDBL
mask |= PEXT_SOUNDDBL;
#endif
#ifdef PEXT_VWEAP
mask |= PEXT_VWEAP;
#endif
#ifdef PEXT_FLOATCOORDS
mask |= PEXT_FLOATCOORDS;
#endif
mask |= PEXT_SPAWNSTATIC2;
mask |= PEXT_COLOURMOD;
mask |= PEXT_SPLITSCREEN;
mask |= PEXT_HEXEN2;
mask |= PEXT_CUSTOMTEMPEFFECTS;
mask |= PEXT_256PACKETENTITIES;
mask |= PEXT_ENTITYDBL;
mask |= PEXT_ENTITYDBL2;
mask |= PEXT_SHOWPIC;
mask |= PEXT_SETATTACHMENT;
#ifdef PEXT_CHUNKEDDOWNLOADS
mask |= PEXT_CHUNKEDDOWNLOADS;
#endif
#ifdef PEXT_CSQC
mask |= PEXT_CSQC;
#endif
#ifdef PEXT_DPFLAGS
mask |= PEXT_DPFLAGS;
#endif
}
else if (maskset == 2)
{
mask |= PEXT2_PRYDONCURSOR;
#ifdef PEXT2_VOICECHAT
mask |= PEXT2_VOICECHAT;
#endif
mask |= PEXT2_SETANGLEDELTA;
if (pext_replacementdeltas.ival)
mask |= PEXT2_REPLACEMENTDELTAS;
if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS;
}
return mask;
}
/*
===============
@ -92,6 +195,12 @@ void Netchan_Init (void)
{
int port;
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking");
Cvar_Register (&qport, "Networking");
Cvar_Register (&net_mtu, "Networking");
// pick a port value that should be nice and random
#ifdef _WIN32
port = (time(NULL)) & 0xffff;
@ -99,10 +208,7 @@ void Netchan_Init (void)
port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
#endif
Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking");
Cvar_Register (&qport, "Networking");
Cvar_SetValue(&qport, port);
Cvar_SetValue (&qport, port);
}
/*
@ -496,9 +602,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
// write the packet header
send.data = send_buf;
send.maxsize = MAX_QWMSGLEN + PACKET_HEADER; //dmw: wasn't quite true.
if (chan->sock == NS_CLIENT)
send.maxsize += 2;
send.maxsize = MAX_QWMSGLEN + PACKET_HEADER;
send.cursize = 0;
w1 = chan->outgoing_sequence | (send_reliable<<31);
@ -515,6 +619,13 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
MSG_WriteShort (&send, cls.qport);
#endif
if (chan->fragmentsize)
{
//allow the max size to be bigger
send.maxsize = MAX_OVERALLMSGLEN + PACKET_HEADER;
MSG_WriteShort(&send, 0);
}
// copy the reliable message to the packet first
if (send_reliable)
{
@ -535,7 +646,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
if (chan->compress)
{
//int oldsize = send.cursize;
Huff_CompressPacket(&send, (chan->sock == NS_CLIENT)?10:8);
Huff_CompressPacket(&send, 8 + ((chan->sock == NS_CLIENT)?2:0) + (chan->fragmentsize?2:0));
// Con_Printf("%i becomes %i\n", oldsize, send.cursize);
// Huff_DecompressPacket(&send, (chan->sock == NS_CLIENT)?10:8);
}
@ -546,7 +657,45 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
if (!cls.demoplayback)
#endif
{
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
int hsz = 10 + ((chan->sock == NS_CLIENT)?2:0); /*header size, if fragmentation is in use*/
if (!chan->fragmentsize || send.cursize < chan->fragmentsize - hsz)
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
else
{
int offset = chan->fragmentsize, no;
qboolean more;
/*switch on the 'more flags' bit, and send the first part*/
send.data[hsz - 2] |= 0x1;
NET_SendPacket (chan->sock, offset, send.data, chan->remote_address);
/*send the additional parts, adding new headers within the previous packet*/
while(offset < send.cursize)
{
no = offset + chan->fragmentsize - hsz;
if (no < send.cursize)
{
more = true;
no &= 7;
if (no == offset)
break;
}
else
{
no = send.cursize;
more = false;
}
*(int*)&send.data[(offset - hsz) + 0] = LittleLong(w1);
*(int*)&send.data[(offset - hsz) + 4] = LittleLong(w2);
if (chan->sock == NS_CLIENT)
*(short*)&send.data[offset - 4] = LittleShort(cls.qport);
*(short*)&send.data[offset - 2] = LittleShort(((offset-hsz)>>2) | (more?1:0));
NET_SendPacket (chan->sock, (no - offset) + hsz, send.data + offset - hsz, chan->remote_address);
offset = no;
}
}
}
Netchan_Block(chan, send.cursize, rate);
@ -562,7 +711,6 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
, chan->incoming_sequence
, chan->incoming_reliable_sequence
, send.cursize);
return send.cursize;
}
@ -583,6 +731,7 @@ qboolean Netchan_Process (netchan_t *chan)
#ifndef CLIENTONLY
int qport;
#endif
int offset;
if (
#ifndef SERVERONLY
@ -602,6 +751,11 @@ qboolean Netchan_Process (netchan_t *chan)
qport = MSG_ReadShort ();
#endif
if (chan->fragmentsize)
offset = (unsigned short)MSG_ReadShort();
else
offset = 0;
reliable_message = sequence >> 31;
reliable_ack = sequence_ack >> 31;
@ -659,6 +813,53 @@ qboolean Netchan_Process (netchan_t *chan)
return false;
}
if (offset)
{
int len = net_message.cursize - msg_readcount;
qboolean more = false;
if (offset & 1)
{
more = true;
offset &= ~1;
offset = offset << 2;
}
if (offset + len > sizeof(chan->in_fragment_buf)) /*stop the overflow*/
{
if (showdrop.value)
Con_Printf("Dropping packet - too many fragments\n");
return false;
}
if (chan->incoming_unreliable != sequence)
{
/*sequence doesn't match, forget the old*/
chan->in_fragment_length = 0;
chan->incoming_unreliable = sequence;
}
if (offset != chan->in_fragment_length)
return false; /*dropped one*/
memcpy(chan->in_fragment_buf + offset, net_message.data + msg_readcount, len);
chan->in_fragment_length += net_message.cursize - msg_readcount;
if (more)
{
/*nothing to process yet*/
return false;
}
memcpy(net_message.data, chan->in_fragment_buf, chan->in_fragment_length);
msg_readcount = 0;
net_message.cursize = chan->in_fragment_length;
chan->incoming_unreliable = 0;
chan->in_fragment_length = 0;
}
else
{
/*kill any pending reliable*/
chan->incoming_unreliable = 0;
chan->in_fragment_length = 0;
}
//
// dropped packets don't keep the message from being used
//

View File

@ -75,6 +75,7 @@ extern cvar_t sv_port_tcp;
extern cvar_t sv_port_tcp6;
#endif
cvar_t net_hybriddualstack = CVAR("net_hybriddualstack", "1");
cvar_t net_fakeloss = CVARFD("net_fakeloss", "0", CVAR_CHEAT, "Simulates packetloss in both receiving and sending, on a scale from 0 to 1.");
extern cvar_t sv_public, sv_listen_qw, sv_listen_nq, sv_listen_dp, sv_listen_q3;
@ -2890,15 +2891,23 @@ int NET_GetPacket (netsrc_t netsrc, int firstsock)
if (!collection)
return -1;
for (; firstsock < MAX_CONNECTIONS; firstsock+=1)
while (firstsock < MAX_CONNECTIONS)
{
if (!collection->conn[firstsock])
break;
if (collection->conn[firstsock]->GetPacket(collection->conn[firstsock]))
{
if (net_fakeloss.value)
{
if (frandom () < net_fakeloss.value)
continue;
}
net_from.connum = firstsock+1;
return firstsock;
}
firstsock += 1;
}
return -1;
@ -2945,6 +2954,12 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
if (!collection)
return;
if (net_fakeloss.value)
{
if (frandom () < net_fakeloss.value)
return;
}
if (to.connum)
{
if (collection->conn[to.connum-1])
@ -3487,6 +3502,7 @@ void NET_Init (void)
#endif
Cvar_Register(&net_hybriddualstack, "networking");
Cvar_Register(&net_fakeloss, "networking");
#ifndef CLIENTONLY
Cmd_AddCommand("sv_addport", SVNET_AddPort_f);

View File

@ -516,7 +516,7 @@ void PM_WaterMove (void)
for (i=0 ; i<3 ; i++)
wishvel[i] = forward[i]*pmove.cmd.forwardmove + right[i]*pmove.cmd.sidemove;
if (pmove.pm_type != PM_FLY && !pmove.cmd.forwardmove && !pmove.cmd.sidemove && !pmove.cmd.upmove)
if (pmove.pm_type != PM_FLY && !pmove.cmd.forwardmove && !pmove.cmd.sidemove && !pmove.cmd.upmove && !pmove.onladder)
wishvel[2] -= 60; // drift towards bottom
else
wishvel[2] += pmove.cmd.upmove;
@ -760,13 +760,11 @@ void PM_CategorizePosition (void)
}
}
if (cont & Q2CONTENTS_LADDER && pmove.physents[0].model->fromgame == fg_quake2)
pmove.onladder = true;
else
pmove.onladder = false;
//bsp objects marked as ladders mark regions to stand in to be classed as on a ladder.
cont = PM_ExtraBoxContents(pmove.origin);
//are we on a ladder?
#ifdef Q2BSPS
//q3 has surfaceflag-based ladders
if (pmove.physents[0].model->fromgame == fg_quake3)
{
trace_t t;
@ -786,7 +784,9 @@ void PM_CategorizePosition (void)
pmove.onground = false; // too steep
}
}
if (cont & Q2CONTENTS_LADDER && pmove.physents[0].model->fromgame == fg_quake2)
#endif
//q2 has contents-based ladders
if ((cont & FTECONTENTS_LADDER) || ((cont & Q2CONTENTS_LADDER) && pmove.physents[0].model->fromgame == fg_quake2))
{
trace_t t;
vec3_t flatforward, fwd1;
@ -799,25 +799,13 @@ void PM_CategorizePosition (void)
VectorMA (pmove.origin, 24, flatforward, fwd1);
//if we hit a wall when going forwards and we are in a ladder region, then we are on a ladder.
if (pmove.physents[0].model->fromgame == fg_quake2)
t = PM_PlayerTrace(pmove.origin, fwd1);
if (t.fraction < 1)
{
t = CM_BoxTrace(pmove.physents[0].model, pmove.origin, fwd1, player_mins, player_maxs, MASK_PLAYERSOLID);
if (t.fraction < 1)
{
pmove.onladder = true;
pmove.onground = false; // too steep
}
pmove.onladder = true;
pmove.onground = false; // too steep
}
}
#endif
//bsp objects marked as ladders mark regions to stand in to be classed as on a ladder.
cont = PM_ExtraBoxContents(pmove.origin);
if ((cont & Q2CONTENTS_LADDER) && (pmove.physents[0].model->fromgame == fg_quake2 || pmove.physents[0].model->fromgame == fg_halflife))
{
pmove.onladder = true;
pmove.onground = false; // too steep
}
if (pmove.onground && pmove.pm_type != PM_FLY && pmove.waterlevel < 2)
{
@ -956,7 +944,7 @@ void PM_NudgePosition (void)
VectorCopy (pmove.origin, base);
for (i=0 ; i<3 ; i++)
pmove.origin[i] = ((int)(pmove.origin[i]*8)) * 0.125;
base[i] = ((int)(base[i]*8)) * 0.125;
for (z=0 ; z<=4 ; z++)
{

View File

@ -60,7 +60,6 @@ typedef struct
int jump_msec; // msec since last jump
float waterjumptime;
int pm_type;
int hullnum;
// world state
int numphysent;
@ -72,6 +71,7 @@ typedef struct
qboolean onladder;
// results
int skipent;
int numtouch;
int touchindex[MAX_PHYSENTS];
vec3_t touchvel[MAX_PHYSENTS];

View File

@ -125,26 +125,35 @@ int PM_PointContents (vec3_t p)
for (num = 1; num < pmove.numphysent; num++)
{
pe = &pmove.physents[num];
if (pe->info == pmove.skipent)
continue;
pm = pe->model;
if (pm)
{
if (pe->forcecontentsmask)
if (p[0] >= pe->origin[0]+pm->mins[0] && p[0] <= pe->origin[0]+pm->maxs[0] &&
p[1] >= pe->origin[1]+pm->mins[1] && p[1] <= pe->origin[1]+pm->maxs[1] &&
p[2] >= pe->origin[2]+pm->mins[2] && p[2] <= pe->origin[2]+pm->maxs[2])
{
if (PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles))
pc |= pe->forcecontentsmask;
}
else
{
if (pe->nonsolid)
continue;
pc |= PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles);
if (pe->forcecontentsmask)
{
if (PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles))
pc |= pe->forcecontentsmask;
}
else
{
if (pe->nonsolid)
continue;
pc |= PM_TransformedModelPointContents(pm, p, pe->origin, pe->angles);
}
}
}
else if (pe->forcecontentsmask)
{
if (p[0] >= pe->mins[0] && p[0] <= pe->maxs[0] &&
p[1] >= pe->mins[1] && p[1] <= pe->maxs[1] &&
p[2] >= pe->mins[2] && p[2] <= pe->maxs[2])
if (p[0] >= pe->origin[0]+pe->mins[0] && p[0] <= pe->origin[0]+pe->maxs[0] &&
p[1] >= pe->origin[1]+pe->mins[1] && p[1] <= pe->origin[1]+pe->maxs[1] &&
p[2] >= pe->origin[2]+pe->mins[2] && p[2] <= pe->origin[2]+pe->maxs[2])
pc |= pe->forcecontentsmask;
}
}
@ -179,9 +188,9 @@ int PM_ExtraBoxContents (vec3_t p)
}
else if (pe->forcecontentsmask)
{
if (p[0]+player_maxs[0] >= pe->mins[0] && p[0]+player_mins[0] <= pe->maxs[0] &&
p[1]+player_maxs[1] >= pe->mins[1] && p[1]+player_mins[1] <= pe->maxs[1] &&
p[2]+player_maxs[2] >= pe->mins[2] && p[2]+player_mins[2] <= pe->maxs[2])
if (p[0]+player_maxs[0] >= pe->origin[0]+pe->mins[0] && p[0]+player_mins[0] <= pe->origin[0]+pe->maxs[0] &&
p[1]+player_maxs[1] >= pe->origin[1]+pe->mins[1] && p[1]+player_mins[1] <= pe->origin[1]+pe->maxs[1] &&
p[2]+player_maxs[2] >= pe->origin[2]+pe->mins[2] && p[2]+player_mins[2] <= pe->origin[2]+pe->maxs[2])
pc |= pe->forcecontentsmask;
}
}
@ -267,6 +276,9 @@ qboolean PM_TestPlayerPosition (vec3_t pos)
{
pe = &pmove.physents[i];
if (pe->info == pmove.skipent)
continue;
if (pe->nonsolid)
continue;
@ -316,6 +328,8 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end)
if (pe->nonsolid)
continue;
if (pe->info == pmove.skipent)
continue;
if (!pe->model || pe->model->needload)
{
@ -363,6 +377,5 @@ trace_t PM_TraceLine (vec3_t start, vec3_t end)
{
VectorClear(player_mins);
VectorClear(player_maxs);
pmove.hullnum = 0;
return PM_PlayerTrace(start, end);
}

View File

@ -303,7 +303,7 @@ void QCBUILTIN PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *
mvertex_t *v1, *v2;
int edge;
int e;
float bestdist = 10000000000000, dist;
float bestdist = 0x7fffffff, dist;
int bestsurf = -1;
world_t *w = prinst->parms->user;
@ -2094,7 +2094,6 @@ void QCBUILTIN PF_strftime (progfuncs_t *prinst, struct globalvars_s *pr_globals
else
tm = gmtime(&ctime);
strftime(result, sizeof(result), in, tm);
Q_strncpyz(result, in, sizeof(result));
strtoupper(result);
RETURN_TSTRING(result);

View File

@ -465,3 +465,12 @@ enum lightfield_e
lfield_diffusescale=11,
lfield_specularscale=12
};
enum csqc_input_event
{
/*devid is the player id (on android, its the multitouch id and is always present even in single player)*/
CSIE_KEYDOWN = 0, /*syscode, unicode, devid*/
CSIE_KEYUP = 1, /*syscode, unicode, devid*/
CSIE_MOUSEDELTA = 2, /*x, y, devid*/
CSIE_MOUSEABS = 3, /*x, y, devid*/
CSIE_ACCELEROMETER = 4 /*x, y, z*/
};

View File

@ -52,10 +52,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT_SPAWNSTATIC2 0x00400000 //Sends an entity delta instead of a baseline.
#define PEXT_CUSTOMTEMPEFFECTS 0x00800000 //supports custom temp ents.
#define PEXT_256PACKETENTITIES 0x01000000 //Client can recieve 256 packet entities.
//#define PEXT_NEVERUSED 0x02000000 //Client is able to cope with 64 players. Wow.
//#define PEXT_NEVERUSED 0x02000000
#define PEXT_SHOWPIC 0x04000000
#define PEXT_SETATTACHMENT 0x08000000 //md3 tags (needs networking, they need to lerp).
//#define PEXT_NEVERUSED 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs)
//#define PEXT_NEVERUSED 0x10000000
#define PEXT_CHUNKEDDOWNLOADS 0x20000000 //alternate file download method. Hopefully it'll give quadroupled download speed, especially on higher pings.
#ifdef CSQC_DAT
@ -73,7 +73,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT2_PRYDONCURSOR 0x00000001
#define PEXT2_VOICECHAT 0x00000002
#define PEXT2_SETANGLEDELTA 0x00000004
//#define PEXT2_64PLAYERS 0x02000000 //Client is able to cope with 64 players. Wow.
#define PEXT2_REPLACEMENTDELTAS 0x00000008
#define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues.
//#define PEXT2_PK3DOWNLOADS 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs)
//ZQuake transparent protocol extensions.
@ -95,7 +96,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PROTOCOL_VERSION_FTE (('F'<<0) + ('T'<<8) + ('E'<<16) + ('X' << 24)) //fte extensions.
#define PROTOCOL_VERSION_FTE2 (('F'<<0) + ('T'<<8) + ('E'<<16) + ('2' << 24)) //fte extensions.
#define PROTOCOL_VERSION_HUFFMAN (('H'<<0) + ('U'<<8) + ('F'<<16) + ('F' << 24)) //packet compression
#define PROTOCOL_VERSION_VARLENGTH (('v'<<0) + ('l'<<8) + ('e'<<16) + ('n' << 24)) //packet compression
#define PROTOCOL_VERSION_VARLENGTH (('v'<<0) + ('l'<<8) + ('e'<<16) + ('n' << 24)) //variable length handshake
#define PROTOCOL_VERSION_FRAGMENT (('F'<<0) + ('R'<<8) + ('A'<<16) + ('G' << 24)) //supports fragmentation/packets larger than 1450
#define PROTOCOL_INFO_GUID (('G'<<0) + ('U'<<8) + ('I'<<16) + ('D' << 24)) //globally 'unique' client id info.
@ -276,6 +278,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define svcfte_cgamepacket 83
#define svcfte_voicechat 84
#define svcfte_setangledelta 85 // [angle3] add this to the current viewangles
#define svcfte_updateentities 86
//fitz svcs
@ -513,6 +516,57 @@ enum clcq2_ops_e
#endif
//first byte contains the stuff that's most likely to change constantly*/
#define UF_FRAME (1u<<0)
#define UF_ORIGINXY (1u<<1)
#define UF_ORIGINZ (1u<<2)
#define UF_ANGLESXZ (1u<<4)
#define UF_ANGLESY (1u<<3)
#define UF_EFFECTS (1u<<5)
#define UF_PREDINFO (1u<<6) /*ent is predicted, probably a player*/
#define UF_EXTEND1 (1u<<7)
/*stuff which is common on ent spawning*/
#define UF_RESET (1u<<8)
#define UF_16BIT (1u<<9) /*within this update, frame/skin/model is 16bit, not part of the deltaing itself*/
#define UF_MODEL (1u<<10)
#define UF_SKIN (1u<<11)
#define UF_COLORMAP (1u<<12)
#define UF_SOLID (1u<<13)
#define UF_FLAGS (1u<<14)
#define UF_EXTEND2 (1u<<15)
/*the rest is optional extensions*/
#define UF_ALPHA (1u<<16)
#define UF_SCALE (1u<<17)
#define UF_ABSLIGHT (1u<<18)
#define UF_DRAWFLAGS (1u<<19)
#define UF_TAGINFO (1u<<20)
#define UF_LIGHT (1u<<21)
#define UF_EFFECTS2 (1u<<22)
#define UF_EXTEND3 (1u<<23)
#define UF_COLORMOD (1u<<24)
#define UF_GLOWMOD (1u<<25)
#define UF_FATNESS (1u<<26)
#define UF_MODELINDEX2 (1u<<27)
#define UF_UNUSED4 (1u<<28)
#define UF_UNUSED3 (1u<<29)
#define UF_UNUSED2 (1u<<30)
#define UF_UNUSED1 (1u<<31)
/*these flags are generally not deltaed as they're changing constantly*/
#define UFP_FORWARD (1u<<0)
#define UFP_SIDE (1u<<1)
#define UFP_UP (1u<<2)
#define UFP_MOVETYPE (1u<<3) /*deltaed*/
#define UFP_VELOCITYXY (1u<<4)
#define UFP_VELOCITYZ (1u<<5)
#define UFP_MSEC (1u<<6)
#define UF_REMOVE UF_16BIT /*special flag, slightly more compact (we can reuse the 16bit flag as its not important)*/
#ifdef NQPROT
@ -716,7 +770,8 @@ enum {
==========================================================
*/
#define MAX_CLIENTS 32
#define MAX_CLIENTS 32 /*max 255, min 32*/
#define QWMAX_CLIENTS 32 /*QW's standard max*/
#define UPDATE_BACKUP 64 // copies of entity_state_t to keep buffered
// must be power of two
@ -738,7 +793,6 @@ typedef struct entity_state_s
{
unsigned short number; // edict index
unsigned short modelindex;
unsigned int bitmask; // for dp ents, so lost state can be repeated in replacement packets.
unsigned int flags; // nolerp, etc
@ -747,35 +801,51 @@ typedef struct entity_state_s
vec3_t origin;
vec3_t angles;
#if defined(Q2CLIENT) || defined(Q2SERVER)
int renderfx; //q2
vec3_t old_origin; //q2/q3
qbyte modelindex3; //q2
qbyte modelindex4; //q2
qbyte sound; //q2
qbyte event; //q2
unsigned short modelindex2; //q2
union
{
struct
{
int renderfx; //q2
vec3_t old_origin; //q2/q3
qbyte modelindex3; //q2
qbyte modelindex4; //q2
qbyte sound; //q2
qbyte event; //q2
} q2;
struct
{
/*info to predict other players, so I don't get yelled at if fte were to stop supporting it*/
qbyte pmovetype;
qbyte msec;
short movement[3];
short velocity[3]; // 1/8th
} q1;
} u;
#endif
unsigned short modelindex2; //q2/vweps
unsigned short frame;
unsigned int skinnum; /*q2 needs 32 bits, which is quite impressive*/
unsigned short colormap;
//pad 2 bytes
qbyte glowsize;
qbyte glowcolour;
qbyte scale;
char fatness;
qbyte hexen2flags;
qbyte abslight;
qbyte dpflags;
//pad
qbyte dpflags;
qbyte colormod[3];//multiply this by 8 to read as 0 to 1...
qbyte glowmod[3];
qbyte trans;
qbyte lightstyle;
qbyte lightpflags;
unsigned short solid;
#define ES_SOLID_BSP 31
unsigned short light[4];
@ -1278,10 +1348,8 @@ typedef struct q1usercmd_s
#define RENDER_EXTERIORMODEL 8
#define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth
#define RENDER_COLORMAPPED 32
//#define RENDER_INDIRECT 64
#define RENDER_SHADOW 65536 // cast shadow
#define RENDER_LIGHT 131072 // receive light
#define RENDER_TRANSPARENT 262144 // can't light during opaque stage
//#define RENDER_WORLDOBJECT 64
//#define RENDER_COMPLEXANIMATION 128
//darkplaces protocols 5 to 7 use these
// reset all entity fields (typically used if status changed)
@ -1347,7 +1415,7 @@ typedef struct q1usercmd_s
#define E5_EXTEND3 (1<<23)
// unused
#define E5_UNUSED24 (1<<24)
#define E5_GLOWMOD (1<<24)
// unused
#define E5_UNUSED25 (1<<25)
// unused
@ -1363,7 +1431,7 @@ typedef struct q1usercmd_s
// bits2 > 0
#define E5_EXTEND4 (1<<31)
#define E5_ALLUNUSED (E5_UNUSED24|E5_UNUSED25|E5_UNUSED26|E5_UNUSED27|E5_UNUSED28|E5_UNUSED29|E5_UNUSED30)
#define E5_ALLUNUSED (E5_UNUSED25|E5_UNUSED26|E5_UNUSED27|E5_UNUSED28|E5_UNUSED29|E5_UNUSED30)
#define FITZB_LARGEMODEL (1<<0) // modelindex is short instead of byte
#define FITZB_LARGEFRAME (1<<1) // frame is short instead of byte

View File

@ -66,7 +66,7 @@ enum
vec3_t rht_start, rht_end;
static int Q1BSP_RecursiveHullTrace (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
{
dclipnode_t *node;
mclipnode_t *node;
mplane_t *plane;
float t1, t2;
vec3_t mid;
@ -152,7 +152,6 @@ reenter:
if (rht != rht_solid)
return rht;
trace->fraction = midf;
if (side)
{
/*we impacted the back of the node, so flip the plane*/
@ -167,6 +166,13 @@ reenter:
VectorCopy(plane->normal, trace->plane.normal);
midf = (t1 - DIST_EPSILON) / (t1 - t2);
}
t1 = DotProduct (trace->plane.normal, rht_start) - trace->plane.dist;
t2 = DotProduct (trace->plane.normal, rht_end) - trace->plane.dist;
midf = (t1 - DIST_EPSILON) / (t1 - t2);
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
VectorInterpolate(rht_start, midf, rht_end, trace->endpos);
@ -396,11 +402,11 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
if (size[0] < 3) // Point
hull = &model->hulls[0];
else if (size[0] <= 8 && model->hulls[4].available)
else if (size[0] <= 8.1 && model->hulls[4].available)
hull = &model->hulls[4]; //Pentacles
else if (size[0] <= 32 && size[2] <= 28) // Half Player
else if (size[0] <= 32.1 && size[2] <= 28.1) // Half Player
hull = &model->hulls[3];
else if (size[0] <= 32) // Full Player
else if (size[0] <= 32.1) // Full Player
hull = &model->hulls[1];
else // Golumn
hull = &model->hulls[5];
@ -409,9 +415,9 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
{
if (size[0] < 3 || !model->hulls[1].available)
hull = &model->hulls[0];
else if (size[0] <= 32)
else if (size[0] <= 32.1)
{
if (size[2] < 54 && model->hulls[3].available)
if (size[2] < 54.1 && model->hulls[3].available)
hull = &model->hulls[3]; // 32x32x36 (half-life's crouch)
else
hull = &model->hulls[1];

View File

@ -169,6 +169,8 @@ struct world_s
int lastcheck; // used by PF_checkclient
double lastchecktime; // for monster ai
float defaultgravityscale; //0 in QW, 1 for anything else (inc csqc)
/*antilag*/
float lagentsfrac;
laggedentinfo_t *lagents;

View File

@ -1535,6 +1535,8 @@ void *Hunk_TempAllocMore (int size)
#if TEMPDEBUG>0
hnktemps_t *nt;
nt = (hnktemps_t*)malloc(size + sizeof(hnktemps_t) + TEMPDEBUG*2);
if (!nt)
return NULL;
nt->next = hnktemps;
nt->len = size;
hnktemps = nt;
@ -1547,6 +1549,8 @@ void *Hunk_TempAllocMore (int size)
#else
hnktemps_t *nt;
nt = (hnktemps_t*)malloc(size + sizeof(hnktemps_t));
if (!nt)
return NULL;
nt->next = hnktemps;
hnktemps = nt;
buf = (void *)(nt+1);

View File

@ -1181,7 +1181,7 @@ static void D3D9_SetupViewPort(void)
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
if (r_waterwarp.value<0 && r_viewleaf->contents <= Q1CONTENTS_WATER)
if (r_waterwarp.value<0 && r_viewcontents & FTECONTENTS_FLUID)
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);

View File

@ -139,7 +139,6 @@ Global
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.ActiveCfg = GLRelease|Win32

View File

@ -699,6 +699,7 @@
GenerateDebugInformation="true"
GenerateMapFile="true"
SubSystem="2"
LargeAddressAware="2"
TargetMachine="1"
/>
<Tool

View File

@ -28,14 +28,17 @@ public class FTEDroidActivity extends Activity
private SensorManager sensorman;
private Sensor sensoracc;
private FTEView view;
float acc_x, acc_y, acc_z; /*might be some minor race condition on these*/
private class FTERenderer implements GLSurfaceView.Renderer
{
private boolean inited;
private String basedir;
FTEDroidActivity act;
FTERenderer(Context ctx)
FTERenderer(Context ctx, FTEDroidActivity parent)
{
act = parent;
try
{
android.content.pm.PackageInfo info = ctx.getPackageManager().getPackageInfo("com.fteqw", 0);
@ -45,6 +48,8 @@ public class FTEDroidActivity extends Activity
{
/*oh well, can just use the homedir instead*/
}
android.util.Log.i("FTEDroid", "Base dir is \"" + basedir + "\".");
}
@Override
@ -52,12 +57,13 @@ public class FTEDroidActivity extends Activity
{
if (inited == true)
{
FTEDroidEngine.frame();
FTEDroidEngine.frame(act.acc_x, act.acc_y, act.acc_z);
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
android.util.Log.i("FTEDroid", "Surface changed, now " + width + " by " + height + ".");
FTEDroidEngine.init(width, height, basedir);
inited = true;
}
@ -146,17 +152,19 @@ public class FTEDroidActivity extends Activity
at.play();
}
public FTEView(Context context)
public FTEView(FTEDroidActivity context)
{
super(context);
rndr = new FTERenderer(getContext());
rndr = new FTERenderer(context, context);
// setEGLConfigChooser(new FTEEGLConfig());
setRenderer(rndr);
setFocusable(true);
setFocusableInTouchMode(true);
android.util.Log.i("FTEDroid", "starting audio");
audioInit();
android.util.Log.i("FTEDroid", "audio running");
}
private void sendKey(final boolean presseddown, final int qcode, final int unicode)
@ -169,42 +177,81 @@ public class FTEDroidActivity extends Activity
}
});
}
private void sendAccelerometer(final float x, final float y, final float z)
{
queueEvent(new Runnable()
{
public void run()
{
FTEDroidEngine.accelerometer(x, y, z);
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event)
public boolean onTouchEvent(final MotionEvent event)
{
final int act = event.getAction();
final float x = event.getX();
final float y = event.getY();
//float p = event.getPressure();
queueEvent(new Runnable()
/*the test itself requires android 4...*/
if (android.os.Build.VERSION.SDK_INT >= 5)
{
public void run()
/*Requires API level 5+ (android 2.0+)*/
queueEvent(new Runnable()
{
switch(act)
private void domove()
{
case MotionEvent.ACTION_DOWN:
FTEDroidEngine.motion(1, x, y);
break;
case MotionEvent.ACTION_UP:
FTEDroidEngine.motion(2, x, y);
break;
case MotionEvent.ACTION_MOVE:
FTEDroidEngine.motion(0, x, y);
break;
final int pointerCount = event.getPointerCount();
int i;
for (i = 0; i < pointerCount; i++)
FTEDroidEngine.motion(0, event.getPointerId(i), event.getX(i), event.getY(i));
}
}
});
public void run()
{
int id;
float x, y;
final int act = event.getAction();
domove();
switch(act & event.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
id = ((act&event.ACTION_POINTER_ID_MASK) >> event.ACTION_POINTER_ID_SHIFT);
x = event.getX(id);
y = event.getY(id);
id = event.getPointerId(id);
FTEDroidEngine.motion(1, id, x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
id = ((act&event.ACTION_POINTER_ID_MASK) >> event.ACTION_POINTER_ID_SHIFT);
x = event.getX(id);
y = event.getY(id);
id = event.getPointerId(id);
FTEDroidEngine.motion(2, id, x, y);
break;
case MotionEvent.ACTION_MOVE:
break;
}
}
});
}
else
{
queueEvent(new Runnable()
{
public void run()
{
final int act = event.getAction();
final float x = event.getX();
final float y = event.getY();
FTEDroidEngine.motion(0, 0, x, y);
switch(act)
{
case MotionEvent.ACTION_DOWN:
FTEDroidEngine.motion(1, 0, x, y);
break;
case MotionEvent.ACTION_UP:
FTEDroidEngine.motion(2, 0, x, y);
break;
case MotionEvent.ACTION_MOVE:
break;
}
}
});
}
return true;
}
/*
@ -237,6 +284,8 @@ public class FTEDroidActivity extends Activity
return '\r';
case KeyEvent.KEYCODE_BACK:
return 27;
case KeyEvent.KEYCODE_MENU:
return 241;
case KeyEvent.KEYCODE_DEL:
return 127;
default:
@ -266,47 +315,44 @@ public class FTEDroidActivity extends Activity
{
}
private float gx,gy,gz;
public void onSensorChanged(final SensorEvent event)
{
// alpha is calculated as t / (t + dT)
// with t, the low-pass filter's time-constant
// and dT, the event delivery rate
final float alpha = 0.8f;
gx = alpha * gx + (1 - alpha) * event.values[0];
gy = alpha * gy + (1 - alpha) * event.values[1];
gz = alpha * gz + (1 - alpha) * event.values[2];
sendAccelerometer(event.values[0] - gx, event.values[1] - gy, event.values[2] - gz);
acc_x = event.values[0];
acc_y = event.values[1];
acc_z = event.values[2];
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
//go full-screen
android.util.Log.i("FTEDroid", "onCreate");
//go full-screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
android.util.Log.i("FTEDroid", "create view");
view = new FTEView(this);
setContentView(view);
// setContentView(R.layout.main);
android.util.Log.i("FTEDroid", "init sensor manager");
sensorman = (SensorManager)getSystemService(SENSOR_SERVICE);
sensoracc = sensorman.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
android.util.Log.i("FTEDroid", "init accelerometer");
if (sensorman != null)
sensoracc = sensorman.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
android.util.Log.i("FTEDroid", "done");
}
@Override
protected void onResume()
{
super.onResume();
sensorman.registerListener((SensorEventListener)view, sensoracc, SensorManager.SENSOR_DELAY_GAME);
if (sensorman != null && sensoracc != null)
sensorman.registerListener((SensorEventListener)view, sensoracc, SensorManager.SENSOR_DELAY_GAME);
view.resume();
}
@ -314,14 +360,16 @@ public class FTEDroidActivity extends Activity
@Override
protected void onStop()
{
sensorman.unregisterListener(view);
if (sensorman != null && sensoracc != null)
sensorman.unregisterListener(view);
super.onStop();
}
@Override
protected void onPause()
{
sensorman.unregisterListener(view);
if (sensorman != null && sensoracc != null)
sensorman.unregisterListener(view);
super.onPause();
}
}

View File

@ -3,10 +3,9 @@ package com.fteqw;
public class FTEDroidEngine
{
public static native void init(int w, int h, String basedir); /* init/reinit */
public static native void frame();
public static native void frame(float ax, float ay, float az);
public static native void keypress(int down, int qkey, int unicode);
public static native void motion(int act, float x, float y);
public static native void accelerometer(float x, float y, float z);
public static native void motion(int act, int pointerid, float x, float y);
public static native int paintaudio(byte[] stream, int len);
static

View File

@ -170,10 +170,10 @@ void GL_GAliasFlushSkinCache(void)
skincolourmapped.numbuckets = 0;
}
static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, entity_t *e)
static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, entity_t *e, texnums_t **forcedtex)
{
galiasskin_t *skins;
texnums_t *texnums;
shader_t *shader;
int frame;
unsigned int subframe;
extern int cl_playerindex; //so I don't have to strcmp
@ -181,14 +181,15 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
unsigned int tc, bc, pc;
qboolean forced;
*forcedtex = NULL;
if (e->skinnum >= 100 && e->skinnum < 110)
{
shader_t *s;
s = R_RegisterSkin(va("gfx/skin%d.lmp", e->skinnum), NULL);
if (!TEXVALID(s->defaulttextures.base))
s->defaulttextures.base = R_LoadHiResTexture(va("gfx/skin%d.lmp", e->skinnum), NULL, 0);
s->defaulttextures.shader = s;
return &s->defaulttextures;
return s;
}
@ -258,28 +259,30 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
if (!inf->numskins)
{
/*model has no skins*/
skins = NULL;
subframe = 0;
texnums = NULL;
shader = NULL;
}
else
{
skins = (galiasskin_t*)((char *)inf + inf->ofsskins);
if (!skins->texnums)
if (e->skinnum >= 0 && e->skinnum < inf->numskins)
skins += e->skinnum;
if (!skins->numshaders)
{
/*model has a skin, but has no framegroups*/
skins = NULL;
subframe = 0;
texnums = NULL;
shader = NULL;
}
else
{
if (e->skinnum >= 0 && e->skinnum < inf->numskins)
skins += e->skinnum;
subframe = cl.time*skins->skinspeed;
subframe = subframe%skins->texnums;
subframe = subframe%skins->numshaders;
texnums = (texnums_t*)((char *)skins + skins->ofstexnums + subframe*sizeof(texnums_t));
shader = *(shader_t**)((char *)skins + skins->ofsshaders + subframe*sizeof(shader_t*));
}
}
@ -287,12 +290,14 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
{
if (cm->tcolour == tc && cm->bcolour == bc && cm->skinnum == e->skinnum && cm->subframe == subframe && cm->pclass == pc)
{
return &cm->texnum;
*forcedtex = &cm->texnum;
return shader;
}
}
//colourmap isn't present yet.
cm = BZ_Malloc(sizeof(*cm));
*forcedtex = &cm->texnum;
Q_strncpyz(cm->name, skinname, sizeof(cm->name));
Hash_Add(&skincolourmapped, cm->name, cm, &cm->bucket);
cm->tcolour = tc;
@ -304,10 +309,11 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
cm->texnum.base = r_nulltex;
cm->texnum.loweroverlay = r_nulltex;
cm->texnum.upperoverlay = r_nulltex;
cm->texnum.shader = texnums?texnums->shader:R_RegisterSkin(skinname, NULL);
if (!texnums)
{ //load just the skin
if (!shader)
{ //model has no shaders, so just the skin directly
shader = R_RegisterSkin(skinname, NULL);
if (e->scoreboard && e->scoreboard->skin)
{
if (cls.protocol == CP_QUAKE2)
@ -318,7 +324,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
inwidth = e->scoreboard->skin->width;
inheight = e->scoreboard->skin->height;
cm->texnum.base = R_LoadTexture32(e->scoreboard->skin->name, inwidth, inheight, (unsigned int*)original, IF_NOALPHA|IF_NOGAMMA);
return &cm->texnum;
return shader;
}
}
else
@ -329,39 +335,38 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
inwidth = e->scoreboard->skin->width;
inheight = e->scoreboard->skin->height;
cm->texnum.base = R_LoadTexture8(e->scoreboard->skin->name, inwidth, inheight, original, IF_NOALPHA|IF_NOGAMMA, 1);
return &cm->texnum;
return shader;
}
}
if (TEXVALID(e->scoreboard->skin->tex_base))
{
texnums = &cm->texnum;
texnums->loweroverlay = e->scoreboard->skin->tex_lower;
texnums->upperoverlay = e->scoreboard->skin->tex_upper;
texnums->base = e->scoreboard->skin->tex_base;
return texnums;
cm->texnum.loweroverlay = e->scoreboard->skin->tex_lower;
cm->texnum.upperoverlay = e->scoreboard->skin->tex_upper;
cm->texnum.base = e->scoreboard->skin->tex_base;
return shader;
}
cm->texnum.base = R_LoadHiResTexture(e->scoreboard->skin->name, "skins", IF_NOALPHA);
return &cm->texnum;
return shader;
}
return NULL;
return shader;
}
cm->texnum.bump = texnums[cm->skinnum].bump; //can't colour bumpmapping
if (cls.protocol != CP_QUAKE2 && ((!texnums || (model==cl.model_precache[cl_playerindex] || model==cl.model_precache_vwep[0])) && e->scoreboard && e->scoreboard->skin))
cm->texnum.bump = shader->defaulttextures.bump; //can't colour bumpmapping
if (cls.protocol != CP_QUAKE2 && ((model==cl.model_precache[cl_playerindex] || model==cl.model_precache_vwep[0]) && e->scoreboard && e->scoreboard->skin))
{
/*q1 only reskins the player model, not gibbed heads (which have the same colourmap)*/
original = Skin_Cache8(e->scoreboard->skin);
inwidth = e->scoreboard->skin->width;
inheight = e->scoreboard->skin->height;
if (!original && TEXVALID(e->scoreboard->skin->tex_base))
{
texnums = &cm->texnum;
texnums->loweroverlay = e->scoreboard->skin->tex_lower;
texnums->upperoverlay = e->scoreboard->skin->tex_upper;
texnums->base = e->scoreboard->skin->tex_base;
return texnums;
cm->texnum.loweroverlay = e->scoreboard->skin->tex_lower;
cm->texnum.upperoverlay = e->scoreboard->skin->tex_upper;
cm->texnum.base = e->scoreboard->skin->tex_base;
return shader;
}
}
else
@ -398,10 +403,8 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
unsigned scaled_width, scaled_height;
qbyte *inrow;
texnums = &cm->texnum;
texnums->base = r_nulltex;
texnums->fullbright = r_nulltex;
cm->texnum.base = r_nulltex;
cm->texnum.fullbright = r_nulltex;
scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
scaled_height = gl_max_size.value < 512 ? gl_max_size.value : 512;
@ -514,12 +517,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
}
if (qrenderer == QR_OPENGL)
{
texnums->base = R_AllocNewTexture(cm->name, scaled_width, scaled_height);
R_Upload(texnums->base, cm->name, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP);
cm->texnum.base = R_AllocNewTexture(cm->name, scaled_width, scaled_height);
R_Upload(cm->texnum.base, cm->name, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP);
}
else
{
texnums->base = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0);
cm->texnum.base = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0);
}
if (!h2playertranslations)
@ -540,30 +543,21 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
}
if (qrenderer == QR_OPENGL)
{
texnums->fullbright = R_AllocNewTexture(cm->name, scaled_width, scaled_height);
R_Upload(texnums->fullbright, cm->name, TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP);
cm->texnum.fullbright = R_AllocNewTexture(cm->name, scaled_width, scaled_height);
R_Upload(cm->texnum.fullbright, cm->name, TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP);
}
else
{
texnums->fullbright = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0);
cm->texnum.fullbright = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0);
}
}
}
else
{
skins = (galiasskin_t*)((char *)inf + inf->ofsskins);
if (e->skinnum >= 0 && e->skinnum < inf->numskins)
skins += e->skinnum;
if (!inf->numskins || !skins->texnums)
return NULL;
frame = cl.time*skins->skinspeed;
frame = frame%skins->texnums;
texnums = (texnums_t*)((char *)skins + skins->ofstexnums + frame*sizeof(texnums_t));
memcpy(&cm->texnum, texnums, sizeof(cm->texnum));
/*model has no original skin info and thus cannot be reskinned, copy over the default textures so that the skincache doesn't break things when it gets reused*/
cm->texnum = shader->defaulttextures;
}
return &cm->texnum;
return shader;
}
}
@ -580,14 +574,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
return NULL;
}
if (!skins->texnums)
if (!skins->numshaders)
return NULL;
frame = cl.time*skins->skinspeed;
frame = frame%skins->texnums;
texnums = (texnums_t*)((char *)skins + skins->ofstexnums + frame*sizeof(texnums_t));
return texnums;
frame = frame%skins->numshaders;
return *(shader_t**)((char *)skins + skins->ofsshaders + frame*sizeof(shader_t*));
}
#if defined(RTLIGHTS)
@ -958,7 +950,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
{
galiasinfo_t *inf;
model_t *clmodel;
shader_t *shader;
shader_t *shader, *regshader;
batch_t *b;
int surfnum;
shadersort_t sort;
@ -1006,10 +998,11 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
for(surfnum=0; inf; ((inf->nextsurf)?(inf = (galiasinfo_t*)((char *)inf + inf->nextsurf)):(inf=NULL)), surfnum++)
{
skin = GL_ChooseSkin(inf, clmodel, surfnum, e);
if (!skin)
regshader = GL_ChooseSkin(inf, clmodel, surfnum, e, &skin);
if (!regshader)
continue;
shader = e->forcedshader?e->forcedshader:skin->shader;
skin = skin?skin:&regshader->defaulttextures;
shader = e->forcedshader?e->forcedshader:regshader;
if (shader)
{
b = BE_GetTempBatch();

View File

@ -727,7 +727,10 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea
t = shaderstate.curdeluxmap;
break;
case T_GEN_DIFFUSE:
t = (shaderstate.curtexnums && TEXVALID(shaderstate.curtexnums->base))?shaderstate.curtexnums->base:missing_texture;
if (shaderstate.curtexnums && TEXVALID(shaderstate.curtexnums->base))
t = shaderstate.curtexnums->base;
else
t = missing_texture;
break;
case T_GEN_NORMALMAP:
t = shaderstate.curtexnums?shaderstate.curtexnums->bump:r_nulltex; /*FIXME: nulltex is not correct*/
@ -3138,7 +3141,9 @@ void GLBE_SubmitBatch(batch_t *batch)
if (lm < 0)
{
shaderstate.curlightmap = r_nulltex;
extern texid_t r_whiteimage;
/*FIXME: this doesn't compensate for overbrighting*/
shaderstate.curlightmap = r_whiteimage;
shaderstate.curdeluxmap = r_nulltex;
}
else

View File

@ -1150,6 +1150,7 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
}
}
}
switch((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT)
{
case 0:

View File

@ -817,7 +817,8 @@ static texid_t Font_LoadFallbackConchars(void)
int width, height;
unsigned int i;
qbyte *lump;
lump = ReadTargaFile(default_conchar, sizeof(default_conchar), &width, &height, false);
qboolean hasalpha;
lump = ReadTargaFile(default_conchar, sizeof(default_conchar), &width, &height, &hasalpha, false);
if (!lump)
Sys_Error("Corrupt internal drawchars");
/*convert greyscale to alpha*/

View File

@ -3503,6 +3503,7 @@ void * RMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
Q_strncatz(name, va("_%i.tga", framenum), sizeof(name));
pspriteframe->shader = R_RegisterShader(name,
"{\n"
"program defaultsprite\n"
"{\n"
"map $diffuse\n"
"alphafunc ge128\n"

View File

@ -229,8 +229,6 @@ typedef struct texnums_s {
texid_t loweroverlay;
texid_t specular;
texid_t fullbright;
struct shader_s *shader; //fixme: remove...
} texnums_t;
typedef struct vboarray_s

View File

@ -63,6 +63,7 @@ vec3_t r_origin;
//
refdef_t r_refdef;
unsigned int r_viewcontents;
mleaf_t *r_viewleaf, *r_oldviewleaf;
mleaf_t *r_viewleaf2, *r_oldviewleaf2;
int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
@ -375,7 +376,7 @@ void R_SetupGL (void)
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
if (r_waterwarp.value<0 && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER)
if (r_waterwarp.value<0 && r_viewleaf && (r_viewcontents & FTECONTENTS_FLUID))
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
@ -762,7 +763,7 @@ void R_Clear (void)
#if 0
void GLR_SetupFog (void)
{
if (r_viewleaf)// && r_viewleaf->contents != CONTENTS_EMPTY)
if (r_viewleaf)// && r_viewcontents != FTECONTENTS_EMPTY)
{
// static fogcolour;
float fogcol[4]={0};
@ -771,7 +772,7 @@ void GLR_SetupFog (void)
fogperc=0;
fogdist=512;
switch(r_viewleaf->contents)
switch(r_viewcontents)
{
case FTECONTENTS_WATER:
fogcol[0] = 64/255.0;
@ -1150,7 +1151,7 @@ void GLR_RenderView (void)
// SCENE POST PROCESSING
// we check if we need to use any shaders - currently it's just waterwarp
if ((r_waterwarp.value>0 && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER))
if ((r_waterwarp.value>0 && r_viewleaf && (r_viewcontents & FTECONTENTS_WATER)))
{
if (scenepp_waterwarp)
{

View File

@ -37,7 +37,7 @@ extern LPDIRECT3DDEVICE9 pD3DDev9;
#endif
extern texid_t missing_texture;
static texid_t r_whiteimage;
texid_t r_whiteimage;
static qboolean shader_reload_needed;
static qboolean shader_rescan_needed;
@ -1074,10 +1074,12 @@ struct sbuiltin_s
"uniform sampler2D s_t0;\n"
"in vec2 tc;\n"
"varying vec4 vc;\n"
"uniform vec4 e_colourident;\n"
"void main ()\n"
"{\n"
" gl_FragColor = fog4blend(texture2D(s_t0, tc) * vc);\n"
" gl_FragColor = gl_FragColor * e_colourident;\n"
"}\n"
"#endif\n"
},
@ -1102,10 +1104,12 @@ struct sbuiltin_s
"uniform sampler2D s_t0;\n"
"in vec2 tc;\n"
"varying vec4 vc;\n"
"uniform vec4 e_colourident;\n"
"void main ()\n"
"{\n"
" gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc);\n"
" gl_FragColor = gl_FragColor * e_colourident;\n"
"}\n"
"#endif\n"
},
@ -1186,6 +1190,7 @@ struct sbuiltin_s
"#endif\n"
"varying vec2 tc, lm;\n"
"uniform vec4 e_lmscale;\n"
"uniform vec4 e_colourident;\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
@ -1204,6 +1209,7 @@ struct sbuiltin_s
"#ifdef FOG\n"
"gl_FragColor = fog4(gl_FragColor);\n"
"#endif\n"
"gl_FragColor = gl_FragColor * e_colourident;\n"
"}\n"
"#endif\n"
},
@ -4696,6 +4702,8 @@ void Shader_UpdateRegistration (void)
void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader)
{
if (!tn)
tn = &shader->defaulttextures;
if (!TEXVALID(shader->defaulttextures.base))
{
/*dlights/realtime lighting needs some stuff*/

View File

@ -237,7 +237,7 @@ static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf)
sh_shmesh->litleaves[i>>3] |= 1<<(i&7);
}
static void SH_FreeShadowMesh(shadowmesh_t *sm)
void SH_FreeShadowMesh(shadowmesh_t *sm)
{
unsigned int i;
for (i = 0; i < sm->numsurftextures; i++)

View File

@ -768,8 +768,8 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float fro
}
if (mesh->numindexes+6 > tex->maxindicies)
{
tex->maxindicies = mesh->numvertexes+6;
mesh->indexes = BZ_Realloc(mesh->colors4b_array, sizeof(*mesh->indexes) * tex->maxindicies);
tex->maxindicies = mesh->numindexes+6;
mesh->indexes = BZ_Realloc(mesh->indexes, sizeof(*mesh->indexes) * tex->maxindicies);
}
col = colour4b * 0x01010101;
@ -783,17 +783,17 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float fro
VectorSet(mesh->xyz_array[mesh->numvertexes+2], x2, y2, backfloor);
VectorSet(mesh->xyz_array[mesh->numvertexes+3], x2, y2, frontfloor);
Vector2Set(mesh->st_array[mesh->numvertexes+0], s1, t2);
Vector2Set(mesh->st_array[mesh->numvertexes+0], s1, t1);
Vector2Set(mesh->st_array[mesh->numvertexes+0], s2, t1);
Vector2Set(mesh->st_array[mesh->numvertexes+0], s2, t2);
Vector2Set(mesh->st_array[mesh->numvertexes+1], s1, t1);
Vector2Set(mesh->st_array[mesh->numvertexes+2], s2, t1);
Vector2Set(mesh->st_array[mesh->numvertexes+2], s2, t2);
mesh->indexes[mesh->numindexes+0] = mesh->numvertexes;
mesh->indexes[mesh->numindexes+1] = mesh->numvertexes;
mesh->indexes[mesh->numindexes+2] = mesh->numvertexes;
mesh->indexes[mesh->numindexes+0] = mesh->numvertexes+0;
mesh->indexes[mesh->numindexes+1] = mesh->numvertexes+1;
mesh->indexes[mesh->numindexes+2] = mesh->numvertexes+2;
mesh->indexes[mesh->numindexes+0] = mesh->numvertexes;
mesh->indexes[mesh->numindexes+2] = mesh->numvertexes;
mesh->indexes[mesh->numindexes+3] = mesh->numvertexes;
mesh->indexes[mesh->numindexes+3] = mesh->numvertexes+0;
mesh->indexes[mesh->numindexes+4] = mesh->numvertexes+2;
mesh->indexes[mesh->numindexes+5] = mesh->numvertexes+3;
mesh->numvertexes += 4;
mesh->numindexes += 6;
@ -1024,11 +1024,30 @@ static void GLR_RecursiveDoomNode(unsigned int node)
void GLR_DoomWorld(void)
{
int texnum;
gldoomtexture_t *t;
if (!nodel || !nodec)
return; //err... buggy
for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan.
{
t = &gldoomtextures[texnum];
t->mesh.numindexes = 0;
t->mesh.numvertexes = 0;
}
r_visframecount++;
GLR_RecursiveDoomNode(nodec-1);
memset(cl.worldmodel->batches, 0, sizeof(cl.worldmodel->batches));
for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan.
{
t = &gldoomtextures[texnum];
if (t->mesh.numindexes)
{
t->batch.next = cl.worldmodel->batches[t->shader->sort];
cl.worldmodel->batches[t->shader->sort] = &t->batch;
}
}
}
@ -1517,6 +1536,7 @@ static int Doom_LoadPatch(char *name)
// texnum = numgldoomtextures;
gldoomtextures = BZ_Realloc(gldoomtextures, sizeof(*gldoomtextures)*((numgldoomtextures+16)&~15));
memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures]));
numgldoomtextures++;
strncpy(gldoomtextures[texnum].name, name, 8);
@ -2037,6 +2057,8 @@ qboolean Mod_LoadDoomLevel(model_t *mod)
mod->needload = false;
mod->fromgame = fg_doom;
mod->type = mod_brush;
mod->nodes = (void*)0x1;
CleanWalls(sidedefsl);

View File

@ -257,6 +257,7 @@ extern vec3_t r_origin;
// screen size info
//
extern refdef_t r_refdef;
extern unsigned int r_viewcontents;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; //q2

View File

@ -515,6 +515,7 @@ void D3DBE_BaseEntTextures(void);
void Sh_PreGenerateLights(void);
//Draws lights, called from the backend
void Sh_DrawLights(qbyte *vis, batch_t **mbatches);
void SH_FreeShadowMesh(struct shadowmesh_s *sm);
void Sh_Shutdown(void);
//Draws the depth of ents in the world near the current light
void BE_BaseEntShadowDepth(void);

View File

@ -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},

View File

@ -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)

View File

@ -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
{

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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");

View File

@ -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
{

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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.