diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f04676162..6b68c4a18 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -83,6 +83,7 @@ char playeraddress[MAXPLAYERS][64]; // The actual timeout will be longer depending on the savegame length tic_t jointimeout = (10*TICRATE); static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame? +static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame? static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout? UINT16 pingmeasurecount = 1; @@ -102,15 +103,8 @@ static tic_t maketic; static INT16 consistancy[BACKUPTICS]; -// Resynching shit! -static UINT32 resynch_score[MAXNETNODES]; // "score" for kicking -- if this gets too high then cfail kick -static UINT16 resynch_delay[MAXNETNODES]; // delay time before the player can be considered to have desynched -static UINT32 resynch_status[MAXNETNODES]; // 0 bit means synched for that player, 1 means possibly desynched -static UINT8 resynch_sent[MAXNETNODES][MAXPLAYERS]; // what synch packets have we attempted to send to the player -static UINT8 resynch_inprogress[MAXNETNODES]; -static UINT8 resynch_local_inprogress = false; // WE are desynched and getting packets to fix it. static UINT8 player_joining = false; -UINT8 hu_resynching = 0; +UINT8 hu_redownloadinggamestate = 0; UINT8 adminpassmd5[16]; boolean adminpasswordset = false; @@ -504,597 +498,6 @@ void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) // end extra data function for lmps // ----------------------------------------------------------------- -// ----------------------------------------------------------------- -// resynch player data -// ----------------------------------------------------------------- -static inline void resynch_write_player(resynch_pak *rsp, const size_t i) -{ - size_t j; - - rsp->playernum = (UINT8)i; - - // Do not send anything visual related. - // Only send data that we need to know for physics. - rsp->playerstate = (UINT8)players[i].playerstate; //playerstate_t - rsp->pflags = (UINT32)LONG(players[i].pflags); //pflags_t - rsp->panim = (UINT8)players[i].panim; //panim_t - - rsp->aiming = (angle_t)LONG(players[i].aiming); - rsp->currentweapon = LONG(players[i].currentweapon); - rsp->ringweapons = LONG(players[i].ringweapons); - - rsp->ammoremoval = (UINT16)SHORT(players[i].ammoremoval); - rsp->ammoremovaltimer = (tic_t)LONG(players[i].ammoremovaltimer); - rsp->ammoremovalweapon = LONG(players[i].ammoremovalweapon); - - for (j = 0; j < NUMPOWERS; ++j) - rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]); - - // Score is resynched in the rspfirm resync packet - rsp->rings = SHORT(players[i].rings); - rsp->spheres = SHORT(players[i].spheres); - rsp->lives = players[i].lives; - rsp->continues = players[i].continues; - rsp->scoreadd = players[i].scoreadd; - rsp->xtralife = players[i].xtralife; - rsp->pity = players[i].pity; - - rsp->skincolor = players[i].skincolor; - rsp->skin = LONG(players[i].skin); - rsp->availabilities = LONG(players[i].availabilities); - // Just in case Lua does something like - // modify these at runtime - rsp->camerascale = (fixed_t)LONG(players[i].camerascale); - rsp->shieldscale = (fixed_t)LONG(players[i].shieldscale); - rsp->normalspeed = (fixed_t)LONG(players[i].normalspeed); - rsp->runspeed = (fixed_t)LONG(players[i].runspeed); - rsp->thrustfactor = players[i].thrustfactor; - rsp->accelstart = players[i].accelstart; - rsp->acceleration = players[i].acceleration; - rsp->charability = players[i].charability; - rsp->charability2 = players[i].charability2; - rsp->charflags = (UINT32)LONG(players[i].charflags); - rsp->thokitem = (UINT32)LONG(players[i].thokitem); //mobjtype_t - rsp->spinitem = (UINT32)LONG(players[i].spinitem); //mobjtype_t - rsp->revitem = (UINT32)LONG(players[i].revitem); //mobjtype_t - rsp->followitem = (UINT32)LONG(players[i].followitem); //mobjtype_t - rsp->actionspd = (fixed_t)LONG(players[i].actionspd); - rsp->mindash = (fixed_t)LONG(players[i].mindash); - rsp->maxdash = (fixed_t)LONG(players[i].maxdash); - rsp->jumpfactor = (fixed_t)LONG(players[i].jumpfactor); - rsp->playerheight = (fixed_t)LONG(players[i].height); - rsp->playerspinheight = (fixed_t)LONG(players[i].spinheight); - - rsp->speed = (fixed_t)LONG(players[i].speed); - rsp->secondjump = players[i].secondjump; - rsp->fly1 = players[i].fly1; - rsp->glidetime = (tic_t)LONG(players[i].glidetime); - rsp->climbing = players[i].climbing; - rsp->deadtimer = players[i].deadtimer; - rsp->exiting = (tic_t)LONG(players[i].exiting); - rsp->homing = players[i].homing; - rsp->dashmode = (tic_t)LONG(players[i].dashmode); - rsp->skidtime = (tic_t)LONG(players[i].skidtime); - rsp->cmomx = (fixed_t)LONG(players[i].cmomx); - rsp->cmomy = (fixed_t)LONG(players[i].cmomy); - rsp->rmomx = (fixed_t)LONG(players[i].rmomx); - rsp->rmomy = (fixed_t)LONG(players[i].rmomy); - - rsp->weapondelay = LONG(players[i].weapondelay); - rsp->tossdelay = LONG(players[i].tossdelay); - - rsp->starpostx = SHORT(players[i].starpostx); - rsp->starposty = SHORT(players[i].starposty); - rsp->starpostz = SHORT(players[i].starpostz); - rsp->starpostnum = LONG(players[i].starpostnum); - rsp->starposttime = (tic_t)LONG(players[i].starposttime); - rsp->starpostangle = (angle_t)LONG(players[i].starpostangle); - rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale); - - rsp->maxlink = LONG(players[i].maxlink); - rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed); - rsp->angle_pos = (angle_t)LONG(players[i].angle_pos); - rsp->old_angle_pos = (angle_t)LONG(players[i].old_angle_pos); - rsp->bumpertime = (tic_t)LONG(players[i].bumpertime); - rsp->flyangle = LONG(players[i].flyangle); - rsp->drilltimer = (tic_t)LONG(players[i].drilltimer); - rsp->linkcount = LONG(players[i].linkcount); - rsp->linktimer = (tic_t)LONG(players[i].linktimer); - rsp->anotherflyangle = LONG(players[i].anotherflyangle); - rsp->nightstime = (tic_t)LONG(players[i].nightstime); - rsp->drillmeter = LONG(players[i].drillmeter); - rsp->drilldelay = players[i].drilldelay; - rsp->bonustime = players[i].bonustime; - rsp->mare = players[i].mare; - rsp->lastsidehit = SHORT(players[i].lastsidehit); - rsp->lastlinehit = SHORT(players[i].lastlinehit); - - rsp->losstime = (tic_t)LONG(players[i].losstime); - rsp->timeshit = players[i].timeshit; - rsp->onconveyor = LONG(players[i].onconveyor); - - rsp->hasmo = false; - //Transfer important mo information if the player has a body. - //This lets us resync players even if they are dead. - if (!players[i].mo) - return; - rsp->hasmo = true; - - rsp->health = LONG(players[i].mo->health); - rsp->angle = (angle_t)LONG(players[i].mo->angle); - rsp->rollangle = (angle_t)LONG(players[i].mo->rollangle); - rsp->x = LONG(players[i].mo->x); - rsp->y = LONG(players[i].mo->y); - rsp->z = LONG(players[i].mo->z); - rsp->momx = LONG(players[i].mo->momx); - rsp->momy = LONG(players[i].mo->momy); - rsp->momz = LONG(players[i].mo->momz); - rsp->friction = LONG(players[i].mo->friction); - rsp->movefactor = LONG(players[i].mo->movefactor); - - rsp->sprite = (spritenum_t)LONG(players[i].mo->sprite); - rsp->frame = LONG(players[i].mo->frame); - rsp->sprite2 = players[i].mo->sprite2; - rsp->anim_duration = SHORT(players[i].mo->anim_duration); - rsp->tics = LONG(players[i].mo->tics); - rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( - rsp->eflags = (UINT16)SHORT(players[i].mo->eflags); - rsp->flags = LONG(players[i].mo->flags); - rsp->flags2 = LONG(players[i].mo->flags2); - - rsp->radius = LONG(players[i].mo->radius); - rsp->height = LONG(players[i].mo->height); - rsp->scale = LONG(players[i].mo->scale); - rsp->destscale = LONG(players[i].mo->destscale); - rsp->scalespeed = LONG(players[i].mo->scalespeed); -} - -static void resynch_read_player(resynch_pak *rsp) -{ - INT32 i = rsp->playernum, j; - mobj_t *savedmo = players[i].mo; - - // Do not send anything visual related. - // Only send data that we need to know for physics. - players[i].playerstate = (UINT8)rsp->playerstate; //playerstate_t - players[i].pflags = (UINT32)LONG(rsp->pflags); //pflags_t - players[i].panim = (UINT8)rsp->panim; //panim_t - - players[i].aiming = (angle_t)LONG(rsp->aiming); - players[i].currentweapon = LONG(rsp->currentweapon); - players[i].ringweapons = LONG(rsp->ringweapons); - - players[i].ammoremoval = (UINT16)SHORT(rsp->ammoremoval); - players[i].ammoremovaltimer = (tic_t)LONG(rsp->ammoremovaltimer); - players[i].ammoremovalweapon = LONG(rsp->ammoremovalweapon); - - for (j = 0; j < NUMPOWERS; ++j) - players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]); - - // Score is resynched in the rspfirm resync packet - players[i].rings = SHORT(rsp->rings); - players[i].spheres = SHORT(rsp->spheres); - players[i].lives = rsp->lives; - players[i].continues = rsp->continues; - players[i].scoreadd = rsp->scoreadd; - players[i].xtralife = rsp->xtralife; - players[i].pity = rsp->pity; - - players[i].skincolor = rsp->skincolor; - players[i].skin = LONG(rsp->skin); - players[i].availabilities = LONG(rsp->availabilities); - // Just in case Lua does something like - // modify these at runtime - players[i].camerascale = (fixed_t)LONG(rsp->camerascale); - players[i].shieldscale = (fixed_t)LONG(rsp->shieldscale); - players[i].normalspeed = (fixed_t)LONG(rsp->normalspeed); - players[i].runspeed = (fixed_t)LONG(rsp->runspeed); - players[i].thrustfactor = rsp->thrustfactor; - players[i].accelstart = rsp->accelstart; - players[i].acceleration = rsp->acceleration; - players[i].charability = rsp->charability; - players[i].charability2 = rsp->charability2; - players[i].charflags = (UINT32)LONG(rsp->charflags); - players[i].thokitem = (UINT32)LONG(rsp->thokitem); //mobjtype_t - players[i].spinitem = (UINT32)LONG(rsp->spinitem); //mobjtype_t - players[i].revitem = (UINT32)LONG(rsp->revitem); //mobjtype_t - players[i].followitem = (UINT32)LONG(rsp->followitem); //mobjtype_t - players[i].actionspd = (fixed_t)LONG(rsp->actionspd); - players[i].mindash = (fixed_t)LONG(rsp->mindash); - players[i].maxdash = (fixed_t)LONG(rsp->maxdash); - players[i].jumpfactor = (fixed_t)LONG(rsp->jumpfactor); - players[i].height = (fixed_t)LONG(rsp->playerheight); - players[i].spinheight = (fixed_t)LONG(rsp->playerspinheight); - - players[i].speed = (fixed_t)LONG(rsp->speed); - players[i].secondjump = rsp->secondjump; - players[i].fly1 = rsp->fly1; - players[i].glidetime = (tic_t)LONG(rsp->glidetime); - players[i].climbing = rsp->climbing; - players[i].deadtimer = rsp->deadtimer; - players[i].exiting = (tic_t)LONG(rsp->exiting); - players[i].homing = rsp->homing; - players[i].dashmode = (tic_t)LONG(rsp->dashmode); - players[i].skidtime = (tic_t)LONG(rsp->skidtime); - players[i].cmomx = (fixed_t)LONG(rsp->cmomx); - players[i].cmomy = (fixed_t)LONG(rsp->cmomy); - players[i].rmomx = (fixed_t)LONG(rsp->rmomx); - players[i].rmomy = (fixed_t)LONG(rsp->rmomy); - - players[i].weapondelay = LONG(rsp->weapondelay); - players[i].tossdelay = LONG(rsp->tossdelay); - - players[i].starpostx = SHORT(rsp->starpostx); - players[i].starposty = SHORT(rsp->starposty); - players[i].starpostz = SHORT(rsp->starpostz); - players[i].starpostnum = LONG(rsp->starpostnum); - players[i].starposttime = (tic_t)LONG(rsp->starposttime); - players[i].starpostangle = (angle_t)LONG(rsp->starpostangle); - players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale); - - players[i].maxlink = LONG(rsp->maxlink); - players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed); - players[i].angle_pos = (angle_t)LONG(rsp->angle_pos); - players[i].old_angle_pos = (angle_t)LONG(rsp->old_angle_pos); - players[i].bumpertime = (tic_t)LONG(rsp->bumpertime); - players[i].flyangle = LONG(rsp->flyangle); - players[i].drilltimer = (tic_t)LONG(rsp->drilltimer); - players[i].linkcount = LONG(rsp->linkcount); - players[i].linktimer = (tic_t)LONG(rsp->linktimer); - players[i].anotherflyangle = LONG(rsp->anotherflyangle); - players[i].nightstime = (tic_t)LONG(rsp->nightstime); - players[i].drillmeter = LONG(rsp->drillmeter); - players[i].drilldelay = rsp->drilldelay; - players[i].bonustime = rsp->bonustime; - players[i].mare = rsp->mare; - players[i].lastsidehit = SHORT(rsp->lastsidehit); - players[i].lastlinehit = SHORT(rsp->lastlinehit); - - players[i].losstime = (tic_t)LONG(rsp->losstime); - players[i].timeshit = rsp->timeshit; - players[i].onconveyor = LONG(rsp->onconveyor); - - //We get a packet for each player in game. - if (!playeringame[i]) - return; - - //...but keep old mo even if it is corrupt or null! - players[i].mo = savedmo; - - //Transfer important mo information if they have a valid mo. - if (!rsp->hasmo) - return; - - //server thinks player has a body. - //Give them a new body that can be then manipulated by the server's info. - if (!players[i].mo) //client thinks it has no body. - P_SpawnPlayer(i); - - //At this point, the player should have a body, whether they were respawned or not. - P_UnsetThingPosition(players[i].mo); - players[i].mo->angle = (angle_t)LONG(rsp->angle); - players[i].mo->rollangle = (angle_t)LONG(rsp->rollangle); - players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); - players[i].mo->flags = LONG(rsp->flags); - players[i].mo->flags2 = LONG(rsp->flags2); - players[i].mo->friction = LONG(rsp->friction); - players[i].mo->health = LONG(rsp->health); - players[i].mo->momx = LONG(rsp->momx); - players[i].mo->momy = LONG(rsp->momy); - players[i].mo->momz = LONG(rsp->momz); - players[i].mo->movefactor = LONG(rsp->movefactor); - - // Don't use P_SetMobjStateNF to restore state, write/read all the values manually! - // This should stop those stupid console errors, hopefully. - // -- Monster Iestyn - players[i].mo->sprite = (spritenum_t)LONG(rsp->sprite); - players[i].mo->frame = LONG(rsp->frame); - players[i].mo->sprite2 = rsp->sprite2; - players[i].mo->anim_duration = SHORT(rsp->anim_duration); - players[i].mo->tics = LONG(rsp->tics); - players[i].mo->state = &states[LONG(rsp->statenum)]; - - players[i].mo->x = LONG(rsp->x); - players[i].mo->y = LONG(rsp->y); - players[i].mo->z = LONG(rsp->z); - players[i].mo->radius = LONG(rsp->radius); - players[i].mo->height = LONG(rsp->height); - // P_SetScale is redundant for this, as all related variables are already restored properly. - players[i].mo->scale = LONG(rsp->scale); - players[i].mo->destscale = LONG(rsp->destscale); - players[i].mo->scalespeed = LONG(rsp->scalespeed); - - // And finally, SET THE MOBJ SKIN damn it. - if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NFLY].numframes == 0)) - { - players[i].mo->skin = &skins[DEFAULTNIGHTSSKIN]; - players[i].mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; // this will be corrected by thinker to super flash - } - else - { - players[i].mo->skin = &skins[players[i].skin]; - players[i].mo->color = players[i].skincolor; // this will be corrected by thinker to super flash/mario star - } - - P_SetThingPosition(players[i].mo); -} - -static inline void resynch_write_ctf(resynchend_pak *rst) -{ - mobj_t *mflag; - UINT8 i, j; - - for (i = 0, mflag = redflag; i < 2; ++i, mflag = blueflag) - { - rst->flagx[i] = rst->flagy[i] = rst->flagz[i] = 0; - rst->flagloose[i] = rst->flagflags[i] = 0; - rst->flagplayer[i] = -1; - - if (!mflag) - { - // Should be held by a player - for (j = 0; j < MAXPLAYERS; ++j) - { - // GF_REDFLAG is 1, GF_BLUEFLAG is 2 - // redflag handling is i=0, blueflag is i=1 - // so check for gotflag == (i+1) - if (!playeringame[j] || players[j].gotflag != (i+1)) - continue; - rst->flagplayer[i] = (SINT8)j; - break; - } - if (j == MAXPLAYERS) // fine, no I_Error - { - CONS_Alert(CONS_ERROR, "One of the flags has gone completely missing...\n"); - rst->flagplayer[i] = -2; - } - continue; - } - - rst->flagx[i] = (fixed_t)LONG(mflag->x); - rst->flagy[i] = (fixed_t)LONG(mflag->y); - rst->flagz[i] = (fixed_t)LONG(mflag->z); - rst->flagflags[i] = LONG(mflag->flags2); - rst->flagloose[i] = LONG(mflag->fuse); // Dropped or not? - } -} - -static inline void resynch_read_ctf(resynchend_pak *p) -{ - UINT8 i; - - for (i = 0; i < MAXPLAYERS; ++i) - players[i].gotflag = 0; - - // Red flag - if (p->flagplayer[0] == -2) - ; // The server doesn't even know what happened to it... - else if (p->flagplayer[0] != -1) // Held by a player - { - if (!playeringame[p->flagplayer[0]]) - I_Error("Invalid red flag player %d who isn't in the game!", (INT32)p->flagplayer[0]); - players[p->flagplayer[0]].gotflag = GF_REDFLAG; - if (redflag) - { - P_RemoveMobj(redflag); - redflag = NULL; - } - } - else - { - if (!redflag) - redflag = P_SpawnMobj(0,0,0,MT_REDFLAG); - - P_UnsetThingPosition(redflag); - redflag->x = (fixed_t)LONG(p->flagx[0]); - redflag->y = (fixed_t)LONG(p->flagy[0]); - redflag->z = (fixed_t)LONG(p->flagz[0]); - redflag->flags2 = LONG(p->flagflags[0]); - redflag->fuse = LONG(p->flagloose[0]); - P_SetThingPosition(redflag); - } - - // Blue flag - if (p->flagplayer[1] == -2) - ; // The server doesn't even know what happened to it... - else if (p->flagplayer[1] != -1) // Held by a player - { - if (!playeringame[p->flagplayer[1]]) - I_Error("Invalid blue flag player %d who isn't in the game!", (INT32)p->flagplayer[1]); - players[p->flagplayer[1]].gotflag = GF_BLUEFLAG; - if (blueflag) - { - P_RemoveMobj(blueflag); - blueflag = NULL; - } - } - else - { - if (!blueflag) - blueflag = P_SpawnMobj(0,0,0,MT_BLUEFLAG); - - P_UnsetThingPosition(blueflag); - blueflag->x = (fixed_t)LONG(p->flagx[1]); - blueflag->y = (fixed_t)LONG(p->flagy[1]); - blueflag->z = (fixed_t)LONG(p->flagz[1]); - blueflag->flags2 = LONG(p->flagflags[1]); - blueflag->fuse = LONG(p->flagloose[1]); - P_SetThingPosition(blueflag); - } -} - -static inline void resynch_write_others(resynchend_pak *rst) -{ - UINT8 i; - - rst->ingame = 0; - rst->outofcoop = 0; - - for (i = 0; i < MAXPLAYERS; ++i) - { - if (!playeringame[i]) - { - rst->ctfteam[i] = 0; - rst->score[i] = 0; - rst->numboxes[i] = 0; - rst->totalring[i] = 0; - rst->realtime[i] = 0; - rst->laps[i] = 0; - continue; - } - - if (!players[i].spectator) - rst->ingame |= (1<outofcoop |= (1<ctfteam[i] = (INT32)LONG(players[i].ctfteam); - rst->score[i] = (UINT32)LONG(players[i].score); - rst->numboxes[i] = SHORT(players[i].numboxes); - rst->totalring[i] = SHORT(players[i].totalring); - rst->realtime[i] = (tic_t)LONG(players[i].realtime); - rst->laps[i] = players[i].laps; - } - - // endian safeness - rst->ingame = (UINT32)LONG(rst->ingame); -} - -static inline void resynch_read_others(resynchend_pak *p) -{ - UINT8 i; - UINT32 loc_ingame = (UINT32)LONG(p->ingame); - UINT32 loc_outofcoop = (UINT32)LONG(p->outofcoop); - - for (i = 0; i < MAXPLAYERS; ++i) - { - // We don't care if they're in the game or not, just write all the data. - players[i].spectator = !(loc_ingame & (1<ctfteam[i]); // no, 0 does not mean spectator, at least not in Match - players[i].score = (UINT32)LONG(p->score[i]); - players[i].numboxes = SHORT(p->numboxes[i]); - players[i].totalring = SHORT(p->totalring[i]); - players[i].realtime = (tic_t)LONG(p->realtime[i]); - players[i].laps = p->laps[i]; - } -} - -static void SV_InitResynchVars(INT32 node) -{ - resynch_delay[node] = TICRATE; // initial one second delay - resynch_score[node] = 0; // clean slate - resynch_status[node] = 0x00; - resynch_inprogress[node] = false; - memset(resynch_sent[node], 0, MAXPLAYERS); -} - -static void SV_RequireResynch(INT32 node) -{ - INT32 i; - - resynch_delay[node] = 10; // Delay before you can fail sync again - resynch_score[node] += 200; // Add score for initial desynch - resynch_status[node] = 0xFFFFFFFF; // No players assumed synched - resynch_inprogress[node] = true; // so we know to send a PT_RESYNCHEND after sync - - // Initial setup - memset(resynch_sent[node], 0, MAXPLAYERS); - for (i = 0; i < MAXPLAYERS; ++i) - { - if (!playeringame[i]) // Player not in game so just drop it from required synch - resynch_status[node] &= ~(1<>1)+1; - } -} - -static void SV_SendResynch(INT32 node) -{ - INT32 i, j; - - if (!nodeingame[node]) - { - // player left during resynch - // so obviously we don't need to do any of this anymore - resynch_inprogress[node] = false; - return; - } - - // resynched? - if (!resynch_status[node]) - { - // you are now synched - resynch_inprogress[node] = false; - - netbuffer->packettype = PT_RESYNCHEND; - - netbuffer->u.resynchend.randomseed = P_GetRandSeed(); - if (gametyperules & GTR_TEAMFLAGS) - resynch_write_ctf(&netbuffer->u.resynchend); - resynch_write_others(&netbuffer->u.resynchend); - - HSendPacket(node, true, 0, (sizeof(resynchend_pak))); - return; - } - - netbuffer->packettype = PT_RESYNCHING; - for (i = 0, j = 0; i < MAXPLAYERS; ++i) - { - // if already synched don't bother - if (!(resynch_status[node] & 1<u.resynchpak, i); - HSendPacket(node, false, 0, (sizeof(resynch_pak))); - - resynch_sent[node][i] = TICRATE; - resynch_score[node] += 2; // penalty for send - - if (++j > 3) - break; - } - - if (resynch_score[node] > (unsigned)cv_resynchattempts.value*250) - { - SendKick(nodetoplayer[node], KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - resynch_score[node] = 0; - } -} - -static void CL_AcknowledgeResynch(resynch_pak *rsp) -{ - resynch_read_player(rsp); - - netbuffer->packettype = PT_RESYNCHGET; - netbuffer->u.resynchgot = rsp->playernum; - HSendPacket(servernode, true, 0, sizeof(UINT8)); -} - -static void SV_AcknowledgeResynchAck(INT32 node, UINT8 rsg) -{ - if (rsg >= MAXPLAYERS) - resynch_score[node] += 16384; // lol. - else - { - resynch_status[node] &= ~(1<packettype = PT_RECEIVEDGAMESTATE; + HSendPacket(servernode, true, 0, 0); } static void CL_ReloadReceivedSavegame(void) @@ -2535,7 +1943,6 @@ void CL_Reset(void) multiplayer = false; servernode = 0; server = true; - resynch_local_inprogress = false; doomcom->numnodes = 1; doomcom->numslots = 1; SV_StopServer(); @@ -3112,7 +2519,7 @@ static void ResetNode(INT32 node) nodewaiting[node] = 0; playerpernode[node] = 0; sendingsavegame[node] = false; - SV_InitResynchVars(node); + resendingsavegame[node] = false; } void SV_ResetServer(void) @@ -3634,12 +3041,6 @@ static void HandleConnect(SINT8 node) #endif SV_AddNode(node); - /// \note Wait what??? - /// What if the gamestate takes more than one second to get downloaded? - /// Or if a lagspike happens? - // you get a free second before desynch checks. use it wisely. - SV_InitResynchVars(node); - if (cv_joinnextround.value && gameaction == ga_nothing) G_SetGamestate(GS_WAITINGPLAYERS); if (!SV_SendServerConfig(node)) @@ -3762,6 +3163,7 @@ static void PT_CanReceiveGamestate(SINT8 node) CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); SV_SendSaveGame(node, true); // Resend a complete game state + resendingsavegame[node] = true; } /** Handles a packet received from a node that isn't in game @@ -3976,11 +3378,6 @@ static void HandlePacketFromPlayer(SINT8 node) switch (netbuffer->packettype) { // -------------------------------------------- SERVER RECEIVE ---------- - case PT_RESYNCHGET: - if (client) - break; - SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); - break; case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: @@ -3990,10 +3387,6 @@ static void HandlePacketFromPlayer(SINT8 node) if (client) break; - // Ignore tics from those not synched - if (resynch_inprogress[node] && nettics[node] == gametic) - break; - // To save bytes, only the low byte of tic numbers are sent // Use ExpandTics to figure out what the rest of the bytes are realstart = ExpandTics(netbuffer->u.clientpak.client_tic); @@ -4020,9 +3413,6 @@ static void HandlePacketFromPlayer(SINT8 node) || netbuffer->packettype == PT_NODEKEEPALIVEMIS) break; - // If a client sends a ticcmd it should mean they are done receiving the savegame - sendingsavegame[node] = false; - // As long as clients send valid ticcmds, the server can keep running, so reset the timeout /// \todo Use a separate cvar for that kind of timeout? freezetimeout[node] = I_GetTime() + connectiontimeout; @@ -4047,21 +3437,19 @@ static void HandlePacketFromPlayer(SINT8 node) G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); - // A delay before we check resynching - // Used on join or just after a synch fail - if (resynch_delay[node]) - { - --resynch_delay[node]; - break; - } // Check player consistancy during the level if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) + && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) + && !resendingsavegame[node]) { - SV_RequireResynch(node); - - if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) + if (cv_resynchattempts.value) { + // Tell the client we are about to resend them the gamestate + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + HSendPacket(node, true, 0, 0); + + resendingsavegame[node] = true; + if (cv_blamecfail.value) CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), netconsole+1, player_names[netconsole], @@ -4081,8 +3469,6 @@ static void HandlePacketFromPlayer(SINT8 node) break; } } - else if (resynch_score[node]) - --resynch_score[node]; break; case PT_TEXTCMD2: // splitscreen special netconsole = nodetoplayer2[node]; @@ -4211,25 +3597,11 @@ static void HandlePacketFromPlayer(SINT8 node) case PT_CANRECEIVEGAMESTATE: PT_CanReceiveGamestate(node); break; -// -------------------------------------------- CLIENT RECEIVE ---------- - case PT_RESYNCHEND: - // Only accept PT_RESYNCHEND from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHEND", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - resynch_local_inprogress = false; - - P_SetRandSeed(netbuffer->u.resynchend.randomseed); - - if (gametyperules & GTR_TEAMFLAGS) - resynch_read_ctf(&netbuffer->u.resynchend); - resynch_read_others(&netbuffer->u.resynchend); - + case PT_RECEIVEDGAMESTATE: + sendingsavegame[node] = false; + resendingsavegame[node] = false; break; +// -------------------------------------------- CLIENT RECEIVE ---------- case PT_SERVERTICS: // Only accept PT_SERVERTICS from the server. if (node != servernode) @@ -4293,18 +3665,6 @@ static void HandlePacketFromPlayer(SINT8 node) "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ } break; - case PT_RESYNCHING: - // Only accept PT_RESYNCHING from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHING", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - resynch_local_inprogress = true; - CL_AcknowledgeResynch(&netbuffer->u.resynchpak); - break; case PT_PING: // Only accept PT_PING from the server. if (node != servernode) @@ -4832,7 +4192,7 @@ void TryRunTics(tic_t realtics) if (player_joining) return; - if (neededtic > gametic && !resynch_local_inprogress) + if (neededtic > gametic) { if (advancedemo) { @@ -4991,9 +4351,9 @@ void NetUpdate(void) if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND) CL_ReloadReceivedSavegame(); - if (!(resynch_local_inprogress || cl_redownloadinggamestate)) + if (!cl_redownloadinggamestate) CL_SendClientCmd(); // Send tic cmd - hu_resynching = resynch_local_inprogress; + hu_redownloadinggamestate = cl_redownloadinggamestate; } else { @@ -5001,7 +4361,7 @@ void NetUpdate(void) { INT32 counts; - hu_resynching = false; + hu_redownloadinggamestate = false; firstticstosend = gametic; for (i = 0; i < MAXNETNODES; i++) @@ -5011,18 +4371,6 @@ void NetUpdate(void) // Don't erase tics not acknowledged counts = realtics; - for (i = 0; i < MAXNETNODES; ++i) - if (resynch_inprogress[i]) - { - if (!nodeingame[i] || nettics[i] == gametic) - { - SV_SendResynch(i); - counts = -666; - } - else - counts = 0; // Let the client catch up with the server - } - // Do not make tics while resynching if (counts != -666) { @@ -5040,7 +4388,7 @@ void NetUpdate(void) neededtic = maketic; // The server is a client too } else - hu_resynching = true; + hu_redownloadinggamestate = true; } } Net_AckTicker(); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 0f1998d51..81ea17638 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -64,11 +64,10 @@ typedef enum PT_REQUESTFILE, // Client requests a file transfer PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. // If this ID changes, update masterserver definition. - PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic - PT_RESYNCHGET, // Player got resynch packet PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate! - PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead. + PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead. + PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again! // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. @@ -82,8 +81,6 @@ typedef enum PT_TEXTCMD2, // Splitscreen text commands. PT_CLIENTJOIN, // Client wants to join; used in start game. PT_NODETIMEOUT, // Packet sent to self if the connection times out. - PT_RESYNCHING, // Packet sent to resync players. - // Blocks game advance until synched. PT_LOGIN, // Login attempt from the client. @@ -136,165 +133,6 @@ typedef struct ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large } ATTRPACK servertics_pak; -// Sent to client when all consistency data -// for players has been restored -typedef struct -{ - UINT32 randomseed; - - // CTF flag stuff - SINT8 flagplayer[2]; - INT32 flagloose[2]; - INT32 flagflags[2]; - fixed_t flagx[2]; - fixed_t flagy[2]; - fixed_t flagz[2]; - - UINT32 ingame; // Spectator bit for each player - UINT32 outofcoop; // outofcoop bit for each player - INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams) - - // Resynch game scores and the like all at once - UINT32 score[MAXPLAYERS]; // Everyone's score - INT16 numboxes[MAXPLAYERS]; - INT16 totalring[MAXPLAYERS]; - tic_t realtime[MAXPLAYERS]; - UINT8 laps[MAXPLAYERS]; -} ATTRPACK resynchend_pak; - -typedef struct -{ - // Player stuff - UINT8 playernum; - - // Do not send anything visual related. - // Only send data that we need to know for physics. - UINT8 playerstate; // playerstate_t - UINT32 pflags; // pflags_t - UINT8 panim; // panim_t - - angle_t aiming; - INT32 currentweapon; - INT32 ringweapons; - UINT16 ammoremoval; - tic_t ammoremovaltimer; - INT32 ammoremovalweapon; - UINT16 powers[NUMPOWERS]; - - // Score is resynched in the confirm resync packet - INT16 rings; - INT16 spheres; - SINT8 lives; - SINT8 continues; - UINT8 scoreadd; - SINT8 xtralife; - SINT8 pity; - - UINT8 skincolor; - INT32 skin; - UINT32 availabilities; - // Just in case Lua does something like - // modify these at runtime - fixed_t camerascale; - fixed_t shieldscale; - fixed_t normalspeed; - fixed_t runspeed; - UINT8 thrustfactor; - UINT8 accelstart; - UINT8 acceleration; - UINT8 charability; - UINT8 charability2; - UINT32 charflags; - UINT32 thokitem; // mobjtype_t - UINT32 spinitem; // mobjtype_t - UINT32 revitem; // mobjtype_t - UINT32 followitem; // mobjtype_t - fixed_t actionspd; - fixed_t mindash; - fixed_t maxdash; - fixed_t jumpfactor; - fixed_t playerheight; - fixed_t playerspinheight; - - fixed_t speed; - UINT8 secondjump; - UINT8 fly1; - tic_t glidetime; - UINT8 climbing; - INT32 deadtimer; - tic_t exiting; - UINT8 homing; - tic_t dashmode; - tic_t skidtime; - fixed_t cmomx; - fixed_t cmomy; - fixed_t rmomx; - fixed_t rmomy; - - INT32 weapondelay; - INT32 tossdelay; - - INT16 starpostx; - INT16 starposty; - INT16 starpostz; - INT32 starpostnum; - tic_t starposttime; - angle_t starpostangle; - fixed_t starpostscale; - - INT32 maxlink; - fixed_t dashspeed; - angle_t angle_pos; - angle_t old_angle_pos; - tic_t bumpertime; - INT32 flyangle; - tic_t drilltimer; - INT32 linkcount; - tic_t linktimer; - INT32 anotherflyangle; - tic_t nightstime; - INT32 drillmeter; - UINT8 drilldelay; - UINT8 bonustime; - UINT8 mare; - INT16 lastsidehit, lastlinehit; - - tic_t losstime; - UINT8 timeshit; - INT32 onconveyor; - - //player->mo stuff - UINT8 hasmo; // Boolean - - INT32 health; - angle_t angle; - angle_t rollangle; - fixed_t x; - fixed_t y; - fixed_t z; - fixed_t momx; - fixed_t momy; - fixed_t momz; - fixed_t friction; - fixed_t movefactor; - - spritenum_t sprite; - UINT32 frame; - UINT8 sprite2; - UINT16 anim_duration; - INT32 tics; - statenum_t statenum; - UINT32 flags; - UINT32 flags2; - UINT16 eflags; - - fixed_t radius; - fixed_t height; - fixed_t scale; - fixed_t destscale; - fixed_t scalespeed; -} ATTRPACK resynch_pak; - typedef struct { UINT8 version; // Different versions don't work @@ -430,9 +268,6 @@ typedef struct client2cmd_pak client2pak; // 200 bytes servertics_pak serverpak; // 132495 bytes (more around 360, no?) serverconfig_pak servercfg; // 773 bytes - resynchend_pak resynchend; // - resynch_pak resynchpak; // - UINT8 resynchgot; // UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) filetx_pak filetxpak; // 139 bytes clientconfig_pak clientcfg; // 136 bytes @@ -567,7 +402,7 @@ UINT8 GetFreeXCmdSize(void); void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest); -extern UINT8 hu_resynching; +extern UINT8 hu_redownloadinggamestate; extern UINT8 adminpassmd5[16]; extern boolean adminpasswordset; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 98f3ca5a9..561c04677 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2206,7 +2206,7 @@ void HU_Drawer(void) HU_DrawCrosshair2(); // draw desynch text - if (hu_resynching) + if (hu_redownloadinggamestate) { static UINT32 resynch_ticker = 0; char resynch_text[14];