// // CL_RequestDownload // please sir, can i have some more? // void CL_RequestDownload(std::string filename, std::string filehash) { // [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(); } }
// // P_PreservePlayer // void P_PreservePlayer(player_t &player) { if (!serverside || sv_gametype != GM_COOP || !validplayer(player) || !player.ingame()) return; if(!unnatural_level_progression) player.playerstate = PST_LIVE; // denis - carry weapons and keys over to next level G_DoReborn(player); // inform client { size_t i; client_t *cl = &player.client; MSG_WriteMarker (&cl->reliablebuf, svc_playerinfo); for(i = 0; i < NUMWEAPONS; i++) MSG_WriteByte (&cl->reliablebuf, player.weaponowned[i]); for(i = 0; i < NUMAMMO; i++) { MSG_WriteShort (&cl->reliablebuf, player.maxammo[i]); MSG_WriteShort (&cl->reliablebuf, player.ammo[i]); } MSG_WriteByte (&cl->reliablebuf, player.health); MSG_WriteByte (&cl->reliablebuf, player.armorpoints); MSG_WriteByte (&cl->reliablebuf, player.armortype); MSG_WriteByte (&cl->reliablebuf, player.readyweapon); MSG_WriteByte (&cl->reliablebuf, player.backpack); } }
// // [Toke - CTF] SV_CTFEvent // Sends CTF events to player // void SV_CTFEvent (flag_t f, flag_score_t event, player_t &who) { if(event == SCORE_NONE) return; if(validplayer(who)) who.points += ctf_points[event]; for (size_t i = 0; i < players.size(); ++i) { if (!players[i].ingame()) continue; client_t *cl = &players[i].client; MSG_WriteMarker (&cl->reliablebuf, svc_ctfevent); MSG_WriteByte (&cl->reliablebuf, event); MSG_WriteByte (&cl->reliablebuf, f); if(validplayer(who)) { MSG_WriteByte (&cl->reliablebuf, who.id); MSG_WriteLong (&cl->reliablebuf, who.points); } else { MSG_WriteByte (&cl->reliablebuf, 0); MSG_WriteLong (&cl->reliablebuf, 0); } for(size_t j = 0; j < NUMFLAGS; j++) MSG_WriteLong (&cl->reliablebuf, TEAMpoints[j]); } }
// Broadcast warmup state to client. void SV_SendWarmupState(player_t &player, Warmup::status_t status, short count = 0) { client_t* cl = &player.client; MSG_WriteMarker(&cl->reliablebuf, svc_warmupstate); MSG_WriteByte(&cl->reliablebuf, static_cast<byte>(status)); if (status == Warmup::COUNTDOWN || status == Warmup::FORCE_COUNTDOWN) MSG_WriteShort(&cl->reliablebuf, count); }
// // P_ExplodeMissile // void P_ExplodeMissile (AActor* mo) { for (size_t i = 0; i < players.size(); i++) { client_t *cl = &clients[i]; if(!SV_IsPlayerAllowedToSee(players[i], mo)) continue; MSG_WriteMarker (&cl->reliablebuf, svc_movemobj); MSG_WriteShort (&cl->reliablebuf, mo->netid); MSG_WriteByte (&cl->reliablebuf, mo->rndindex); MSG_WriteLong (&cl->reliablebuf, mo->x); MSG_WriteLong (&cl->reliablebuf, mo->y); MSG_WriteLong (&cl->reliablebuf, mo->z); MSG_WriteMarker(&cl->reliablebuf, svc_explodemissile); MSG_WriteShort(&cl->reliablebuf, mo->netid); } mo->momx = mo->momy = mo->momz = 0; P_SetMobjState (mo, mobjinfo[mo->type].deathstate); if (mobjinfo[mo->type].deathstate != S_NULL) { // [RH] If the object is already translucent, don't change it. // Otherwise, make it 66% translucent. if (mo->translucency == FRACUNIT) mo->translucency = TRANSLUC66; mo->tics -= P_Random (mo) & 3; if (mo->tics < 1) mo->tics = 1; mo->flags &= ~MF_MISSILE; if (mo->info->deathsound) S_Sound (mo, CHAN_VOICE, mo->info->deathsound, 1, ATTN_NORM); mo->effects = 0; // [RH] } }
// // SV_AcknowledgePacket // void SV_AcknowledgePacket(player_t &player) { client_t *cl = &player.client; int sequence = MSG_ReadLong(); cl->compressor.packet_acked(sequence); // packet is missed if (sequence - cl->last_sequence > 1) { // resend for (int seq = cl->last_sequence+1; seq < sequence; seq++) { int n; bool needfullupdate = true; for (n=0; n<256; n++) if (cl->packetseq[n] == seq) { needfullupdate = false; break; } if (needfullupdate) { // do full update Printf(PRINT_HIGH, "need full update\n"); cl->last_sequence = sequence; return; } MSG_WriteMarker(&cl->reliablebuf, svc_missedpacket); MSG_WriteLong(&cl->reliablebuf, seq); MSG_WriteShort(&cl->reliablebuf, cl->packetsize[n]); if (cl->packetsize[n]) SZ_Write (&cl->reliablebuf, cl->relpackets.data, cl->packetbegin[n], cl->packetsize[n]); if (cl->reliablebuf.overflowed) { // do full update Printf(PRINT_HIGH, "reliablebuf overflowed, need full update\n"); cl->last_sequence = sequence; return; } if (cl->reliablebuf.cursize > 600) SV_SendPacket(player); } } cl->last_sequence = sequence; }
// Checks if we need to ask the server for a re-request of the current download // chunk void CL_DownloadTicker() { dtime_t diff = 0; if(gamestate != GS_DOWNLOAD || download.filename.empty()) { return; } if (download.timeout) { // Calculate how many seconds have elapsed since the last server // response diff = I_GetTime() - download.timeout; if (diff) diff /= I_ConvertTimeFromMs(1000); } else { download.timeout = I_GetTime(); return; } if (diff >= 3) { DPrintf("No response from server for %d seconds, re-requesting\n", diff); MSG_WriteMarker(&net_buffer, clc_wantwad); MSG_WriteString(&net_buffer, download.filename.c_str()); MSG_WriteString(&net_buffer, download.md5.c_str()); MSG_WriteLong(&net_buffer, download.got_bytes); NET_SendPacket(net_buffer, serveraddr); download.timeout = 0; ++download.retrycount; } if (download.retrycount >= 5) { Printf(PRINT_HIGH, "Server hasn't responded to download re-requests, aborting\n"); download.retrycount = 0; download.timeout = 0; CL_QuitNetGame(); gamestate = GS_STARTUP; } }
// // CTF_Connect // Send states of all flags to new player // void CTF_Connect(player_t &player) { client_t *cl = &player.client; MSG_WriteMarker (&cl->reliablebuf, svc_ctfevent); MSG_WriteByte (&cl->reliablebuf, SCORE_NONE); for(size_t i = 0; i < NUMFLAGS; i++) { MSG_WriteByte (&cl->reliablebuf, CTFdata[i].state); MSG_WriteByte (&cl->reliablebuf, CTFdata[i].flagger); } // send team scores to the client SV_CTFEvent ((flag_t)0, SCORE_REFRESH, player); }
int VPrintf (int printlevel, const char *format, va_list parms) { char outline[8192]; if (gameisdead) return 0; vsprintf (outline, format, parms); // denis - 0x07 is a system beep, which can DoS the console (lol) size_t len = strlen(outline); size_t i; for(i = 0; i < len; i++) if(outline[i] == 0x07) outline[i] = '.'; std::string str(TimeStamp()); str.append(" "); str.append(outline); if(str[str.length()-1] != '\n') str += '\n'; // send to any rcon players client_t *cl; for (i = 0; i < players.size(); i++) { cl = &clients[i]; if(!clients[i].allow_rcon) continue; MSG_WriteMarker (&cl->reliablebuf, svc_print); MSG_WriteByte (&cl->reliablebuf, PRINT_MEDIUM); MSG_WriteString (&cl->reliablebuf, (char *)str.c_str()); } if (LOG.is_open()) { LOG << str; LOG.flush(); } return PrintString (printlevel, str.c_str()); }
// // 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); }
// Respond to keyboard input events, intercept cheats. // [RH] Cheats eatkey the last keypress used to trigger them bool ST_Responder (event_t *ev) { player_t *plyr = &consoleplayer(); bool eatkey = false; int i; // Filter automap on/off. if (ev->type == ev_keyup && ((ev->data1 & 0xffff0000) == AM_MSGHEADER)) { switch(ev->data1) { case AM_MSGENTERED: st_gamestate = AutomapState; st_firsttime = true; break; case AM_MSGEXITED: st_gamestate = FirstPersonState; break; } } // if a user keypress... else if (ev->type == ev_keydown) { // 'dqd' cheat for toggleable god mode if (cht_CheckCheat(&cheat_god, (char)ev->data2)) { if (CheckCheatmode ()) return false; // [Russell] - give full health plyr->mo->health = deh.StartHealth; plyr->health = deh.StartHealth; AddCommandString("god"); // Net_WriteByte (DEM_GENERICCHEAT); // Net_WriteByte (CHT_IDDQD); eatkey = true; } // 'fa' cheat for killer f*****g arsenal else if (cht_CheckCheat(&cheat_ammonokey, (char)ev->data2)) { if (CheckCheatmode ()) return false; Printf(PRINT_HIGH, "Ammo (No keys) Added\n"); plyr->armorpoints = deh.FAArmor; plyr->armortype = deh.FAAC; weapontype_t pendweap = plyr->pendingweapon; for (i = 0; i<NUMWEAPONS; i++) P_GiveWeapon (plyr, (weapontype_t)i, false); plyr->pendingweapon = pendweap; for (i=0; i<NUMAMMO; i++) plyr->ammo[i] = plyr->maxammo[i]; MSG_WriteMarker(&net_buffer, clc_cheatpulse); MSG_WriteByte(&net_buffer, 1); eatkey = true; } // 'kfa' cheat for key full ammo else if (cht_CheckCheat(&cheat_ammo, (char)ev->data2)) { if (CheckCheatmode ()) return false; Printf(PRINT_HIGH, "Very Happy Ammo Added\n"); plyr->armorpoints = deh.KFAArmor; plyr->armortype = deh.KFAAC; weapontype_t pendweap = plyr->pendingweapon; for (i = 0; i<NUMWEAPONS; i++) P_GiveWeapon (plyr, (weapontype_t)i, false); plyr->pendingweapon = pendweap; for (i=0; i<NUMAMMO; i++) plyr->ammo[i] = plyr->maxammo[i]; for (i=0; i<NUMCARDS; i++) plyr->cards[i] = true; MSG_WriteMarker(&net_buffer, clc_cheatpulse); MSG_WriteByte(&net_buffer, 2); eatkey = true; } // [Russell] - Only doom 1/registered can have idspispopd and // doom 2/final can have idclip else if (cht_CheckCheat(&cheat_noclip, (char)ev->data2)) { if (CheckCheatmode ()) return false; if ((gamemode != shareware) && (gamemode != registered) && (gamemode != retail)) return false; AddCommandString("noclip"); // Net_WriteByte (DEM_GENERICCHEAT); // Net_WriteByte (CHT_NOCLIP); eatkey = true; } else if (cht_CheckCheat(&cheat_commercial_noclip, (char)ev->data2)) { if (CheckCheatmode ()) return false; if (gamemode != commercial) return false; AddCommandString("noclip"); // Net_WriteByte (DEM_GENERICCHEAT); // Net_WriteByte (CHT_NOCLIP); eatkey = true; } // 'behold?' power-up cheats for (i=0; i<6; i++) { if (cht_CheckCheat(&cheat_powerup[i], (char)ev->data2)) { if (CheckCheatmode ()) return false; Printf(PRINT_HIGH, "Power-up toggled\n"); if (!plyr->powers[i]) P_GivePower( plyr, i); else if (i!=pw_strength) plyr->powers[i] = 1; else plyr->powers[i] = 0; MSG_WriteMarker(&net_buffer, clc_cheatpulse); MSG_WriteByte(&net_buffer, 3); MSG_WriteByte(&net_buffer, (byte)i); eatkey = true; } } // 'behold' power-up menu if (cht_CheckCheat(&cheat_powerup[6], (char)ev->data2)) { if (CheckCheatmode ()) return false; Printf (PRINT_HIGH, "%s\n", STSTR_BEHOLD); } // 'choppers' invulnerability & chainsaw else if (cht_CheckCheat(&cheat_choppers, (char)ev->data2)) { if (CheckCheatmode ()) return false; Printf(PRINT_HIGH, "... Doesn't suck - GM\n"); plyr->weaponowned[wp_chainsaw] = true; MSG_WriteMarker(&net_buffer, clc_cheatpulse); MSG_WriteByte(&net_buffer, 4); eatkey = true; } // 'clev' change-level cheat else if (cht_CheckCheat(&cheat_clev, (char)ev->data2)) { if (CheckCheatmode ()) return false; char buf[16]; //char *bb; cht_GetParam(&cheat_clev, buf); buf[2] = 0; // [ML] Chex mode: always set the episode number to 1. // FIXME: This is probably a horrible hack, it sure looks like one at least if (gamemode == retail_chex) sprintf(buf,"1%c",buf[1]); sprintf (buf + 3, "map %s\n", buf); AddCommandString (buf + 3); eatkey = true; } // 'mypos' for player position else if (cht_CheckCheat(&cheat_mypos, (char)ev->data2)) { AddCommandString ("toggle idmypos"); eatkey = true; } // 'idmus' change-music cheat else if (cht_CheckCheat(&cheat_mus, (char)ev->data2)) { char buf[16]; cht_GetParam(&cheat_mus, buf); buf[2] = 0; sprintf (buf + 3, "idmus %s\n", buf); AddCommandString (buf + 3); eatkey = true; } } return eatkey; }
void G_Ticker (void) { int buf; gamestate_t oldgamestate; size_t i; // Run client tics; CL_RunTics (); // do player reborns if needed if(serverside) for (i = 0; i < players.size(); i++) if (players[i].ingame() && players[i].playerstate == PST_REBORN) G_DoReborn (players[i]); // do things to change the game state oldgamestate = gamestate; while (gameaction != ga_nothing) { switch (gameaction) { case ga_loadlevel: G_DoLoadLevel (-1); break; case ga_newgame: G_DoNewGame (); break; case ga_loadgame: gameaction = ga_nothing; break; case ga_savegame: gameaction = ga_nothing; break; case ga_playdemo: G_DoPlayDemo (); break; case ga_completed: G_DoCompleted (); break; case ga_victory: gameaction = ga_nothing; break; case ga_worlddone: G_DoWorldDone (); break; case ga_screenshot: I_ScreenShot(shotfile.c_str()); gameaction = ga_nothing; break; case ga_fullconsole: C_FullConsole (); gameaction = ga_nothing; break; case ga_nothing: break; } C_AdjustBottom (); } // get commands buf = gametic%BACKUPTICS; memcpy (&consoleplayer().cmd, &consoleplayer().netcmds[buf], sizeof(ticcmd_t)); static int realrate = 0; int packet_size; if (demoplayback) G_ReadDemoTiccmd(); // play all player commands if (demorecording) G_WriteDemoTiccmd(); // read in all player commands if (connected) { while ((packet_size = NET_GetPacket()) ) { // denis - don't accept candy from strangers if(!NET_CompareAdr(serveraddr, net_from)) break; realrate += packet_size; last_received = gametic; noservermsgs = false; CL_ReadPacketHeader(); CL_ParseCommands(); if (gameaction == ga_fullconsole) // Host_EndGame was called return; } if (!(gametic%TICRATE)) { netin = realrate; realrate = 0; } if (!noservermsgs) CL_SendCmd(); // send console commands to the server CL_SaveCmd(); // save console commands if (!(gametic%TICRATE)) { netout = outrate; outrate = 0; } if (gametic - last_received > 65) noservermsgs = true; } else if (NET_GetPacket() ) { // denis - don't accept candy from strangers if((gamestate == GS_DOWNLOAD || gamestate == GS_CONNECTING) && NET_CompareAdr(serveraddr, net_from)) { int type = MSG_ReadLong(); if(type == CHALLENGE) { CL_PrepareConnect(); } else if(type == 0) { if (!CL_Connect()) memset (&serveraddr, 0, sizeof(serveraddr)); connecttimeout = 0; } else { // we are already connected to this server, quit first MSG_WriteMarker(&net_buffer, clc_disconnect); NET_SendPacket(net_buffer, serveraddr); } } } // check for special buttons if(serverside && consoleplayer().ingame()) { player_t &player = consoleplayer(); if (player.cmd.ucmd.buttons & BT_SPECIAL) { switch (player.cmd.ucmd.buttons & BT_SPECIALMASK) { case BTS_PAUSE: paused ^= 1; if (paused) S_PauseSound (); else S_ResumeSound (); break; case BTS_SAVEGAME: if (!savedescription[0]) strcpy (savedescription, "NET GAME"); savegameslot = (player.cmd.ucmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT; gameaction = ga_savegame; break; } } }
// // G_BuildTiccmd // Builds a ticcmd from all of the available inputs // or reads it from the demo buffer. // If recording a demo, write it out // void G_BuildTiccmd (ticcmd_t *cmd) { int strafe; int speed; int tspeed; int forward; int side; int look; int fly; ticcmd_t *base; base = I_BaseTiccmd (); // empty, or external driver memcpy (cmd,base,sizeof(*cmd)); strafe = Actions[ACTION_STRAFE]; speed = Actions[ACTION_SPEED]; if (cl_run) speed ^= 1; forward = side = look = fly = 0; // GhostlyDeath -- USE takes us out of spectator mode if ((&consoleplayer())->spectator && Actions[ACTION_USE] && connected) { MSG_WriteMarker(&net_buffer, clc_spectate); MSG_WriteByte(&net_buffer, false); } // [RH] only use two stage accelerative turning on the keyboard // and not the joystick, since we treat the joystick as // the analog device it is. if ((Actions[ACTION_LEFT]) || (Actions[ACTION_RIGHT])) turnheld += 1; else turnheld = 0; if (turnheld < SLOWTURNTICS) tspeed = 2; // slow turn else tspeed = speed; // let movement keys cancel each other out if (strafe) { if (Actions[ACTION_RIGHT]) side += sidemove[speed]; if (Actions[ACTION_LEFT]) side -= sidemove[speed]; } else { if (Actions[ACTION_RIGHT]) cmd->ucmd.yaw -= angleturn[tspeed]; if (Actions[ACTION_LEFT]) cmd->ucmd.yaw += angleturn[tspeed]; } if (Actions[ACTION_LOOKUP]) look += lookspeed[speed]; if (Actions[ACTION_LOOKDOWN]) look -= lookspeed[speed]; if (Actions[ACTION_MOVEUP]) fly += flyspeed[speed]; if (Actions[ACTION_MOVEDOWN]) fly -= flyspeed[speed]; if (Actions[ACTION_KLOOK]) { if (Actions[ACTION_FORWARD]) look += lookspeed[speed]; if (Actions[ACTION_BACK]) look -= lookspeed[speed]; } else { if (Actions[ACTION_FORWARD]) forward += forwardmove[speed]; if (Actions[ACTION_BACK]) forward -= forwardmove[speed]; } if (Actions[ACTION_MOVERIGHT]) side += sidemove[speed]; if (Actions[ACTION_MOVELEFT]) side -= sidemove[speed]; // buttons if (Actions[ACTION_ATTACK] && ConsoleState == c_up && !headsupactive) // john - only add attack when console up cmd->ucmd.buttons |= BT_ATTACK; if (Actions[ACTION_USE]) cmd->ucmd.buttons |= BT_USE; if (Actions[ACTION_JUMP]) cmd->ucmd.buttons |= BT_JUMP; // [RH] Handle impulses. If they are between 1 and 7, // they get sent as weapon change events. if (Impulse >= 1 && Impulse <= 7) { cmd->ucmd.buttons |= BT_CHANGE; cmd->ucmd.buttons |= (Impulse - 1) << BT_WEAPONSHIFT; } else { cmd->ucmd.impulse = Impulse; } Impulse = 0; // [RH] Scale joystick moves to full range of allowed speeds if (strafe || lookstrafe) side += (MAXPLMOVE * joyxmove) / 256; else cmd->ucmd.yaw -= (angleturn[1] * joyxmove) / 256; // [RH] Scale joystick moves over full range if (Actions[ACTION_MLOOK]) { if (invertmouse) look -= (joyymove * 32767) / 256; else look += (joyymove * 32767) / 256; } else { forward += (MAXPLMOVE * joyymove) / 256; } if ((Actions[ACTION_MLOOK]) || (cl_mouselook && sv_freelook)) { int val; val = (int)((float)(mousey * 16) * m_pitch); if (invertmouse) look -= val; else look += val; } else { if (novert == 0) // [Toke - Mouse] acts like novert.exe { forward += (int)((float)mousey * m_forward); } } if (sendcenterview) { sendcenterview = false; look = -32768; } else { if (look > 32767) look = 32767; else if (look < -32767) look = -32767; } if (strafe || lookstrafe) side += (int)((float)mousex * m_side); else cmd->ucmd.yaw -= (int)((float)(mousex*0x8) * m_yaw); mousex = mousey = 0; if (forward > MAXPLMOVE) forward = MAXPLMOVE; else if (forward < -MAXPLMOVE) forward = -MAXPLMOVE; if (side > MAXPLMOVE) side = MAXPLMOVE; else if (side < -MAXPLMOVE) side = -MAXPLMOVE; cmd->ucmd.forwardmove += forward; cmd->ucmd.sidemove += side; cmd->ucmd.pitch = look; cmd->ucmd.upmove = fly; // special buttons if (sendpause) { sendpause = false; cmd->ucmd.buttons = BT_SPECIAL | BTS_PAUSE; } if (sendsave) { sendsave = false; cmd->ucmd.buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT); } cmd->ucmd.forwardmove <<= 8; cmd->ucmd.sidemove <<= 8; // [RH] 180-degree turn overrides all other yaws if (turntick) { turntick--; cmd->ucmd.yaw = (ANG180 / TURN180_TICKS) >> 16; } joyxmove = 0; joyymove = 0; }
void G_InitNew (const char *mapname) { size_t i; if (!savegamerestore) G_ClearSnapshots (); // [RH] Mark all levels as not visited if (!savegamerestore) { for (i = 0; i < wadlevelinfos.size(); i++) wadlevelinfos[i].flags &= ~LEVEL_VISITED; for (i = 0; LevelInfos[i].mapname[0]; i++) LevelInfos[i].flags &= ~LEVEL_VISITED; } int old_gametype = sv_gametype.asInt(); cvar_t::UnlatchCVars (); if(old_gametype != sv_gametype || sv_gametype != GM_COOP) { unnatural_level_progression = true; // Nes - Force all players to be spectators when the sv_gametype is not now or previously co-op. for (i = 0; i < players.size(); i++) { // [SL] 2011-07-30 - Don't force downloading players to become spectators // it stops their downloading if (!players[i].ingame()) continue; for (size_t j = 0; j < players.size(); j++) { if (!players[j].ingame()) continue; MSG_WriteMarker (&(players[j].client.reliablebuf), svc_spectate); MSG_WriteByte (&(players[j].client.reliablebuf), players[i].id); MSG_WriteByte (&(players[j].client.reliablebuf), true); } players[i].spectator = true; players[i].playerstate = PST_LIVE; players[i].joinafterspectatortime = -(TICRATE*5); } } // [SL] 2011-09-01 - Change gamestate here so SV_ServerSettingChange will // send changed cvars gamestate = GS_LEVEL; SV_ServerSettingChange(); if (paused) { paused = false; } // [RH] If this map doesn't exist, bomb out if (W_CheckNumForName (mapname) == -1) { I_Error ("Could not find map %s\n", mapname); } if (sv_skill == sk_nightmare || sv_monstersrespawn) respawnmonsters = true; else respawnmonsters = false; bool wantFast = sv_fastmonsters || (sv_skill == sk_nightmare); if (wantFast != isFast) { if (wantFast) { for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) states[i].tics >>= 1; mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT; mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; } else { for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) states[i].tics <<= 1; mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT; mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT; mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; } isFast = wantFast; }
void NetDemo::writeConnectionSequence(buf_t *netbuffer) { // The packet sequence id MSG_WriteLong (netbuffer, 0); // Server sends our player id and digest MSG_WriteMarker (netbuffer, svc_consoleplayer); MSG_WriteByte (netbuffer, consoleplayer().id); MSG_WriteString (netbuffer, digest.c_str()); // our userinfo MSG_WriteMarker (netbuffer, svc_userinfo); MSG_WriteByte (netbuffer, consoleplayer().id); MSG_WriteString (netbuffer, consoleplayer().userinfo.netname.c_str()); MSG_WriteByte (netbuffer, consoleplayer().userinfo.team); MSG_WriteLong (netbuffer, consoleplayer().userinfo.gender); MSG_WriteLong (netbuffer, consoleplayer().userinfo.color); MSG_WriteString (netbuffer, ""); // [SL] place holder for deprecated skins MSG_WriteShort (netbuffer, consoleplayer().GameTime); // Server sends its settings MSG_WriteMarker (netbuffer, svc_serversettings); cvar_t *var = GetFirstCvar(); while (var) { if (var->flags() & CVAR_SERVERINFO) { MSG_WriteByte (netbuffer, 1); MSG_WriteString (netbuffer, var->name()); MSG_WriteString (netbuffer, var->cstring()); } var = var->GetNext(); } MSG_WriteByte (netbuffer, 2); // end of server settings marker // Server tells everyone if we're a spectator MSG_WriteMarker (netbuffer, svc_spectate); MSG_WriteByte (netbuffer, consoleplayer().id); MSG_WriteByte (netbuffer, consoleplayer().spectator); // Server sends wads & map name MSG_WriteMarker (netbuffer, svc_loadmap); // send list of wads (skip over wadnames[0] == odamex.wad) MSG_WriteByte(netbuffer, MIN<size_t>(wadfiles.size() - 1, 255)); for (size_t i = 1; i < MIN<size_t>(wadfiles.size(), 256); i++) { MSG_WriteString(netbuffer, D_CleanseFileName(wadfiles[i], "wad").c_str()); MSG_WriteString(netbuffer, wadhashes[i].c_str()); } // send list of DEH/BEX patches MSG_WriteByte(netbuffer, MIN<size_t>(patchfiles.size(), 255)); for (size_t i = 0; i < MIN<size_t>(patchfiles.size(), 255); i++) { MSG_WriteString(netbuffer, D_CleanseFileName(patchfiles[i]).c_str()); MSG_WriteString(netbuffer, patchfiles[i].c_str()); } MSG_WriteString(netbuffer, level.mapname); // Server spawns the player MSG_WriteMarker (netbuffer, svc_spawnplayer); MSG_WriteByte (netbuffer, consoleplayer().id); if (consoleplayer().mo) { MSG_WriteShort (netbuffer, consoleplayer().mo->netid); MSG_WriteLong (netbuffer, consoleplayer().mo->angle); MSG_WriteLong (netbuffer, consoleplayer().mo->x); MSG_WriteLong (netbuffer, consoleplayer().mo->y); MSG_WriteLong (netbuffer, consoleplayer().mo->z); } else { // The client hasn't yet received his own position from the server // This happens with cl_autorecord // Just fake a position for now MSG_WriteShort (netbuffer, MAXSHORT); MSG_WriteLong (netbuffer, 0); MSG_WriteLong (netbuffer, 0); MSG_WriteLong (netbuffer, 0); MSG_WriteLong (netbuffer, 0); } }
// // CL_Download // denis - get a little chunk of the file and store it, much like a hampster. Well, hamster; but hampsters can dance and sing. Also much like Scraps, the Ice Age squirrel thing, stores his acorn. Only with a bit more success. Actually, quite a bit more success, specifically as in that the world doesn't crack apart when we store our chunk and it does when Scraps stores his (or her?) acorn. But when Scraps does it, it is funnier. The rest of Ice Age mostly sucks. // void CL_Download() { DWORD offset = MSG_ReadLong(); size_t len = MSG_ReadShort(); size_t left = MSG_BytesLeft(); void *p = MSG_ReadChunk(len); if(gamestate != GS_DOWNLOAD) return; if (download.buf == NULL) { // We must have not received the svc_wadinfo message Printf(PRINT_HIGH, "Unable to start download, aborting\n"); download.clear(); CL_QuitNetGame(); return; } // check ranges if(offset + len > download.buf->maxsize() || len > left || p == NULL) { Printf(PRINT_HIGH, "Bad download packet (%d, %d) encountered (%d), aborting\n", (int)offset, (int)left, (int)download.buf->size()); download.clear(); CL_QuitNetGame(); return; } // check for missing packet, re-request if(offset < download.got_bytes || offset > download.got_bytes) { DPrintf("Missed a packet after/before %d bytes (got %d), re-requesting\n", download.got_bytes, offset); MSG_WriteMarker(&net_buffer, clc_wantwad); MSG_WriteString(&net_buffer, download.filename.c_str()); MSG_WriteString(&net_buffer, download.md5.c_str()); MSG_WriteLong(&net_buffer, download.got_bytes); NET_SendPacket(net_buffer, serveraddr); return; } // send keepalive NET_SendPacket(net_buffer, serveraddr); // copy into downloaded buffer memcpy(download.buf->ptr() + offset, p, len); download.got_bytes += len; // calculate percentage for the user static int old_percent = 0; int percent = (download.got_bytes*100)/download.buf->maxsize(); if(percent != old_percent) { SetDownloadPercentage(percent); old_percent = percent; } // 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.got_bytes >= download.buf->maxsize()) { IntDownloadComplete(); } }
bool NetDemo::startRecording(const std::string &filename) { this->filename = filename; if (isPlaying() || isPaused()) { error("Cannot record a netdemo while not connected to a server."); return false; } // Already recording so just ignore the command if (isRecording()) return true; if (demofp != NULL) // file is already open for some reason { fclose(demofp); demofp = NULL; } demofp = fopen(filename.c_str(), "wb"); if (!demofp) { error("Unable to create netdemo file " + filename + "."); return false; } memset(&header, 0, sizeof(header)); // Note: The header is not finalized at this point. Write it anyway to // reserve space in the output file for it and overwrite it later. if (!writeHeader()) { error("Unable to write netdemo header."); return false; } state = NetDemo::st_recording; header.starting_gametic = gametic; Printf(PRINT_HIGH, "Recording netdemo %s.\n", filename.c_str()); if (connected) { // write a simulation of the connection sequence since the server // has already sent it to the client and it wasn't captured static buf_t tempbuf(MAX_UDP_PACKET); // Fake the launcher query response SZ_Clear(&tempbuf); writeLauncherSequence(&tempbuf); capture(&tempbuf); writeMessages(); // Fake the server's side of the connection sequence SZ_Clear(&tempbuf); writeConnectionSequence(&tempbuf); capture(&tempbuf); writeMessages(); // Record any additional messages (usually a full update if auto-recording)) capture(&net_message); writeMessages(); SZ_Clear(&tempbuf); MSG_WriteMarker(&tempbuf, svc_netdemoloadsnap); capture(&tempbuf); writeMessages(); } return true; }
void NetDemo::writeConnectionSequence(buf_t *netbuffer) { // The packet sequence id MSG_WriteLong (netbuffer, 0); // Server sends our player id and digest MSG_WriteMarker (netbuffer, svc_consoleplayer); MSG_WriteByte (netbuffer, consoleplayer().id); MSG_WriteString (netbuffer, digest.c_str()); // our userinfo MSG_WriteMarker (netbuffer, svc_userinfo); MSG_WriteByte (netbuffer, consoleplayer().id); MSG_WriteString (netbuffer, consoleplayer().userinfo.netname); MSG_WriteByte (netbuffer, consoleplayer().userinfo.team); MSG_WriteLong (netbuffer, consoleplayer().userinfo.gender); MSG_WriteLong (netbuffer, consoleplayer().userinfo.color); MSG_WriteString (netbuffer, skins[consoleplayer().userinfo.skin].name); MSG_WriteShort (netbuffer, consoleplayer().GameTime); // Server sends its settings MSG_WriteMarker (netbuffer, svc_serversettings); cvar_t *var = GetFirstCvar(); while (var) { if (var->flags() & CVAR_SERVERINFO) { MSG_WriteByte (netbuffer, 1); MSG_WriteString (netbuffer, var->name()); MSG_WriteString (netbuffer, var->cstring()); } var = var->GetNext(); } MSG_WriteByte (netbuffer, 2); // end of server settings marker // Server tells everyone if we're a spectator MSG_WriteMarker (netbuffer, svc_spectate); MSG_WriteByte (netbuffer, consoleplayer().id); MSG_WriteByte (netbuffer, consoleplayer().spectator); // Server sends map name MSG_WriteMarker (netbuffer, svc_loadmap); MSG_WriteString (netbuffer, level.mapname); // Server spawns the player MSG_WriteMarker (netbuffer, svc_spawnplayer); MSG_WriteByte (netbuffer, consoleplayer().id); if (consoleplayer().mo) { MSG_WriteShort (netbuffer, consoleplayer().mo->netid); MSG_WriteLong (netbuffer, consoleplayer().mo->angle); MSG_WriteLong (netbuffer, consoleplayer().mo->x); MSG_WriteLong (netbuffer, consoleplayer().mo->y); MSG_WriteLong (netbuffer, consoleplayer().mo->z); } else { // The client hasn't yet received his own position from the server // This happens with cl_autorecord // Just fake a position for now MSG_WriteShort (netbuffer, MAXSHORT); MSG_WriteLong (netbuffer, 0); MSG_WriteLong (netbuffer, 0); MSG_WriteLong (netbuffer, 0); MSG_WriteLong (netbuffer, 0); } }