/* ================= Netchan_TransmitNextFragment Send one fragment of the current message ================= */ void Netchan_TransmitNextFragment( netchan_t *chan ) { msg_t send; byte send_buf[MAX_PACKETLEN]; int fragmentLength; // write the packet header MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT ); // send the qport if we are a client if ( chan->sock == NS_CLIENT ) { MSG_WriteShort( &send, qport->integer ); } // copy the reliable message to the packet first fragmentLength = FRAGMENT_SIZE; if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) { fragmentLength = chan->unsentLength - chan->unsentFragmentStart; } MSG_WriteShort( &send, chan->unsentFragmentStart ); MSG_WriteShort( &send, fragmentLength ); MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength ); // send the datagram NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress ); if ( showpackets->integer ) { Com_Printf ("%s send %4i : s=%i fragment=%i,%i\n" , netsrcString[ chan->sock ] , send.cursize , chan->outgoingSequence , chan->unsentFragmentStart, fragmentLength); } chan->unsentFragmentStart += fragmentLength; // this exit condition is a little tricky, because a packet // that is exactly the fragment length still needs to send // a second packet of zero length so that the other side // can tell there aren't more to follow if ( chan->unsentFragmentStart == chan->unsentLength && fragmentLength != FRAGMENT_SIZE ) { chan->outgoingSequence++; chan->unsentFragments = qfalse; } }
/* ======================= SV_SendClientSnapshot Also called by SV_FinalMessage ======================= */ void SV_SendClientSnapshot( client_t* client ) { byte msg_buf[MAX_MSGLEN]; msg_s msg; // build the snapshot SV_BuildClientSnapshot( client ); // bots need to have their snapshots build, but // the query them directly without needing to be sent //if ( client->gentity && client->gentity->r.svFlags & SVF_BOT ) { // return; //} MSG_Init( &msg, msg_buf, sizeof( msg_buf ) ); msg.allowoverflow = true; // compression byte is the first byte in all server->client messages msg.oob = true; MSG_WriteByte( &msg, 0 ); msg.oob = false; // NOTE, MRE: all server->client messages now acknowledge // let the client know which reliable clientCommands we have received MSG_WriteLong( &msg, client->lastClientCommand ); // (re)send any reliable server commands SV_UpdateServerCommandsToClient( client, &msg ); // send over all the relevant entityState_s // and the playerState_s SV_WriteSnapshotToClient( client, &msg ); #ifdef USE_VOIP SV_WriteVoipToClient( client, &msg ); #endif // check for overflow if ( msg.overflowed ) { Com_Printf( "WARNING: msg overflowed for %s\n", client->name ); MSG_Clear( &msg ); } SV_SendMessageToClient( &msg, client ); }
/* ================ SV_SendServerinfo Sends the first message from the server to a connected client. This will be sent on the initial connection and upon each server load. ================ */ void SV_SendServerinfo (client_t *client) { char **s; char message[2048]; MSG_WriteByte (&client->message, svc_print); sprintf (message, "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc); MSG_WriteString (&client->message,message); MSG_WriteByte (&client->message, svc_serverinfo); MSG_WriteLong (&client->message, PROTOCOL_VERSION); MSG_WriteByte (&client->message, svs.maxclients); if (!coop.value && deathmatch.value) MSG_WriteByte (&client->message, GAME_DEATHMATCH); else MSG_WriteByte (&client->message, GAME_COOP); sprintf (message, pr_strings+sv.edicts->u.v.message); MSG_WriteString (&client->message,message); for (s = sv.model_precache+1 ; *s ; s++) MSG_WriteString (&client->message, *s); MSG_WriteByte (&client->message, 0); for (s = sv.sound_precache+1 ; *s ; s++) MSG_WriteString (&client->message, *s); MSG_WriteByte (&client->message, 0); // send music MSG_WriteByte (&client->message, svc_cdtrack); MSG_WriteByte (&client->message, (int) sv.edicts->u.v.sounds); MSG_WriteByte (&client->message, (int) sv.edicts->u.v.sounds); // set view MSG_WriteByte (&client->message, svc_setview); MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict)); MSG_WriteByte (&client->message, svc_signonnum); MSG_WriteByte (&client->message, 1); client->sendsignon = true; client->spawned = false; // need prespawn, spawn, etc }
/* =============== Netchan_Transmit Sends a message to a connection, fragmenting if necessary A 0 length will still generate a packet. ================ */ void Netchan_Transmit( netchan_t *chan, size_t length, const byte *data ) { msg_t send; byte send_buf[MAX_PACKETLEN]; if ( length > MAX_MSGLEN ) { Com_Error( ERR_DROP, "Netchan_Transmit: length = %i", length ); } chan->unsentFragmentStart = 0; // fragment large reliable messages if ( length >= FRAGMENT_SIZE ) { chan->unsentFragments = qtrue; chan->unsentLength = length; Com_Memcpy( chan->unsentBuffer, data, length ); // only send the first fragment now Netchan_TransmitNextFragment( chan ); return; } // write the packet header MSG_InitOOB (&send, send_buf, sizeof(send_buf)); MSG_WriteLong( &send, chan->outgoingSequence ); chan->outgoingSequence++; // send the qport if we are a client if ( chan->sock == NS_CLIENT ) { MSG_WriteShort( &send, qport->integer ); } MSG_WriteData( &send, data, length ); // send the datagram NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress ); if ( showpackets->integer ) { Com_Printf( "%s send %4i : s=%i ack=%i\n" , netsrcString[ chan->sock ] , send.cursize , chan->outgoingSequence - 1 , chan->incomingSequence ); } }
/* ================== SV_UpdateServerCommandsToClient (re)send all server commands the client hasn't acknowledged yet ================== */ void SV_UpdateServerCommandsToClient( client_t *client, msg_t *msg ) { int i; int reliableAcknowledge; if ( client->demo.isBot && client->demo.demorecording ) { reliableAcknowledge = client->demo.botReliableAcknowledge; } else { reliableAcknowledge = client->reliableAcknowledge; } // write any unacknowledged serverCommands for ( i = reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) { MSG_WriteByte( msg, svc_serverCommand ); MSG_WriteLong( msg, i ); MSG_WriteString( msg, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] ); } client->reliableSent = client->reliableSequence; }
void CTerraBillingCtrl_Decoder:: Transmite_TerraGCPacket_Remain_Minute_NoticeMessage( playerCharacter_t* pToPlayerRecord, const int RemainMinute) const { MSG_BeginWriting(&netMessage); MSG_Clear(&netMessage); { MSG_WriteByte(&netMessage, GSC_EXTEND); MSG_WriteByte(&netMessage, GSC_EXTEND_TERRA); MSG_WriteByte(&netMessage, tagTerraGCPacket::Remain_Minute_NoticeMessage); MSG_WriteLong(&netMessage, RemainMinute); NET_SendMessage(&pToPlayerRecord->sock, &netMessage); } MSG_EndWriting(&netMessage); }
void CHelperManager_Encoder::SendMessage_Mypoint_toTaker( playerCharacter_t* pPlayer, char* pTakerName,char* pHelperName, int MyPoint) { MSG_BeginWriting(&netMessage); MSG_Clear( &netMessage ); { MSG_WriteByte(&netMessage, EXTEND_SECOND); MSG_WriteShort( &netMessage, HELPER_SYSTEM ); MSG_WriteShort(&netMessage, SC_SENDMYPOINT_toAllPlayer); MSG_WriteString(&netMessage,pTakerName); MSG_WriteString(&netMessage,pHelperName); MSG_WriteLong(&netMessage,MyPoint); NET_SendMessage(&pPlayer->sock, &netMessage); } MSG_EndWriting(&netMessage); }
void CPostFunc::GTH_SendMessage_PostSystem_Send() { char name[NAMESTRING+1]; char title[CPostManager::POST_TITLESIZE+1]; char message[CPostManager::POST_STRSIZE+1]; strncpy(name,g_ifMng->m_mailBoxWin->m_name,NAMESTRING); name[NAMESTRING]=NULL; CTools::Replace_singleQUOTATIONmark_by_doubleQUOTATIONmark(name); strncpy(title,g_ifMng->m_mailBoxWin->m_title,CPostManager::POST_TITLESIZE); title[CPostManager::POST_TITLESIZE]=NULL; CTools::Replace_singleQUOTATIONmark_by_doubleQUOTATIONmark(title); strncpy(message,g_ifMng->m_mailBoxWin->m_message,CPostManager::POST_STRSIZE); message[CPostManager::POST_STRSIZE]=NULL; CTools::Replace_singleQUOTATIONmark_by_doubleQUOTATIONmark(message); MSG_BeginWriting(&netMessage); MSG_Clear( &netMessage ); { MSG_WriteByte(&netMessage, CC_EXTEND); MSG_WriteByte(&netMessage, CC_POSTSYSTEM); MSG_WriteByte(&netMessage, POSTSYSTEM_SEND); MSG_WriteString(&netMessage, name); MSG_WriteString(&netMessage, title); MSG_WriteString(&netMessage, message); MSG_WriteLong(&netMessage, g_ifMng->m_mailBoxWin->m_nak); NET_SendMessage(&gsSocket, &netMessage); } MSG_EndWriting( &netMessage ); }
/* Netchan_OutOfBand Sends an out-of-band datagram */ void Netchan_OutOfBand (netadr_t adr, int length, byte * data) { byte send_buf[MAX_MSGLEN + PACKET_HEADER]; sizebuf_t send; // write the packet header send.data = send_buf; send.maxsize = sizeof (send_buf); send.cursize = 0; MSG_WriteLong (&send, -1); // -1 sequence means out of band SZ_Write (&send, data, length); // send the datagram // zoid, no input in demo playback mode if (!net_blocksend) Netchan_SendPacket (send.cursize, send.data, adr); }
inline void CGMCtrl::TransmitePacket_NProtect_msgs_notify_change(const BOOL in_bEnable) const { MSG_BeginWriting(&netMessage); MSG_Clear( &netMessage ); { MSG_WriteByte(&netMessage, EXTEND_SECOND); MSG_WriteShort(&netMessage, GMsystem); MSG_WriteShort(&netMessage, tagExtendSecondPacket_GMsystem::GMsystem_NProtect); MSG_WriteShort(&netMessage, tagExtendSecondPacket_GMsystem::tagNProtect::msgs_notify_change); MSG_WriteLong(&netMessage,in_bEnable); for(int i=1; i < MAX_MEMBER_SERVER; i++){ if ( !g_memberServer[i].active ) continue; NET_SendUnreliableMessage(&g_memberServer[i].sock, &netMessage); } } MSG_EndWriting(&netMessage); }
void CGs_To_Cc::Send(playerCharacter_t* pPlayer,int SystemType,int mainType, int subType,int val, char *TargetPlayerName) { MSG_BeginWriting( &netMessage ); MSG_Clear( &netMessage ); { MSG_WriteByte(&netMessage, EXTEND_SECOND); MSG_WriteShort(&netMessage, SystemType); MSG_WriteShort(&netMessage, mainType); MSG_WriteShort(&netMessage, subType); MSG_WriteLong(&netMessage, val); MSG_WriteString(&netMessage, TargetPlayerName); NET_SendMessage(&pPlayer->sock, &netMessage); } MSG_EndWriting(&netMessage); }
void Netchan_OutOfBand(netsrc_t sock, netadr_t adr, int length, byte *data) { sizebuf_t send; byte send_buf[NET_MAX_PAYLOAD]; send.buffername = "Netchan_OutOfBand"; send.data = send_buf; send.maxsize = sizeof(send_buf); send.cursize = 0; send.flags = SIZEBUF_ALLOW_OVERFLOW; MSG_WriteLong(&send, -1); SZ_Write(&send, data, length); if (!g_pcls.demoplayback) { NET_SendPacket(sock, send.cursize, send.data, adr); } }
/* ================ SV_SendClientGameState Sends the first message from the server to a connected client. This will be sent on the initial connection and upon each new map load. It will be resent if the client acknowledges a later message but has the wrong gamestate. ================ */ void SV_SendClientGameState( client_t *client ) { int start; msg_t msg; byte msgBuffer[MAX_MSGLEN]; Com_DPrintf ("SV_SendGameState() for %s\n", client->name); client->state = CS_PRIMED; // when we receive the first packet from the client, we will // notice that it is from a different serverid and that the // gamestate message was not just sent, forcing a retransmit client->gamestateMessageNum = client->netchan.outgoingSequence; // clear the reliable message list for this client client->reliableSequence = 0; client->reliableAcknowledge = 0; MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) ); // send the gamestate MSG_WriteByte( &msg, svc_gamestate ); MSG_WriteLong( &msg, client->reliableSequence ); // write the configstrings for ( start = 0 ; start < MAX_CONFIGSTRINGS ; start++ ) { if (sv.configstrings[start][0]) { MSG_WriteByte( &msg, svc_configstring ); MSG_WriteShort( &msg, start ); MSG_WriteString( &msg, sv.configstrings[start] ); } } MSG_WriteByte( &msg, 0 ); // check for overflow if ( msg.overflowed ) { Com_Printf ("WARNING: GameState overflowed for %s\n", client->name); } // deliver this to the client SV_SendMessageToClient( &msg, client ); }
/* * TV_Downstream_AddReliableCommandsToMessage * * (re)send all server commands the client hasn't acknowledged yet */ void TV_Downstream_AddReliableCommandsToMessage( client_t *client, msg_t *msg ) { unsigned int i; // write any unacknowledged serverCommands for( i = client->reliableAcknowledge + 1; i <= client->reliableSequence; i++ ) { if( !strlen( client->reliableCommands[i & ( MAX_RELIABLE_COMMANDS-1 )] ) ) continue; MSG_WriteByte( msg, svc_servercmd ); if( !client->reliable ) MSG_WriteLong( msg, i ); MSG_WriteString( msg, client->reliableCommands[i & ( MAX_RELIABLE_COMMANDS-1 )] ); } client->reliableSent = client->reliableSequence; if( client->reliable ) client->reliableAcknowledge = client->reliableSent; }
// Sends resource to all other players, optionally skipping originating player. void SV_Customization(client_t *pPlayer, resource_t *pResource, qboolean bSkipPlayer) { int i; int nPlayerNumber; client_t *pHost; // Get originating player id for (i = 0, pHost = g_psvs.clients; i < g_psvs.maxclients; i++, pHost++) { if (pHost == pPlayer) break; } if (i == g_psvs.maxclients) { Sys_Error("Couldn't find player index for customization."); } nPlayerNumber = i; // Send resource to all other active players for (i = 0, pHost = g_psvs.clients; i < g_psvs.maxclients; i++, pHost++) { if (!pHost->active && !pHost->spawned || pHost->fakeclient) continue; if (pHost == pPlayer && bSkipPlayer) continue; MSG_WriteByte(&pHost->netchan.message, svc_customization); MSG_WriteByte(&pHost->netchan.message, nPlayerNumber); MSG_WriteByte(&pHost->netchan.message, pResource->type); MSG_WriteString(&pHost->netchan.message, pResource->szFileName); MSG_WriteShort(&pHost->netchan.message, pResource->nIndex); MSG_WriteLong(&pHost->netchan.message, pResource->nDownloadSize); MSG_WriteByte(&pHost->netchan.message, pResource->ucFlags); if (pResource->ucFlags & RES_CUSTOM) { SZ_Write(&pHost->netchan.message, pResource->rgucMD5_hash, 16); } } }
/* ================== SV_WriteVoipToClient Check to see if there is any VoIP queued for a client, and send if there is. ================== */ void SV_WriteVoipToClient( client_t *cl, msg_t *msg ) { voipServerPacket_t *packet = &cl->voipPacket[0]; int totalbytes = 0; int i; if (*cl->downloadName) { cl->queuedVoipPackets = 0; return; // no VoIP allowed if download is going, to save bandwidth. } // Write as many VoIP packets as we reasonably can... for (i = 0; i < cl->queuedVoipPackets; i++, packet++) { totalbytes += packet->len; if (totalbytes > MAX_DOWNLOAD_BLKSIZE) break; // You have to start with a svc_EOF, so legacy clients drop the // rest of this packet. Otherwise, those without VoIP support will // see the svc_voip command, then panic and disconnect. // Generally we don't send VoIP packets to legacy clients, but this // serves as both a safety measure and a means to keep demo files // compatible. MSG_WriteByte( msg, svc_EOF ); MSG_WriteByte( msg, svc_extension ); MSG_WriteByte( msg, svc_voip ); MSG_WriteShort( msg, packet->sender ); MSG_WriteByte( msg, (byte) packet->generation ); MSG_WriteLong( msg, packet->sequence ); MSG_WriteByte( msg, packet->frames ); MSG_WriteShort( msg, packet->len ); MSG_WriteData( msg, packet->data, packet->len ); } // !!! FIXME: I hate this queue system. cl->queuedVoipPackets -= i; if (cl->queuedVoipPackets > 0) { memmove( &cl->voipPacket[0], &cl->voipPacket[i], sizeof (voipServerPacket_t) * i); } }
void SV_UpdateServerCommandsToClientRecover( client_t *client, msg_t *msg ) { int i; int cmdlen; for(i = client->reliableAcknowledge + 1; i <= client->reliableSequence; i++) { cmdlen = strlen(client->reliableCommands[i & ( MAX_RELIABLE_COMMANDS - 1 )].command); if ( cmdlen + msg->cursize + 6 >= msg->maxsize ) break; MSG_WriteByte(msg, svc_serverCommand); MSG_WriteLong(msg, i); MSG_WriteString(msg, client->reliableCommands[i & ( MAX_RELIABLE_COMMANDS - 1 )].command); } if ( i - 1 > client->reliableSent ) client->reliableSent = i - 1; }
/* ==================== CL_Stop_f stop recording a demo ==================== */ void CL_Stop_f (void) { if (!cls.demorecording) { Con_Printf ("Not recording a demo.\n"); return; } // write a disconnect message to the demo file SZ_Clear (&net_message); MSG_WriteLong (&net_message, -1); // -1 sequence means out of band MSG_WriteByte (&net_message, svc_disconnect); MSG_WriteString (&net_message, "EndOfDemo"); CL_WriteDemoMessage (&net_message); // finish up fclose (cls.demofile); cls.demofile = NULL; cls.demorecording = false; Con_Printf ("Completed demo\n"); }
/* =============== Netchan_OutOfBand Sends an out-of-band datagram ================ */ void Netchan_OutOfBand(int s, struct sockaddr_in *adr, int length, byte *data) { sizebuf_t send1; byte send_buf[MAX_MSGLEN + PACKET_HEADER]; SZ_InitEx(&send1, send_buf, sizeof(send_buf), true); // write the packet header MSG_WriteLong(&send1, -1); // -1 sequence means out of band // write data SZ_Write(&send1, data, length); if (send1.overflowed) { Sys_Printf("Netchan_OutOfBand: overflowed\n"); return; // ah, should not happens } // send the datagram NET_SendPacket(s, send1.cursize, send1.data, adr); }
// // P_FireWeapon. // void P_FireWeapon (player_t *player) { statenum_t newstate; if (!P_CheckAmmo (player)) return; // [tm512] Send the client the weapon they just fired so // that they can fix any weapon desyncs that they get - apr 14 2012 if (serverside && !clientside) { MSG_WriteMarker (&player->client.reliablebuf, svc_fireweapon); MSG_WriteByte (&player->client.reliablebuf, player->readyweapon); MSG_WriteLong (&player->client.reliablebuf, player->tic); } P_SetMobjState (player->mo, S_PLAY_ATK1); newstate = weaponinfo[player->readyweapon].atkstate; P_SetPsprite (player, ps_weapon, newstate); P_NoiseAlert (player->mo, player->mo); }
void CDanBattleManager::SendGSM_Refresh_PersonData(playerCharacter_t* pc, int type, int etc1, int etc2) { MSG_BeginWriting(&netMessage); MSG_Clear( &netMessage ); MSG_WriteByte(&netMessage, GSC_EXTEND); MSG_WriteByte(&netMessage, GSC_DAN_BATTLE); MSG_WriteByte(&netMessage, DANB_BATTLE_REFRESH_PERSONDATA); MSG_WriteLong(&netMessage, type); switch(type) { case 0: MSG_WriteLong(&netMessage, pc->curChargeSE); break; case 1: MSG_WriteLong(&netMessage, pc->rankPoint); MSG_WriteLong(&netMessage, g_guild[pc->guildIdx].famePoint); case 2: MSG_WriteLong(&netMessage, etc1); break; case 3: MSG_WriteLong(&netMessage, etc1); break; } NET_SendUnreliableMessage(&pc->sock, &netMessage); MSG_EndWriting(&netMessage); }
void SV_SendClientMapChange( client_t *client ) { msg_t msg; byte msgBuffer[MAX_MSGLEN]; MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) ); // NOTE, MRE: all server->client messages now acknowledge // let the client know which reliable clientCommands we have received MSG_WriteLong( &msg, client->lastClientCommand ); // send any server commands waiting to be sent first. // we have to do this cause we send the client->reliableSequence // with a gamestate and it sets the clc.serverCommandSequence at // the client side SV_UpdateServerCommandsToClient( client, &msg ); // send the gamestate MSG_WriteByte( &msg, svc_mapchange ); // deliver this to the client SV_SendMessageToClient( &msg, client ); }
/* ================== SV_WriteVoipToClient Check to see if there is any VoIP queued for a client, and send if there is. ================== */ static void SV_WriteVoipToClient( client_t* cl, msg_s* msg ) { int totalbytes = 0; int i; voipServerPacket_t* packet; if ( cl->queuedVoipPackets ) { // Write as many VoIP packets as we reasonably can... for ( i = 0; i < cl->queuedVoipPackets; i++ ) { packet = cl->voipPacket[( i + cl->queuedVoipIndex ) % ARRAY_LEN( cl->voipPacket )]; if ( !*cl->downloadName ) { totalbytes += packet->len; if ( totalbytes > ( msg->maxsize - msg->cursize ) / 2 ) break; MSG_WriteByte( msg, svc_voip ); MSG_WriteShort( msg, packet->sender ); MSG_WriteByte( msg, ( byte ) packet->generation ); MSG_WriteLong( msg, packet->sequence ); MSG_WriteByte( msg, packet->frames ); MSG_WriteShort( msg, packet->len ); MSG_WriteBits( msg, packet->flags, VOIP_FLAGCNT ); MSG_WriteData( msg, packet->data, packet->len ); } free( packet ); } cl->queuedVoipPackets -= i; cl->queuedVoipIndex += i; cl->queuedVoipIndex %= ARRAY_LEN( cl->voipPacket ); } }
/* =================== SV_FullClientUpdate Writes all update values to a sizebuf =================== */ void SV_FullClientUpdate (client_t *client, sizebuf_t *buf) { int i; char info[MAX_INFO_STRING]; i = client - svs.clients; if (client->state == cs_free && sv_fastconnect.value) return; MSG_WriteByte (buf, svc_updatefrags); MSG_WriteByte (buf, i); MSG_WriteShort (buf, client->old_frags); MSG_WriteByte (buf, svc_updateping); MSG_WriteByte (buf, i); MSG_WriteShort (buf, SV_CalcPing (client)); MSG_WriteByte (buf, svc_updatepl); MSG_WriteByte (buf, i); MSG_WriteByte (buf, client->lossage); MSG_WriteByte (buf, svc_updateentertime); MSG_WriteByte (buf, i); MSG_WriteFloat (buf, svs.realtime - client->connection_started); strcpy (info, client->userinfo); Info_RemovePrefixedKeys (info, '_'); // server passwords, etc Info_RemoveKey (info, "pmodel"); Info_RemoveKey (info, "emodel"); MSG_WriteByte (buf, svc_updateuserinfo); MSG_WriteByte (buf, i); MSG_WriteLong (buf, client->userid); MSG_WriteString (buf, info); }
static void FWD_check_timeout(void) { byte msg_data[6]; sizebuf_t msg; time_t cur_time; double d_cur_time; peer_t *p; SZ_InitEx(&msg, msg_data, sizeof(msg_data), true); cur_time = time(NULL); d_cur_time = Sys_DoubleTime(); for (p = peers; p; p = p->next) { // this is helper for q3 to guess disconnect asap if (p->proto == pr_q3) { if (cur_time - p->last > 1 && d_cur_time - p->q3_disconnect_check > 0.05 && p->ps == ps_connected) { p->q3_disconnect_check = d_cur_time; SZ_Clear(&msg); MSG_WriteLong(&msg, 0); MSG_WriteShort(&msg, p->qport); NET_SendPacket(p->s, msg.cursize, msg.data, &p->to); } } if (cur_time - p->last < 15) // few seconds timeout continue; Sys_DPrintf("peer %s:%d timed out\n", inet_ntoa(p->from.sin_addr), (int)ntohs(p->from.sin_port)); p->ps = ps_drop; } }
void CWeatherSystem:: GTH_SendMessage_Request_WeatherSetting ( TIMESTATE weather, float limittime, bool IsUseItem , int invenpos ) { MSG_BeginWriting( &netMessage ); MSG_Clear( &netMessage ); { MSG_WriteByte(&netMessage, EXTEND_SECOND); MSG_WriteShort(&netMessage, WEATHER_SYSTEM ); MSG_WriteShort(&netMessage, CC_WEATHER_SYSTEM ); MSG_WriteByte(&netMessage, CC_WEATHER_SYSTEM_REQUEST_USE_WEATHER_ITEM); MSG_WriteByte(&netMessage, weather); MSG_WriteLong(&netMessage, limittime); MSG_WriteByte(&netMessage, IsUseItem); if ( IsUseItem ) MSG_WriteByte(&netMessage, invenpos); NET_SendMessage(&gsSocket, &netMessage); } MSG_EndWriting(&netMessage); }
// // CL_RequestDownload // please sir, can i have some more? // void CL_RequestDownload(std::string filename, std::string filehash) { if (cl_serverdownload) { // [Russell] - Allow resumeable downloads if ((download.filename != filename) || (download.md5 != filehash)) { download.filename = filename; download.md5 = filehash; download.got_bytes = 0; } // denis todo clear previous downloads MSG_WriteMarker(&net_buffer, clc_wantwad); MSG_WriteString(&net_buffer, filename.c_str()); MSG_WriteString(&net_buffer, filehash.c_str()); MSG_WriteLong(&net_buffer, download.got_bytes); NET_SendPacket(net_buffer, serveraddr); Printf(PRINT_HIGH, "Requesting download...\n"); // check for completion // [Russell] - We go over the boundary, because sometimes the download will // pause at 100% if the server disconnected you previously, you can // reconnect a couple of times and this will let the checksum system do its // work if ((download.buf != NULL) && (download.got_bytes >= download.buf->maxsize())) { IntDownloadComplete(); } } }
/* * SNAP_DemoMetaDataMessage */ static void SNAP_DemoMetaDataMessage( msg_t *msg, const char *meta_data, size_t meta_data_realsize ) { int demoinfo_len, demoinfo_len_pos, demoinfo_end; int meta_data_ofs, meta_data_ofs_pos; // demoinfo message MSG_WriteByte( msg, svc_demoinfo ); demoinfo_len_pos = msg->cursize; MSG_WriteLong( msg, 0 ); // svc_demoinfo length demoinfo_len = msg->cursize; meta_data_ofs_pos = msg->cursize; MSG_WriteLong( msg, 0 ); // meta data start offset meta_data_ofs = msg->cursize; if( meta_data_realsize > SNAP_MAX_DEMO_META_DATA_SIZE ) meta_data_realsize = SNAP_MAX_DEMO_META_DATA_SIZE; if( meta_data_realsize > 0 ) meta_data_realsize--; meta_data_ofs = msg->cursize - meta_data_ofs; MSG_WriteLong( msg, meta_data_realsize ); // real size MSG_WriteLong( msg, SNAP_MAX_DEMO_META_DATA_SIZE ); // max size MSG_WriteData( msg, meta_data, meta_data_realsize ); MSG_WriteData( msg, dummy_meta_data, SNAP_MAX_DEMO_META_DATA_SIZE - meta_data_realsize ); demoinfo_end = msg->cursize; demoinfo_len = msg->cursize - demoinfo_len; msg->cursize = demoinfo_len_pos; MSG_WriteLong( msg, demoinfo_len ); // svc_demoinfo length msg->cursize = meta_data_ofs_pos; MSG_WriteLong( msg, meta_data_ofs ); // meta data start offset msg->cursize = demoinfo_end; }
/* * CL_WriteUcmdsToMessage */ void CL_WriteUcmdsToMessage( msg_t *msg ) { usercmd_t *cmd; usercmd_t *oldcmd; usercmd_t nullcmd; unsigned int resendCount; unsigned int i; unsigned int ucmdFirst; unsigned int ucmdHead; if( !msg || cls.state < CA_ACTIVE || cls.demo.playing ) return; // find out what ucmds we have to send ucmdFirst = cls.ucmdAcknowledged + 1; ucmdHead = cl.cmdNum + 1; if( cl_ucmdMaxResend->integer > CMD_BACKUP * 0.5 ) Cvar_SetValue( "cl_ucmdMaxResend", CMD_BACKUP * 0.5 ); else if( cl_ucmdMaxResend->integer < 1 ) Cvar_SetValue( "cl_ucmdMaxResend", 1 ); // find what is our resend count (resend doesn't include the newly generated ucmds) // and move the start back to the resend start if( ucmdFirst <= cls.ucmdSent + 1 ) resendCount = 0; else resendCount = ( cls.ucmdSent + 1 ) - ucmdFirst; if( resendCount > (unsigned int)cl_ucmdMaxResend->integer ) resendCount = (unsigned int)cl_ucmdMaxResend->integer; if( ucmdFirst > ucmdHead ) ucmdFirst = ucmdHead; // if this happens, the player is in a freezing lag. Send him the less possible data if( ( ucmdHead - ucmdFirst ) + resendCount > CMD_MASK * 0.5 ) resendCount = 0; // move the start backwards to the resend point ucmdFirst = ( ucmdFirst > resendCount ) ? ucmdFirst - resendCount : ucmdFirst; if( ( ucmdHead - ucmdFirst ) > CMD_MASK ) // ran out of updates, seduce the send to try to recover activity ucmdFirst = ucmdHead - 3; // begin a client move command MSG_WriteByte( msg, clc_move ); // (acknowledge server frame snap) // let the server know what the last frame we // got was, so the next message can be delta compressed if( cl.receivedSnapNum <= 0 ) MSG_WriteLong( msg, -1 ); else MSG_WriteLong( msg, cl.snapShots[cl.receivedSnapNum & UPDATE_MASK].serverFrame ); // Write the actual ucmds // write the id number of first ucmd to be sent, and the count MSG_WriteLong( msg, ucmdHead ); MSG_WriteByte( msg, (uint8_t)( ucmdHead - ucmdFirst ) ); // write the ucmds for( i = ucmdFirst; i < ucmdHead; i++ ) { if( i == ucmdFirst ) // first one isn't delta-compressed { cmd = &cl.cmds[i & CMD_MASK]; memset( &nullcmd, 0, sizeof( nullcmd ) ); MSG_WriteDeltaUsercmd( msg, &nullcmd, cmd ); } else // delta compress to previous written { cmd = &cl.cmds[i & CMD_MASK]; oldcmd = &cl.cmds[( i-1 ) & CMD_MASK]; MSG_WriteDeltaUsercmd( msg, oldcmd, cmd ); } } cls.ucmdSent = i; }
/* ==================== CL_Record_f record <demoname> <server> ==================== */ void CL_Record_f (void) { int c; char name[MAX_OSPATH]; sizebuf_t buf; char buf_data[MAX_MSGLEN]; int n, i, j; char *s; entity_t *ent; entity_state_t *es, blankes; player_info_t *player; extern char gamedirfile[]; int seq = 1; c = Cmd_Argc(); if (c != 2) { Con_Printf ("record <demoname>\n"); return; } if (cls.state != ca_active) { Con_Printf ("You must be connected to record.\n"); return; } if (cls.demorecording) CL_Stop_f(); sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1)); // // open the demo file // COM_DefaultExtension (name, ".qwd"); cls.demofile = fopen (name, "wb"); if (!cls.demofile) { Con_Printf ("ERROR: couldn't open.\n"); return; } Con_Printf ("recording to %s.\n", name); cls.demorecording = true; /*-------------------------------------------------*/ // serverdata // send the info about the new client to all connected clients memset(&buf, 0, sizeof(buf)); buf.data = buf_data; buf.maxsize = sizeof(buf_data); // send the serverdata MSG_WriteByte (&buf, svc_serverdata); MSG_WriteLong (&buf, PROTOCOL_VERSION); MSG_WriteLong (&buf, cl.servercount); MSG_WriteString (&buf, gamedirfile); if (cl.spectator) MSG_WriteByte (&buf, cl.playernum | 128); else MSG_WriteByte (&buf, cl.playernum); // send full levelname MSG_WriteString (&buf, cl.levelname); // send the movevars MSG_WriteFloat(&buf, movevars.gravity); MSG_WriteFloat(&buf, movevars.stopspeed); MSG_WriteFloat(&buf, movevars.maxspeed); MSG_WriteFloat(&buf, movevars.spectatormaxspeed); MSG_WriteFloat(&buf, movevars.accelerate); MSG_WriteFloat(&buf, movevars.airaccelerate); MSG_WriteFloat(&buf, movevars.wateraccelerate); MSG_WriteFloat(&buf, movevars.friction); MSG_WriteFloat(&buf, movevars.waterfriction); MSG_WriteFloat(&buf, movevars.entgravity); // send music MSG_WriteByte (&buf, svc_cdtrack); MSG_WriteByte (&buf, 0); // none in demos // send server info string MSG_WriteByte (&buf, svc_stufftext); MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) ); // flush packet CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); // soundlist MSG_WriteByte (&buf, svc_soundlist); MSG_WriteByte (&buf, 0); n = 0; s = cl.sound_name[n+1]; while (*s) { MSG_WriteString (&buf, s); if (buf.cursize > MAX_MSGLEN/2) { MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, n); CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); MSG_WriteByte (&buf, svc_soundlist); MSG_WriteByte (&buf, n + 1); } n++; s = cl.sound_name[n+1]; } if (buf.cursize) { MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0); CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } // modellist MSG_WriteByte (&buf, svc_modellist); MSG_WriteByte (&buf, 0); n = 0; s = cl.model_name[n+1]; while (*s) { MSG_WriteString (&buf, s); if (buf.cursize > MAX_MSGLEN/2) { MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, n); CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); MSG_WriteByte (&buf, svc_modellist); MSG_WriteByte (&buf, n + 1); } n++; s = cl.model_name[n+1]; } if (buf.cursize) { MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0); CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } // spawnstatic for (i = 0; i < cl.num_statics; i++) { ent = cl_static_entities + i; MSG_WriteByte (&buf, svc_spawnstatic); for (j = 1; j < MAX_MODELS; j++) if (ent->model == cl.model_precache[j]) break; if (j == MAX_MODELS) MSG_WriteByte (&buf, 0); else MSG_WriteByte (&buf, j); MSG_WriteByte (&buf, ent->frame); MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, ent->skinnum); for (j=0 ; j<3 ; j++) { MSG_WriteCoord (&buf, ent->origin[j]); MSG_WriteAngle (&buf, ent->angles[j]); } if (buf.cursize > MAX_MSGLEN/2) { CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } } // spawnstaticsound // static sounds are skipped in demos, life is hard // baselines memset(&blankes, 0, sizeof(blankes)); for (i = 0; i < MAX_EDICTS; i++) { es = cl_baselines + i; if (memcmp(es, &blankes, sizeof(blankes))) { MSG_WriteByte (&buf,svc_spawnbaseline); MSG_WriteShort (&buf, i); MSG_WriteByte (&buf, es->modelindex); MSG_WriteByte (&buf, es->frame); MSG_WriteByte (&buf, es->colormap); MSG_WriteByte (&buf, es->skinnum); for (j=0 ; j<3 ; j++) { MSG_WriteCoord(&buf, es->origin[j]); MSG_WriteAngle(&buf, es->angles[j]); } if (buf.cursize > MAX_MSGLEN/2) { CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } } } MSG_WriteByte (&buf, svc_stufftext); MSG_WriteString (&buf, va("cmd spawn %i 0\n", cl.servercount) ); if (buf.cursize) { CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } // send current status of all other players for (i = 0; i < MAX_CLIENTS; i++) { player = cl.players + i; MSG_WriteByte (&buf, svc_updatefrags); MSG_WriteByte (&buf, i); MSG_WriteShort (&buf, player->frags); MSG_WriteByte (&buf, svc_updateping); MSG_WriteByte (&buf, i); MSG_WriteShort (&buf, player->ping); MSG_WriteByte (&buf, svc_updatepl); MSG_WriteByte (&buf, i); MSG_WriteByte (&buf, player->pl); MSG_WriteByte (&buf, svc_updateentertime); MSG_WriteByte (&buf, i); MSG_WriteFloat (&buf, player->entertime); MSG_WriteByte (&buf, svc_updateuserinfo); MSG_WriteByte (&buf, i); MSG_WriteLong (&buf, player->userid); MSG_WriteString (&buf, player->userinfo); if (buf.cursize > MAX_MSGLEN/2) { CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } } // send all current light styles for (i=0 ; i<MAX_LIGHTSTYLES ; i++) { MSG_WriteByte (&buf, svc_lightstyle); MSG_WriteByte (&buf, (char)i); MSG_WriteString (&buf, cl_lightstyle[i].map); } for (i = 0; i < MAX_CL_STATS; i++) { MSG_WriteByte (&buf, svc_updatestatlong); MSG_WriteByte (&buf, i); MSG_WriteLong (&buf, cl.stats[i]); if (buf.cursize > MAX_MSGLEN/2) { CL_WriteRecordDemoMessage (&buf, seq++); SZ_Clear (&buf); } } #if 0 MSG_WriteByte (&buf, svc_updatestatlong); MSG_WriteByte (&buf, STAT_TOTALMONSTERS); MSG_WriteLong (&buf, cl.stats[STAT_TOTALMONSTERS]); MSG_WriteByte (&buf, svc_updatestatlong); MSG_WriteByte (&buf, STAT_SECRETS); MSG_WriteLong (&buf, cl.stats[STAT_SECRETS]); MSG_WriteByte (&buf, svc_updatestatlong); MSG_WriteByte (&buf, STAT_MONSTERS); MSG_WriteLong (&buf, cl.stats[STAT_MONSTERS]); #endif // get the client to check and download skins // when that is completed, a begin command will be issued MSG_WriteByte (&buf, svc_stufftext); MSG_WriteString (&buf, va("skins\n") ); CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteSetDemoMessage(); // done }