mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-02 05:42:35 +00:00
2994824bc6
errors can be handled - add a MSG_ReadBlock and MSG_WriteBlock, which write arbitrary - add a MSG_PeekByte, although I never actually used it.. - canonicalize the svc's, so that if qw and nq have a svc with the same name but different contents, they get different names - add all the nq stuff to svc_t, so it has both nq and qw. fun enum that :) - fix all the sizebuf_t usages so they init all the fields properly - move qw's net_svc.c, net_clc.c, net_packetlog.c, and msg_ucmd.c (renamed to net_ucmd.c) into libs/net - move headers for the above in include/QF - convert remaining clc bits to NET_CLC (I think I got them all) - I split net_svc into net_svc_common and net_svc_qw too, in preperation for adding nq - moved movevars_t into "QF/net_svc_qw.h", from pmove.h - made the CL_Parse* functions in qw get the net_svc_*_t as a param, instead of parsing themselves - use a jumptable for CL_Parse* - probably other machinates I've forgotten - and of course, probably added numerous bugs :)
542 lines
13 KiB
C
542 lines
13 KiB
C
/*
|
|
net_svc_common.c
|
|
|
|
(description)
|
|
|
|
Copyright (C) 2001 Adam Olsen
|
|
|
|
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
|
|
#ifndef _WIN32
|
|
# ifdef HAVE_UNISTD_H
|
|
# include <unistd.h>
|
|
# endif
|
|
#else
|
|
# include <windows.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.h"
|
|
#include "QF/net_svc.h"
|
|
#include "QF/net_ucmd.h"
|
|
#include "QF/sound.h"
|
|
#include "QF/sys.h"
|
|
|
|
// N is netquake-only, Q is quakeworld-only, M is identical in both,
|
|
// D is exists in both, but is different, X is used in neither
|
|
static const char *net_svc_strings[] = {
|
|
"svc_bad",
|
|
"svc_nop", // M
|
|
"svc_disconnect", // M
|
|
"svc_qwupdatestat", // D
|
|
"svc_version", // N [long] server version
|
|
"svc_setview", // N [short] entity number
|
|
"svc_qwsound", // D <see code>
|
|
"svc_time", // N [float] server time
|
|
"svc_qwprint", // D [string] null terminated string
|
|
"svc_stufftext", // M [string] stuffed into client's
|
|
// console buffer the string
|
|
// should be \n terminated
|
|
"svc_setangle", // M [vec3] set the view angle to this
|
|
// absolute value
|
|
"svc_serverdata", // D [long] version ...
|
|
"svc_lightstyle", // M [byte] [string]
|
|
"svc_updatename", // N [byte] [string]
|
|
"svc_updatefrags", // M [byte] [short]
|
|
"svc_clientdata", // N <shortbits + data>
|
|
"svc_stopsound", // M <see code>
|
|
"svc_updatecolors", // N [byte] [byte]
|
|
"svc_particle", // N [vec3] <variable>
|
|
"svc_damage", // M [byte] impact [byte] blood [vec3]
|
|
// from
|
|
"svc_spawnstatic", // M
|
|
"svc_spawnbinary", // X
|
|
"svc_spawnbaseline", // M
|
|
"svc_qwtempentity", // D <variable>
|
|
"svc_setpause", // M
|
|
"svc_signonnum", // N
|
|
"svc_centerprint", // M
|
|
"svc_killedmonster", // M
|
|
"svc_foundsecret", // M
|
|
"svc_spawnstaticsound", // M
|
|
"svc_qwintermission", // D
|
|
"svc_finale", // M [string] music [string] text
|
|
"svc_qwcdtrack", // D [byte] track [byte] looptrack
|
|
"svc_sellscreen", // M
|
|
"svc_smallkick", // D Quake svc_cutscene
|
|
"svc_bigkick", // Q
|
|
"svc_updateping", // Q
|
|
"svc_updateentertime", // Q
|
|
"svc_updatestatlong", // Q
|
|
"svc_muzzleflash", // Q
|
|
"svc_updateuserinfo", // Q
|
|
"svc_download", // Q
|
|
"svc_playerinfo", // Q
|
|
"svc_nails", // Q
|
|
"svc_chokecount", // Q
|
|
"svc_modellist", // Q
|
|
"svc_soundlist", // Q
|
|
"svc_packetentities", // Q
|
|
"svc_deltapacketentities", // Q
|
|
"svc_maxspeed", // Q
|
|
"svc_entgravity", // Q
|
|
"svc_setinfo", // Q
|
|
"svc_qwserverinfo", // Q
|
|
"svc_updatepl", // Q
|
|
};
|
|
|
|
const char *
|
|
NET_SVC_GetString (svc_t type)
|
|
{
|
|
if (type >= 0 && type < (sizeof (net_svc_strings) / sizeof (const char *)))
|
|
return net_svc_strings[type];
|
|
else
|
|
return "Invalid SVC";
|
|
}
|
|
|
|
|
|
// This is evil }:>
|
|
net_svc_emit_t net_svc_common_emit_jumptable[] = {
|
|
[svc_nop] = (net_svc_emit_t) NET_SVC_NOP_Emit,
|
|
[svc_disconnect] = (net_svc_emit_t) NET_SVC_Disconnect_Emit,
|
|
[svc_centerprint] = (net_svc_emit_t) NET_SVC_Centerprint_Emit,
|
|
[svc_stufftext] = (net_svc_emit_t) NET_SVC_Stufftext_Emit,
|
|
[svc_damage] = (net_svc_emit_t) NET_SVC_Damage_Emit,
|
|
[svc_setangle] = (net_svc_emit_t) NET_SVC_SetAngle_Emit,
|
|
[svc_lightstyle] = (net_svc_emit_t) NET_SVC_LightStyle_Emit,
|
|
[svc_stopsound] = (net_svc_emit_t) NET_SVC_StopSound_Emit,
|
|
[svc_updatefrags] = (net_svc_emit_t) NET_SVC_UpdateFrags_Emit,
|
|
[svc_spawnbaseline] = (net_svc_emit_t) NET_SVC_SpawnBaseline_Emit,
|
|
[svc_spawnstatic] = (net_svc_emit_t) NET_SVC_SpawnStatic_Emit,
|
|
[svc_killedmonster] = (net_svc_emit_t) NET_SVC_KilledMonster_Emit,
|
|
[svc_foundsecret] = (net_svc_emit_t) NET_SVC_FoundSecret_Emit,
|
|
[svc_spawnstaticsound] = (net_svc_emit_t) NET_SVC_SpawnStaticSound_Emit,
|
|
[svc_finale] = (net_svc_emit_t) NET_SVC_Finale_Emit,
|
|
[svc_sellscreen] = (net_svc_emit_t) NET_SVC_SellScreen_Emit,
|
|
[svc_setpause] = (net_svc_emit_t) NET_SVC_SetPause_Emit,
|
|
};
|
|
int net_svc_common_emit_count =
|
|
sizeof (net_svc_common_emit_jumptable) / sizeof (net_svc_emit_t);
|
|
|
|
net_svc_parse_t net_svc_common_parse_jumptable[] = {
|
|
[svc_nop] = (net_svc_parse_t) NET_SVC_NOP_Parse,
|
|
[svc_disconnect] = (net_svc_parse_t) NET_SVC_Disconnect_Parse,
|
|
[svc_centerprint] = (net_svc_parse_t) NET_SVC_Centerprint_Parse,
|
|
[svc_stufftext] = (net_svc_parse_t) NET_SVC_Stufftext_Parse,
|
|
[svc_damage] = (net_svc_parse_t) NET_SVC_Damage_Parse,
|
|
[svc_setangle] = (net_svc_parse_t) NET_SVC_SetAngle_Parse,
|
|
[svc_lightstyle] = (net_svc_parse_t) NET_SVC_LightStyle_Parse,
|
|
[svc_stopsound] = (net_svc_parse_t) NET_SVC_StopSound_Parse,
|
|
[svc_updatefrags] = (net_svc_parse_t) NET_SVC_UpdateFrags_Parse,
|
|
[svc_spawnbaseline] = (net_svc_parse_t) NET_SVC_SpawnBaseline_Parse,
|
|
[svc_spawnstatic] = (net_svc_parse_t) NET_SVC_SpawnStatic_Parse,
|
|
[svc_killedmonster] = (net_svc_parse_t) NET_SVC_KilledMonster_Parse,
|
|
[svc_foundsecret] = (net_svc_parse_t) NET_SVC_FoundSecret_Parse,
|
|
[svc_spawnstaticsound] = (net_svc_parse_t) NET_SVC_SpawnStaticSound_Parse,
|
|
[svc_finale] = (net_svc_parse_t) NET_SVC_Finale_Parse,
|
|
[svc_sellscreen] = (net_svc_parse_t) NET_SVC_SellScreen_Parse,
|
|
[svc_setpause] = (net_svc_parse_t) NET_SVC_SetPause_Parse,
|
|
};
|
|
int net_svc_common_parse_count =
|
|
sizeof (net_svc_common_parse_jumptable) / sizeof (net_svc_parse_t);
|
|
|
|
|
|
net_svc_emit_t *net_svc_emit_jumptable;
|
|
int net_svc_emit_count;
|
|
|
|
net_svc_emit_t *net_svc_emit_jumptable;
|
|
int net_svc_emit_count;
|
|
net_svc_parse_t *net_svc_parse_jumptable;
|
|
int net_svc_parse_count;
|
|
|
|
net_status_t
|
|
NET_SVC_Emit (svc_t type, void *block, sizebuf_t *buf)
|
|
{
|
|
int oldsize = buf->cursize;
|
|
net_status_t retval;
|
|
|
|
if (type < 0 || type >= net_svc_emit_count ||
|
|
!net_svc_emit_jumptable[type])
|
|
// return NET_ERROR;
|
|
Sys_Error ("NET_SVC_Emit: invalid type %d\n", type);
|
|
|
|
MSG_WriteByte (buf, type);
|
|
retval = net_svc_emit_jumptable[type] (block, buf);
|
|
if (retval == NET_SHORT)
|
|
buf->cursize = oldsize; // revert the buffer
|
|
return retval;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Parse (svc_t *type, net_svc_any_t *block, msg_t *msg)
|
|
{
|
|
*type = MSG_ReadByte (msg);
|
|
|
|
if (*type < 0 || *type >= net_svc_parse_count ||
|
|
!net_svc_parse_jumptable[*type])
|
|
return NET_ERROR;
|
|
|
|
return net_svc_parse_jumptable[*type] (block, msg);
|
|
}
|
|
|
|
|
|
net_status_t
|
|
NET_SVC_NOP_Emit (net_svc_nop_t *block, sizebuf_t *buf)
|
|
{
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_NOP_Parse (net_svc_nop_t *block, msg_t *msg)
|
|
{
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Disconnect_Emit (net_svc_disconnect_t *block, sizebuf_t *buf)
|
|
{
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Disconnect_Parse (net_svc_disconnect_t *block, msg_t *msg)
|
|
{
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Centerprint_Emit (net_svc_centerprint_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteString (buf, block->message);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Centerprint_Parse (net_svc_centerprint_t *block, msg_t *msg)
|
|
{
|
|
block->message = MSG_ReadString (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Stufftext_Emit (net_svc_stufftext_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteString (buf, block->commands);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Stufftext_Parse (net_svc_stufftext_t *block, msg_t *msg)
|
|
{
|
|
block->commands = MSG_ReadString (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Damage_Emit (net_svc_damage_t *block, sizebuf_t *buf)
|
|
{
|
|
int i;
|
|
|
|
MSG_WriteByte (buf, block->armor);
|
|
MSG_WriteByte (buf, block->blood);
|
|
for (i = 0; i < 3; i++)
|
|
MSG_WriteCoord (buf, block->from[i]);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Damage_Parse (net_svc_damage_t *block, msg_t *msg)
|
|
{
|
|
int i;
|
|
|
|
block->armor = MSG_ReadByte (msg);
|
|
block->blood = MSG_ReadByte (msg);
|
|
for (i = 0; i < 3; i++)
|
|
block->from[i] = MSG_ReadCoord (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SetAngle_Emit (net_svc_setangle_t *block, sizebuf_t *buf)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
MSG_WriteAngle (buf, block->angles[i]);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SetAngle_Parse (net_svc_setangle_t *block, msg_t *msg)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
block->angles[i] = MSG_ReadAngle (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_LightStyle_Emit (net_svc_lightstyle_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteByte (buf, block->stylenum);
|
|
MSG_WriteString (buf, block->map);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_LightStyle_Parse (net_svc_lightstyle_t *block, msg_t *msg)
|
|
{
|
|
block->stylenum = MSG_ReadByte (msg);
|
|
block->map = MSG_ReadString (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_StopSound_Emit (net_svc_stopsound_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteShort (buf, (block->entity << 3) & (block->channel & 7));
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_StopSound_Parse (net_svc_stopsound_t *block, msg_t *msg)
|
|
{
|
|
int i = MSG_ReadShort (msg);
|
|
block->entity = i >> 3;
|
|
block->channel = i & 7;
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_UpdateFrags_Emit (net_svc_updatefrags_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteByte (buf, block->player);
|
|
MSG_WriteShort (buf, block->frags);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_UpdateFrags_Parse (net_svc_updatefrags_t *block, msg_t *msg)
|
|
{
|
|
block->player = MSG_ReadByte (msg);
|
|
block->frags = MSG_ReadShort (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SpawnBaseline_Emit (net_svc_spawnbaseline_t *block, sizebuf_t *buf)
|
|
{
|
|
int i;
|
|
|
|
MSG_WriteShort (buf, block->num);
|
|
MSG_WriteByte (buf, block->modelindex);
|
|
MSG_WriteByte (buf, block->frame);
|
|
MSG_WriteByte (buf, block->colormap);
|
|
MSG_WriteByte (buf, block->skinnum);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
MSG_WriteCoord (buf, block->origin[i]);
|
|
MSG_WriteAngle (buf, block->angles[i]);
|
|
}
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SpawnBaseline_Parse (net_svc_spawnbaseline_t *block, msg_t *msg)
|
|
{
|
|
int i;
|
|
|
|
block->num = MSG_ReadShort (msg);
|
|
block->modelindex = MSG_ReadByte (msg);
|
|
block->frame = MSG_ReadByte (msg);
|
|
block->colormap = MSG_ReadByte (msg);
|
|
block->skinnum = MSG_ReadByte (msg);
|
|
|
|
// these are interlaced? bad drugs...
|
|
for (i = 0; i < 3; i ++) {
|
|
block->origin[i] = MSG_ReadCoord (msg);
|
|
block->angles[i] = MSG_ReadAngle (msg);
|
|
}
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SpawnStatic_Emit (net_svc_spawnstatic_t *block, sizebuf_t *buf)
|
|
{
|
|
int i;
|
|
|
|
MSG_WriteByte (buf, block->modelindex);
|
|
MSG_WriteByte (buf, block->frame);
|
|
MSG_WriteByte (buf, block->colormap);
|
|
MSG_WriteByte (buf, block->skinnum);
|
|
for (i = 0; i < 3; i++) {
|
|
MSG_WriteCoord (buf, block->origin[i]);
|
|
MSG_WriteAngle (buf, block->angles[i]);
|
|
}
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SpawnStatic_Parse (net_svc_spawnstatic_t *block, msg_t *msg)
|
|
{
|
|
int i;
|
|
|
|
block->modelindex = MSG_ReadByte (msg);
|
|
block->frame = MSG_ReadByte (msg);
|
|
block->colormap = MSG_ReadByte (msg);
|
|
block->skinnum = MSG_ReadByte (msg);
|
|
|
|
// these are interlaced? bad drugs...
|
|
for (i = 0; i < 3; i++) {
|
|
block->origin[i] = MSG_ReadCoord (msg);
|
|
block->angles[i] = MSG_ReadAngle (msg);
|
|
}
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_KilledMonster_Emit (net_svc_killedmonster_t *block, sizebuf_t *buf)
|
|
{
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_KilledMonster_Parse (net_svc_killedmonster_t *block, msg_t *msg)
|
|
{
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_FoundSecret_Emit (net_svc_foundsecret_t *block, sizebuf_t *buf)
|
|
{
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_FoundSecret_Parse (net_svc_foundsecret_t *block, msg_t *msg)
|
|
{
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SpawnStaticSound_Emit (net_svc_spawnstaticsound_t *block,
|
|
sizebuf_t *buf)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
MSG_WriteCoord (buf, block->position[i]);
|
|
MSG_WriteByte (buf, block->sound_num);
|
|
MSG_WriteByte (buf, block->volume);
|
|
MSG_WriteByte (buf, block->attenuation);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SpawnStaticSound_Parse (net_svc_spawnstaticsound_t *block,
|
|
msg_t *msg)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
block->position[i] = MSG_ReadCoord (msg);
|
|
block->sound_num = MSG_ReadByte (msg);
|
|
block->volume = MSG_ReadByte (msg);
|
|
block->attenuation = MSG_ReadByte (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Finale_Emit (net_svc_finale_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteString (buf, block->message);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_Finale_Parse (net_svc_finale_t *block, msg_t *msg)
|
|
{
|
|
block->message = MSG_ReadString (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SellScreen_Emit (net_svc_sellscreen_t *block, sizebuf_t *buf)
|
|
{
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SellScreen_Parse (net_svc_sellscreen_t *block, msg_t *msg)
|
|
{
|
|
return msg->badread;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SetPause_Emit (net_svc_setpause_t *block, sizebuf_t *buf)
|
|
{
|
|
MSG_WriteByte (buf, block->paused);
|
|
|
|
return buf->overflowed;
|
|
}
|
|
|
|
net_status_t
|
|
NET_SVC_SetPause_Parse (net_svc_setpause_t *block, msg_t *msg)
|
|
{
|
|
block->paused = MSG_ReadByte (msg);
|
|
|
|
return msg->badread;
|
|
}
|
|
|