/* net_clc.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 # endif #else # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #include "QF/checksum.h" #include "QF/msg.h" #include "QF/net_clc.h" #include "QF/net_ucmd.h" #include "QF/sys.h" //#include "compat.h" //#include "msg_ucmd.h" // FIXME //#include "net_clc.h" static const char *net_clc_strings[] = { [clc_bad] = "clc_bad", [clc_nop] = "clc_nop", // [clc_doublemove] = "clc_doublemove", // NQ only [clc_move] = "clc_move", [clc_stringcmd] = "clc_stringcmd", [clc_delta] = "clc_delta", [clc_tmove] = "clc_tmove", [clc_upload] = "clc_upload", }; const char * NET_CLC_GetString (clc_t type) { if (type >= 0 && type < (sizeof (net_clc_strings) / sizeof (const char *))) return net_clc_strings[type]; else return "Invalid CLC"; } // This is evil }:> static net_clc_emit_t net_clc_emit_jumptable[] = { [clc_nop] = (net_clc_emit_t) NET_CLC_NOP_Emit, [clc_move] = (net_clc_emit_t) NET_CLC_Move_Emit, [clc_stringcmd] = (net_clc_emit_t) NET_CLC_Stringcmd_Emit, [clc_delta] = (net_clc_emit_t) NET_CLC_Delta_Emit, [clc_tmove] = (net_clc_emit_t) NET_CLC_TMove_Emit, [clc_upload] = (net_clc_emit_t) NET_CLC_Upload_Emit, }; static net_clc_parse_t net_clc_parse_jumptable [] = { [clc_nop] = (net_clc_parse_t) NET_CLC_NOP_Parse, [clc_move] = (net_clc_parse_t) NET_CLC_Move_Parse, [clc_stringcmd] = (net_clc_parse_t) NET_CLC_Stringcmd_Parse, [clc_delta] = (net_clc_parse_t) NET_CLC_Delta_Parse, [clc_tmove] = (net_clc_parse_t) NET_CLC_TMove_Parse, [clc_upload] = (net_clc_parse_t) NET_CLC_Upload_Parse, }; net_status_t NET_CLC_Emit (clc_t type, void *block, sizebuf_t *buf) { int oldsize = buf->cursize; net_status_t retval; if (type < 0 || type >= sizeof (net_clc_emit_jumptable) / sizeof (net_clc_emit_t) || !net_clc_emit_jumptable[type]) return NET_ERROR; MSG_WriteByte (buf, type); retval = net_clc_emit_jumptable[type] (block, buf); if (retval == NET_SHORT) buf->cursize = oldsize; // revert the buffer return retval; } net_status_t NET_CLC_Parse (clc_t *type, net_clc_any_t *block, msg_t *msg) { *type = MSG_ReadByte (msg); if (*type < 0 || *type >= sizeof (net_clc_parse_jumptable) / sizeof (net_clc_parse_t) || !net_clc_parse_jumptable[*type]) return NET_ERROR; return net_clc_parse_jumptable[*type] (block, msg); } net_status_t NET_CLC_NOP_Emit (net_clc_nop_t *block, sizebuf_t *buf) { return buf->overflowed; } net_status_t NET_CLC_NOP_Parse (net_clc_nop_t *block, msg_t *msg) { return msg->badread; } net_status_t NET_CLC_Move_Emit (net_clc_move_t *block, sizebuf_t *buf) { int checksumindex; checksumindex = buf->cursize; MSG_WriteByte (buf, 0); // space for checksum MSG_WriteByte (buf, block->packetloss); NET_WriteDeltaUsercmd (buf, &nullcmd, &block->usercmd[0]); NET_WriteDeltaUsercmd (buf, &block->usercmd[0], &block->usercmd[1]); NET_WriteDeltaUsercmd (buf, &block->usercmd[1], &block->usercmd[2]); // write the checksum if (!buf->overflowed) buf->data[checksumindex] = COM_BlockSequenceCRCByte (buf->data + checksumindex + 1, buf->cursize - checksumindex - 1, block->seq_hash); return buf->overflowed; } net_status_t NET_CLC_Move_Parse (net_clc_move_t *block, msg_t *msg) { int checksumindex; checksumindex = msg->readcount; block->checksum = MSG_ReadByte (msg); block->packetloss = MSG_ReadByte (msg); NET_ReadDeltaUsercmd (msg, &nullcmd, &block->usercmd[0]); NET_ReadDeltaUsercmd (msg, &block->usercmd[0], &block->usercmd[1]); NET_ReadDeltaUsercmd (msg, &block->usercmd[1], &block->usercmd[2]); if (!msg->badread) block->calculatedchecksum = COM_BlockSequenceCRCByte ( msg->message->data + checksumindex + 1, MSG_GetReadCount (msg) - checksumindex - 1, block->seq_hash); return msg->badread; } net_status_t NET_CLC_Stringcmd_Emit (net_clc_stringcmd_t *block, sizebuf_t *buf) { MSG_WriteString (buf, block->command); return buf->overflowed; } net_status_t NET_CLC_Stringcmd_Parse (net_clc_stringcmd_t *block, msg_t *msg) { block->command = MSG_ReadString (msg); return msg->badread; } net_status_t NET_CLC_Delta_Emit (net_clc_delta_t *block, sizebuf_t *buf) { MSG_WriteByte (buf, block->sequence); return buf->overflowed; } net_status_t NET_CLC_Delta_Parse (net_clc_delta_t *block, msg_t *msg) { block->sequence = MSG_ReadByte (msg); return msg->badread; } net_status_t NET_CLC_TMove_Emit (net_clc_tmove_t *block, sizebuf_t *buf) { int i; for (i = 0; i < 3; i++) MSG_WriteCoord (buf, block->origin[i]); return buf->overflowed; } net_status_t NET_CLC_TMove_Parse (net_clc_tmove_t *block, msg_t *msg) { int i; for (i = 0; i < 3; i++) block->origin[i] = MSG_ReadCoord (msg); return msg->badread; } net_status_t NET_CLC_Upload_Emit (net_clc_upload_t *block, sizebuf_t *buf) { MSG_WriteShort (buf, block->size); MSG_WriteByte (buf, block->percent); MSG_WriteBlock (buf, block->data, block->size); return buf->overflowed; } net_status_t NET_CLC_Upload_Parse (net_clc_upload_t *block, msg_t *msg) { block->size = MSG_ReadShort (msg); block->percent = MSG_ReadByte (msg); block->data = MSG_ReadBlock (msg, block->size); return msg->badread; }