9ee7301d32
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
381 lines
8.9 KiB
C
381 lines
8.9 KiB
C
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
#include "quakedef.h"
|
|
|
|
static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, trace_t *trace, vec3_t origin, vec3_t angles);
|
|
int Q1BSP_HullPointContents(hull_t *hull, vec3_t p);
|
|
static hull_t box_hull;
|
|
static mclipnode_t box_clipnodes[6];
|
|
static mplane_t box_planes[6];
|
|
|
|
extern vec3_t player_mins;
|
|
extern vec3_t player_maxs;
|
|
|
|
/*
|
|
===================
|
|
PM_InitBoxHull
|
|
|
|
Set up the planes and clipnodes so that the six floats of a bounding box
|
|
can just be stored out and get a proper hull_t structure.
|
|
===================
|
|
*/
|
|
void PM_InitBoxHull (void)
|
|
{
|
|
int i;
|
|
int side;
|
|
|
|
box_hull.clipnodes = box_clipnodes;
|
|
box_hull.planes = box_planes;
|
|
box_hull.firstclipnode = 0;
|
|
box_hull.lastclipnode = 5;
|
|
|
|
for (i=0 ; i<6 ; i++)
|
|
{
|
|
box_clipnodes[i].planenum = i;
|
|
|
|
side = i&1;
|
|
|
|
box_clipnodes[i].children[side] = Q1CONTENTS_EMPTY;
|
|
if (i != 5)
|
|
box_clipnodes[i].children[side^1] = i + 1;
|
|
else
|
|
box_clipnodes[i].children[side^1] = Q1CONTENTS_SOLID;
|
|
|
|
box_planes[i].type = i>>1;
|
|
box_planes[i].normal[i>>1] = 1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
===================
|
|
PM_HullForBox
|
|
|
|
To keep everything totally uniform, bounding boxes are turned into small
|
|
BSP trees instead of being compared directly.
|
|
===================
|
|
*/
|
|
hull_t *PM_HullForBox (vec3_t mins, vec3_t maxs)
|
|
{
|
|
box_planes[0].dist = maxs[0];
|
|
box_planes[1].dist = mins[0];
|
|
box_planes[2].dist = maxs[1];
|
|
box_planes[3].dist = mins[1];
|
|
box_planes[4].dist = maxs[2];
|
|
box_planes[5].dist = mins[2];
|
|
|
|
return &box_hull;
|
|
}
|
|
|
|
|
|
int PM_TransformedModelPointContents (model_t *mod, vec3_t p, vec3_t origin, vec3_t angles)
|
|
{
|
|
vec3_t p_l, axis[3];
|
|
VectorSubtract (p, origin, p_l);
|
|
|
|
// rotate start and end into the models frame of reference
|
|
if (angles[0] || angles[1] || angles[2])
|
|
{
|
|
AngleVectors (angles, axis[0], axis[1], axis[2]);
|
|
VectorNegate(axis[1], axis[1]);
|
|
return mod->funcs.PointContents(mod, axis, p_l);
|
|
}
|
|
|
|
return mod->funcs.PointContents(mod, NULL, p_l);
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
PM_PointContents
|
|
|
|
==================
|
|
*/
|
|
int PM_PointContents (vec3_t p)
|
|
{
|
|
int num;
|
|
|
|
int pc;
|
|
physent_t *pe;
|
|
model_t *pm;
|
|
|
|
pm = pmove.physents[0].model;
|
|
if (!pm)
|
|
return FTECONTENTS_EMPTY;
|
|
pc = pm->funcs.PointContents(pm, NULL, p);
|
|
//we need this for e2m2 - waterjumping on to plats wouldn't work otherwise.
|
|
for (num = 1; num < pmove.numphysent; num++)
|
|
{
|
|
pe = &pmove.physents[num];
|
|
|
|
if (pe->info == pmove.skipent)
|
|
continue;
|
|
|
|
pm = pe->model;
|
|
if (pm)
|
|
{
|
|
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 (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->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;
|
|
}
|
|
}
|
|
|
|
return pc;
|
|
}
|
|
|
|
int PM_ExtraBoxContents (vec3_t p)
|
|
{
|
|
int num;
|
|
|
|
int pc = 0;
|
|
physent_t *pe;
|
|
model_t *pm;
|
|
trace_t tr;
|
|
|
|
for (num = 1; num < pmove.numphysent; num++)
|
|
{
|
|
pe = &pmove.physents[num];
|
|
if (!pe->nonsolid)
|
|
continue;
|
|
pm = pe->model;
|
|
if (pm)
|
|
{
|
|
if (pe->forcecontentsmask)
|
|
{
|
|
if (!PM_TransformedHullCheck(pm, p, p, &tr, pe->origin, pe->angles))
|
|
continue;
|
|
if (tr.startsolid)
|
|
pc |= pe->forcecontentsmask;
|
|
}
|
|
}
|
|
else if (pe->forcecontentsmask)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
return pc;
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
LINE TESTING IN HULLS
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
/*returns if it actually did a trace*/
|
|
static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, trace_t *trace, vec3_t origin, vec3_t angles)
|
|
{
|
|
vec3_t start_l, end_l;
|
|
int i;
|
|
vec3_t axis[3];
|
|
|
|
// subtract origin offset
|
|
VectorSubtract (start, origin, start_l);
|
|
VectorSubtract (end, origin, end_l);
|
|
|
|
// sweep the box through the model
|
|
if (model)
|
|
{
|
|
if (angles[0] || angles[1] || angles[2])
|
|
{
|
|
AngleVectors (angles, axis[0], axis[1], axis[2]);
|
|
VectorNegate(axis[1], axis[1]);
|
|
model->funcs.NativeTrace(model, 0, 0, axis, start_l, end_l, player_mins, player_maxs, MASK_PLAYERSOLID, trace);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
if (start_l[i]+player_mins[i] > model->maxs[i] && end_l[i] + player_mins[i] > model->maxs[i])
|
|
return false;
|
|
if (start_l[i]+player_maxs[i] < model->mins[i] && end_l[i] + player_maxs[i] < model->mins[i])
|
|
return false;
|
|
}
|
|
model->funcs.NativeTrace(model, 0, 0, NULL, start_l, end_l, player_mins, player_maxs, MASK_PLAYERSOLID, trace);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
if (start_l[i]+player_mins[i] > box_planes[0+i*2].dist && end_l[i] + player_mins[i] > box_planes[0+i*2].dist)
|
|
return false;
|
|
if (start_l[i]+player_maxs[i] < box_planes[1+i*2].dist && end_l[i] + player_maxs[i] < box_planes[1+i*2].dist)
|
|
return false;
|
|
}
|
|
|
|
Q1BSP_RecursiveHullCheck (&box_hull, box_hull.firstclipnode, 0, 1, start_l, end_l, trace);
|
|
}
|
|
|
|
trace->endpos[0] += origin[0];
|
|
trace->endpos[1] += origin[1];
|
|
trace->endpos[2] += origin[2];
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
================
|
|
PM_TestPlayerPosition
|
|
|
|
Returns false if the given player position is not valid (in solid)
|
|
================
|
|
*/
|
|
qboolean PM_TestPlayerPosition (vec3_t pos)
|
|
{
|
|
int i;
|
|
physent_t *pe;
|
|
vec3_t mins, maxs;
|
|
hull_t *hull;
|
|
trace_t trace;
|
|
|
|
for (i=0 ; i< pmove.numphysent ; i++)
|
|
{
|
|
pe = &pmove.physents[i];
|
|
|
|
if (pe->info == pmove.skipent)
|
|
continue;
|
|
|
|
if (pe->nonsolid)
|
|
continue;
|
|
|
|
// get the clipping hull
|
|
if (pe->model)
|
|
{
|
|
if (!PM_TransformedHullCheck (pe->model, pos, pos, &trace, pe->origin, pe->angles))
|
|
continue;
|
|
if (trace.allsolid)
|
|
return false; //solid
|
|
}
|
|
else
|
|
{
|
|
VectorSubtract (pe->mins, player_maxs, mins);
|
|
VectorSubtract (pe->maxs, player_mins, maxs);
|
|
hull = PM_HullForBox (mins, maxs);
|
|
VectorSubtract(pos, pe->origin, mins);
|
|
|
|
if (Q1BSP_HullPointContents(hull, mins) & FTECONTENTS_SOLID)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
================
|
|
PM_PlayerTrace
|
|
================
|
|
*/
|
|
trace_t PM_PlayerTrace (vec3_t start, vec3_t end)
|
|
{
|
|
trace_t trace, total;
|
|
int i;
|
|
physent_t *pe;
|
|
|
|
// fill in a default trace
|
|
memset (&total, 0, sizeof(trace_t));
|
|
total.fraction = 1;
|
|
total.entnum = -1;
|
|
VectorCopy (end, total.endpos);
|
|
|
|
for (i=0 ; i< pmove.numphysent ; i++)
|
|
{
|
|
pe = &pmove.physents[i];
|
|
|
|
if (pe->nonsolid)
|
|
continue;
|
|
if (pe->info == pmove.skipent)
|
|
continue;
|
|
|
|
if (!pe->model || pe->model->needload)
|
|
{
|
|
vec3_t mins, maxs;
|
|
|
|
VectorSubtract (pe->mins, player_maxs, mins);
|
|
VectorSubtract (pe->maxs, player_mins, maxs);
|
|
PM_HullForBox (mins, maxs);
|
|
|
|
// trace a line through the apropriate clipping hull
|
|
if (!PM_TransformedHullCheck (NULL, start, end, &trace, pe->origin, pe->angles))
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// trace a line through the apropriate clipping hull
|
|
if (!PM_TransformedHullCheck (pe->model, start, end, &trace, pe->origin, pe->angles))
|
|
continue;
|
|
}
|
|
|
|
if (trace.allsolid)
|
|
trace.startsolid = true;
|
|
if (trace.startsolid)
|
|
{
|
|
// if (!pmove.physents[i].model) //caught inside annother model
|
|
// continue; //don't count this.
|
|
trace.fraction = 0;
|
|
}
|
|
|
|
// did we clip the move?
|
|
if (trace.fraction < total.fraction)
|
|
{
|
|
// fix trace up by the offset
|
|
total = trace;
|
|
total.entnum = i;
|
|
}
|
|
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
//for use outside the pmove code. lame, but works.
|
|
trace_t PM_TraceLine (vec3_t start, vec3_t end)
|
|
{
|
|
VectorClear(player_mins);
|
|
VectorClear(player_maxs);
|
|
return PM_PlayerTrace(start, end);
|
|
}
|