/* * @brief Pumps the command cycle, sending the most recently gathered movement * to the server. */ void Cl_SendCmd(void) { mem_buf_t buf; byte data[128]; if (cls.state <= CL_CONNECTING) return; if (cls.state == CL_CONNECTED) { // send any reliable messages and / or don't timeout if (cls.net_chan.message.size || cls.real_time - cls.net_chan.last_sent > 1000) Netchan_Transmit(&cls.net_chan, NULL, 0); return; } // send a user info update if needed if (cvar_user_info_modified) { Net_WriteByte(&cls.net_chan.message, CL_CMD_USER_INFO); Net_WriteString(&cls.net_chan.message, Cvar_UserInfo()); cvar_user_info_modified = false; } // finalize the current command Cl_FinalizeCmd(); // and write it out Mem_InitBuffer(&buf, data, sizeof(data)); Net_WriteByte(&buf, CL_CMD_MOVE); // let the server know what the last frame we got was, so the next // message can be delta compressed if (!cl.frame.valid || (cls.demo_file && Fs_Tell(cls.demo_file) == 0)) Net_WriteLong(&buf, -1); // no compression else Net_WriteLong(&buf, cl.frame.frame_num); // send this and the previous two cmds in the message, so // if the last packet was dropped, it can be recovered static user_cmd_t null_cmd; cl_cmd_t *cmd = &cl.cmds[(cls.net_chan.outgoing_sequence - 2) & CMD_MASK]; Net_WriteDeltaUserCmd(&buf, &null_cmd, &cmd->cmd); user_cmd_t *old_cmd = &cmd->cmd; cmd = &cl.cmds[(cls.net_chan.outgoing_sequence - 1) & CMD_MASK]; Net_WriteDeltaUserCmd(&buf, old_cmd, &cmd->cmd); old_cmd = &cmd->cmd; cmd = &cl.cmds[(cls.net_chan.outgoing_sequence) & CMD_MASK]; Net_WriteDeltaUserCmd(&buf, old_cmd, &cmd->cmd); // deliver the message Netchan_Transmit(&cls.net_chan, buf.data, buf.size); cl.packet_counter++; // initialize the next command Cl_InitCmd(); }
/* * @brief Writes the specified lump to the AAS file. */ static void WriteLump(file_t *f, d_bsp_lump_t *lump, void *data, size_t len) { lump->file_ofs = LittleLong((int32_t) Fs_Tell(f)); lump->file_len = LittleLong((int32_t) len); Fs_Write(f, data, 1, (len + 3) & ~3); }
/* * @brief Dumps the current net message, prefixed by the length. */ void Cl_WriteDemoMessage(void) { int32_t len; if (!cls.demo_file) return; // if we received an uncompressed frame, write the demo header if (cl.frame.delta_frame < 1 && !Fs_Tell(cls.demo_file)) { Cl_WriteDemoHeader(); } // the first eight bytes are just packet sequencing stuff len = LittleLong(net_message.size - 8); Fs_Write(cls.demo_file, &len, sizeof(len), 1); Fs_Write(cls.demo_file, net_message.data + 8, len, 1); }
/** * @brief Writes the most recent movement command(s) using delta-compression if available. */ static void Cl_WriteMovementCommand(mem_buf_t *buf) { static cl_cmd_t null_cmd; Net_WriteByte(buf, CL_CMD_MOVE); if (!cl.frame.valid || (cls.demo_file && Fs_Tell(cls.demo_file) == 0)) { Net_WriteLong(buf, -1); } else { Net_WriteLong(buf, cl.frame.frame_num); } cl_cmd_t *from = &null_cmd, *to = &cl.cmds[(cls.net_chan.outgoing_sequence - 2) & CMD_MASK]; Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd); from = to; to = &cl.cmds[(cls.net_chan.outgoing_sequence - 1) & CMD_MASK]; Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd); from = to; to = &cl.cmds[(cls.net_chan.outgoing_sequence) & CMD_MASK]; Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd); }
/** * @brief Dumps the current net message, prefixed by the length. */ void Cl_WriteDemoMessage(void) { if (!cls.demo_file) { return; } if (!Fs_Tell(cls.demo_file)) { if (cl.frame.delta_frame_num < 0) { Com_Debug(DEBUG_CLIENT, "Received uncompressed frame, writing demo header..\n"); Cl_WriteDemoHeader(); } else { return; // wait for an uncompressed packet } } // the first eight bytes are just packet sequencing stuff const int32_t len = LittleLong((int32_t) (net_message.size - 8)); Fs_Write(cls.demo_file, &len, sizeof(len), 1); Fs_Write(cls.demo_file, net_message.data + 8, len, 1); }