Skip to content

Commit

Permalink
Multiplayer: Fixed issues with psprite animations
Browse files Browse the repository at this point in the history
Problems were fixed in the animation of the weapon psprite
on the client when picking up weapons/ammo/armor,
when first spawning on a level, when dying, and when
respawning back from the dead.

The game function P_MaybeChangeWeapon is now
executed by the client and never by the server, which
means the client's configuration affects the weapon
change rules.

Server protocol version number was incremented
because a new packet (GPT_MAYBE_CHANGE_WEAPON)
was added.
  • Loading branch information
skyjake committed Nov 28, 2011
1 parent ead2208 commit d4a0dd9
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 25 deletions.
4 changes: 2 additions & 2 deletions doomsday/engine/portable/include/sv_def.h
Expand Up @@ -32,8 +32,8 @@
#include "dd_def.h"
#include "m_string.h"

#define SV_VERSION 15
#define SV_WELCOME_STRING "Doomsday "DOOMSDAY_VERSION_TEXT" Server (R15)"
#define SV_VERSION 16
#define SV_WELCOME_STRING "Doomsday "DOOMSDAY_VERSION_TEXT" Server (R16)"

// Anything closer than this is always taken into consideration when
// deltas are being generated.
Expand Down
3 changes: 2 additions & 1 deletion doomsday/plugins/common/include/d_net.h
Expand Up @@ -77,7 +77,8 @@ enum {
GPT_PLAYER_SPAWN_POSITION,
GPT_DAMAGE_REQUEST, // Client requests damage on a target.
GPT_MOBJ_IMPULSE, // Momenum to apply on a mobj.
GPT_FLOOR_HIT_REQUEST
GPT_FLOOR_HIT_REQUEST,
GPT_MAYBE_CHANGE_WEAPON // Server suggests weapon change.
};

#if 0
Expand Down
1 change: 1 addition & 0 deletions doomsday/plugins/common/include/d_netsv.h
Expand Up @@ -71,6 +71,7 @@ void NetSv_DoAction(int player, Reader *reader);
void NetSv_DoDamage(int player, Reader *reader);
void NetSv_DoFloorHit(int player, Reader* msg);
void NetSv_SendJumpPower(int target, float power);
void NetSv_MaybeChangeWeapon(int plrNum, int weapon, int ammo, int force);

DEFCC(CCmdMapCycle);

Expand Down
9 changes: 9 additions & 0 deletions doomsday/plugins/common/src/d_net.c
Expand Up @@ -506,6 +506,15 @@ void D_HandlePacket(int fromplayer, int type, void *data, size_t length)
break;
}

case GPT_MAYBE_CHANGE_WEAPON:
{
weapontype_t wt = (weapontype_t) Reader_ReadInt16(reader);
ammotype_t at = (ammotype_t) Reader_ReadInt16(reader);
boolean force = (Reader_ReadByte(reader) != 0);
P_MaybeChangeWeapon(&players[CONSOLEPLAYER], wt, at, force);
break;
}

case GPT_CONSOLEPLAYER_STATE:
NetCl_UpdatePlayerState(reader, CONSOLEPLAYER);
break;
Expand Down
77 changes: 63 additions & 14 deletions doomsday/plugins/common/src/d_netcl.c
Expand Up @@ -354,6 +354,8 @@ void NetCl_UpdatePlayerState2(Reader* msg, int plrNum)

if(flags & PSF2_STATE)
{
int oldPlayerState = pl->playerState;

b = Reader_ReadByte(msg);
pl->playerState = b & 0xf;
#if __JDOOM__ || __JHERETIC__ || __JDOOM64__
Expand All @@ -366,15 +368,25 @@ void NetCl_UpdatePlayerState2(Reader* msg, int plrNum)
pl->playerState == PST_DEAD? "PST_DEAD" : "PST_REBORN");
#endif

// Set or clear the DEAD flag for this player.
if(pl->playerState == PST_LIVE)
pl->plr->flags &= ~DDPF_DEAD;
else
pl->plr->flags |= DDPF_DEAD;

//if(pl->playerState != oldstate)
// Player state changed?
if(oldPlayerState != pl->playerState)
{
P_SetupPsprites(pl);
// Set or clear the DEAD flag for this player.
if(pl->playerState == PST_LIVE)
{
// Becoming alive again...
// After being reborn, the server will tell us the new weapon.
pl->plr->flags |= DDPF_UNDEFINED_WEAPON;
#ifdef _DEBUG
Con_Message("NetCl_UpdatePlayerState2: Player %i: Marking weapon as undefined.\n", pl - players);
#endif

pl->plr->flags &= ~DDPF_DEAD;
}
else
{
pl->plr->flags |= DDPF_DEAD;
}
}

pl->cheats = Reader_ReadByte(msg);
Expand Down Expand Up @@ -619,21 +631,58 @@ void NetCl_UpdatePlayerState(Reader *msg, int plrNum)

if(flags & PSF_PENDING_WEAPON || flags & PSF_READY_WEAPON)
{
boolean wasUndefined = (pl->plr->flags & DDPF_UNDEFINED_WEAPON) != 0;

b = Reader_ReadByte(msg);
if(flags & PSF_PENDING_WEAPON)
{
pl->pendingWeapon = b & 0xf;
#if _DEBUG
Con_Message("NetCl_UpdatePlayerState: pendingweapon=%i\n", pl->pendingWeapon);
if(!wasUndefined)
{
int weapon = b & 0xf;
P_Impulse(pl - players, CTL_WEAPON1 + weapon);
#ifdef _DEBUG
Con_Message("NetCl_UpdatePlayerState: Weapon already known, using an impulse to switch to %i.\n", weapon);
#endif
}
else
{
pl->pendingWeapon = b & 0xf;
#ifdef _DEBUG
Con_Message("NetCl_UpdatePlayerState: pendingweapon=%i\n", pl->pendingWeapon);
#endif
}

pl->plr->flags &= ~DDPF_UNDEFINED_WEAPON;
}

if(flags & PSF_READY_WEAPON)
{
pl->readyWeapon = b >> 4;
#if _DEBUG
Con_Message("NetCl_UpdatePlayerState: readyweapon=%i\n", pl->readyWeapon);
if(wasUndefined)
{
pl->readyWeapon = b >> 4;
#ifdef _DEBUG
Con_Message("NetCl_UpdatePlayerState: readyweapon=%i\n", pl->readyWeapon);
#endif
}
else
{
#ifdef _DEBUG
Con_Message("NetCl_UpdatePlayerState: Readyweapon already known (%i), not setting server's value %i.\n",
pl->readyWeapon, b >> 4);
#endif
}

pl->plr->flags &= ~DDPF_UNDEFINED_WEAPON;
}

if(!(pl->plr->flags & DDPF_UNDEFINED_WEAPON) && wasUndefined)
{
#ifdef _DEBUG
Con_Message("NetCl_UpdatePlayerState: Weapon was undefined, bringing it up now.\n");
#endif

// Bring it up now.
P_BringUpWeapon(pl);
}
}

Expand Down
28 changes: 24 additions & 4 deletions doomsday/plugins/common/src/d_netsv.c
Expand Up @@ -1602,7 +1602,7 @@ void NetSv_SaveGame(unsigned int game_id)
// This will make the clients save their games.
writer = D_NetWrite();
Writer_WriteUInt32(writer, game_id);
Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_CONFIRM, GPT_SAVE, Writer_Data(writer), Writer_Size(writer));
Net_SendPacket(DDSP_ALL_PLAYERS, GPT_SAVE, Writer_Data(writer), Writer_Size(writer));
}

void NetSv_LoadGame(unsigned int game_id)
Expand All @@ -1614,7 +1614,7 @@ void NetSv_LoadGame(unsigned int game_id)

writer = D_NetWrite();
Writer_WriteUInt32(writer, game_id);
Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_CONFIRM, GPT_LOAD, Writer_Data(writer), Writer_Size(writer));
Net_SendPacket(DDSP_ALL_PLAYERS, GPT_LOAD, Writer_Data(writer), Writer_Size(writer));
}

/**
Expand All @@ -1629,7 +1629,7 @@ void NetSv_Paused(boolean isPaused)

writer = D_NetWrite();
Writer_WriteByte(writer, (isPaused != false));
Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_CONFIRM, GPT_PAUSE, Writer_Data(writer), Writer_Size(writer));
Net_SendPacket(DDSP_ALL_PLAYERS, GPT_PAUSE, Writer_Data(writer), Writer_Size(writer));
}

void NetSv_SendMessageEx(int plrNum, const char *msg, boolean yellow)
Expand All @@ -1656,7 +1656,7 @@ void NetSv_SendMessageEx(int plrNum, const char *msg, boolean yellow)
writer = D_NetWrite();
Writer_WriteUInt16(writer, strlen(msg));
Writer_Write(writer, msg, strlen(msg));
Net_SendPacket(plrNum | DDSP_ORDERED,
Net_SendPacket(plrNum,
yellow ? GPT_YELLOW_MESSAGE : GPT_MESSAGE,
Writer_Data(writer), Writer_Size(writer));
}
Expand All @@ -1671,6 +1671,26 @@ void NetSv_SendYellowMessage(int plrNum, const char *msg)
NetSv_SendMessageEx(plrNum, msg, true);
}

void NetSv_MaybeChangeWeapon(int plrNum, int weapon, int ammo, int force)
{
Writer* writer;

if(IS_CLIENT) return;
if(plrNum < 0 || plrNum >= MAXPLAYERS)
return;

#ifdef _DEBUG
Con_Message("NetSv_MaybeChangeWeapon: Plr=%i Weapon=%i Ammo=%i Force=%i\n",
plrNum, weapon, ammo, force);
#endif

writer = D_NetWrite();
Writer_WriteInt16(writer, weapon);
Writer_WriteInt16(writer, ammo);
Writer_WriteByte(writer, force != 0);
Net_SendPacket(plrNum, GPT_MAYBE_CHANGE_WEAPON, Writer_Data(writer), Writer_Size(writer));
}

void P_Telefrag(mobj_t *thing)
{
P_TeleportMove(thing, thing->pos[VX], thing->pos[VY], false);
Expand Down
9 changes: 8 additions & 1 deletion doomsday/plugins/common/src/p_player.c
Expand Up @@ -407,6 +407,13 @@ weapontype_t P_MaybeChangeWeapon(player_t *player, weapontype_t weapon,
weaponinfo_t *winf;
boolean found;

if(IS_SERVER)
{
// This is done on clientside.
NetSv_MaybeChangeWeapon(player - players, weapon, ammo, force);
return WT_NOCHANGE;
}

#ifdef _DEBUG
Con_Message("P_MaybeChangeWeapon: plr %i, weapon %i, ammo %i, force %i\n",
(int)(player - players), weapon, ammo, force);
Expand Down Expand Up @@ -571,7 +578,7 @@ weapontype_t P_MaybeChangeWeapon(player_t *player, weapontype_t weapon,
if(returnval != WT_NOCHANGE)
{
player->pendingWeapon = returnval;
player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON;
//player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON;
}

return returnval;
Expand Down
15 changes: 12 additions & 3 deletions doomsday/plugins/common/src/p_start.c
Expand Up @@ -593,6 +593,7 @@ static void spawnPlayer(int plrNum, playerclass_t pClass, float x, float y,
*/
void P_SpawnClient(int plrNum)
{
player_t* p;
#if __JHEXEN__
playerclass_t pClass = cfg.playerClass[plrNum];
#else
Expand All @@ -606,12 +607,20 @@ void P_SpawnClient(int plrNum)
// The server will fix the player's position and angles soon after.
spawnPlayer(plrNum, pClass, -30000, -30000, 0, 0, MSF_Z_FLOOR, false, false, false);

players[plrNum].viewHeight = cfg.plrViewHeight;
players[plrNum].viewHeightDelta = 0;
p = &players[plrNum];
p->viewHeight = cfg.plrViewHeight;
p->viewHeightDelta = 0;

// The mobj was just spawned onto invalid coordinates. The view cannot
// be drawn until we receive the right coords.
players[plrNum].plr->flags |= DDPF_UNDEFINED_POS;
p->plr->flags |= DDPF_UNDEFINED_POS;

// The weapon of the player is not known. The weapon cannot be raised
// until we know it.
p->plr->flags |= DDPF_UNDEFINED_WEAPON;

// The weapon should be in the down state when spawning.
p->pSprites[0].pos[VY] = WEAPONBOTTOM;
}

/**
Expand Down

0 comments on commit d4a0dd9

Please sign in to comment.