mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-13 14:12:02 +00:00
- add MAX_NET_EDICTS and MAX_NET_EDICTS_MASK defines, which are 512 and 511 respectively - change baselines to access the array directly, rather than through the entity's "data" field - cleanup SV_ReliableSVC_Emit - add entity remapping. the entity number used internally in the server no longer matches the number sent to the client, and it releases the mapping after 10 seconds of inuse, so there's no "512 entity limit" anymore. Still the MAX_EDICTS limit though, which is currently 768, but it can probably be defined to something much higher without any trouble.
245 lines
5.7 KiB
C
245 lines
5.7 KiB
C
/*
|
|
sv_nchan.c
|
|
|
|
user reliable data stream writes
|
|
|
|
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:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
*/
|
|
static const char rcsid[] =
|
|
"$Id$";
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
#ifdef HAVE_STRINGS_H
|
|
# include <strings.h>
|
|
#endif
|
|
|
|
#include "QF/msg.h"
|
|
#include "QF/net_svc.h"
|
|
#include "QF/sys.h"
|
|
|
|
#include "server.h"
|
|
|
|
|
|
void
|
|
PushBackbuf (client_t *cl)
|
|
{
|
|
memset (&cl->backbuf, 0, sizeof (cl->backbuf));
|
|
cl->backbuf.maxsize = sizeof (cl->backbuf_data[cl->num_backbuf]);
|
|
cl->backbuf.data = cl->backbuf_data[cl->num_backbuf];
|
|
cl->backbuf.allowoverflow = true;
|
|
SZ_Clear (&cl->backbuf);
|
|
cl->backbuf_size[cl->num_backbuf] = 0;
|
|
cl->num_backbuf++;
|
|
}
|
|
|
|
// Writes the given block into either cl->netchan.message, or the
|
|
// backbuffer if there's no room
|
|
void
|
|
SV_ReliableSVC_Emit (client_t *cl, int type, void *block)
|
|
{
|
|
net_status_t retval;
|
|
int oldsize;
|
|
sizebuf_t *buf;
|
|
|
|
buf = cl->num_backbuf ? &cl->backbuf : &cl->netchan.message;
|
|
|
|
oldsize = buf->cursize;
|
|
if ((retval = NET_SVC_Emit (type, block, buf)))
|
|
buf->cursize = oldsize;
|
|
|
|
if (retval == NET_SHORT && cl->num_backbuf < MAX_BACK_BUFFERS) {
|
|
PushBackbuf (cl);
|
|
retval = NET_SVC_Emit (type, block, &cl->backbuf);
|
|
}
|
|
|
|
switch (retval) {
|
|
case NET_SHORT:
|
|
SV_Printf ("SV_ReliableSVC_Emit: WARNING: reliable "
|
|
"overflow for %s with %d (%s) block\n",
|
|
cl->name, type, NET_SVC_GetString (type));
|
|
cl->netchan.message.overflowed = true; // this will drop
|
|
// the client
|
|
break;
|
|
case NET_ERROR:
|
|
Sys_Error ("SV_ReliableSVC_Emit: error emitting %d (%s) "
|
|
"block for %s\n", type,
|
|
NET_SVC_GetString (type), cl->name);
|
|
break;
|
|
case NET_OK:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// check to see if client block will fit, if not, rotate buffers
|
|
void
|
|
ClientReliableCheckBlock (client_t *cl, int maxsize)
|
|
{
|
|
if (cl->num_backbuf ||
|
|
cl->netchan.message.cursize > cl->netchan.message.maxsize - maxsize -
|
|
1) {
|
|
// we would probably overflow the buffer, save it for next
|
|
if (!cl->num_backbuf) {
|
|
PushBackbuf (cl);
|
|
}
|
|
|
|
if (cl->backbuf.cursize > cl->backbuf.maxsize - maxsize - 1) {
|
|
if (cl->num_backbuf == MAX_BACK_BUFFERS) {
|
|
SV_Printf ("WARNING: MAX_BACK_BUFFERS for %s\n", cl->name);
|
|
cl->backbuf.cursize = 0; // don't overflow without
|
|
// allowoverflow set
|
|
cl->netchan.message.overflowed = true; // this will drop the
|
|
// client
|
|
return;
|
|
}
|
|
PushBackbuf (cl);
|
|
}
|
|
}
|
|
}
|
|
|
|
// begin a client block, estimated maximum size
|
|
void
|
|
ClientReliableWrite_Begin (client_t *cl, int c, int maxsize)
|
|
{
|
|
ClientReliableCheckBlock (cl, maxsize);
|
|
ClientReliableWrite_Byte (cl, c);
|
|
}
|
|
|
|
void
|
|
ClientReliable_FinishWrite (client_t *cl)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
cl->backbuf_size[cl->num_backbuf - 1] = cl->backbuf.cursize;
|
|
|
|
if (cl->backbuf.overflowed) {
|
|
SV_Printf ("WARNING: backbuf [%d] reliable overflow for %s\n",
|
|
cl->num_backbuf, cl->name);
|
|
cl->netchan.message.overflowed = true; // this will drop the
|
|
// client
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Angle (client_t *cl, float f)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteAngle (&cl->backbuf, f);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteAngle (&cl->netchan.message, f);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Angle16 (client_t *cl, float f)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteAngle16 (&cl->backbuf, f);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteAngle16 (&cl->netchan.message, f);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Byte (client_t *cl, int c)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteByte (&cl->backbuf, c);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteByte (&cl->netchan.message, c);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Char (client_t *cl, int c)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteChar (&cl->backbuf, c);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteChar (&cl->netchan.message, c);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Float (client_t *cl, float f)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteFloat (&cl->backbuf, f);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteFloat (&cl->netchan.message, f);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Coord (client_t *cl, float f)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteCoord (&cl->backbuf, f);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteCoord (&cl->netchan.message, f);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Long (client_t *cl, int c)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteLong (&cl->backbuf, c);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteLong (&cl->netchan.message, c);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_Short (client_t *cl, int c)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteShort (&cl->backbuf, c);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteShort (&cl->netchan.message, c);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_String (client_t *cl, const char *s)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
MSG_WriteString (&cl->backbuf, s);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
MSG_WriteString (&cl->netchan.message, s);
|
|
}
|
|
|
|
void
|
|
ClientReliableWrite_SZ (client_t *cl, void *data, int len)
|
|
{
|
|
if (cl->num_backbuf) {
|
|
SZ_Write (&cl->backbuf, data, len);
|
|
ClientReliable_FinishWrite (cl);
|
|
} else
|
|
SZ_Write (&cl->netchan.message, data, len);
|
|
}
|