Skip to content

Commit

Permalink
Shell|Server: Added basic player info packet
Browse files Browse the repository at this point in the history
The positions, names, numbers, and colors of players will be shown
in the map outline view.

Todo for later: Use the game-side player colors.
  • Loading branch information
skyjake committed Mar 15, 2013
1 parent 70123eb commit 5b6068a
Show file tree
Hide file tree
Showing 10 changed files with 289 additions and 14 deletions.
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/vector.h
Expand Up @@ -501,6 +501,7 @@ typedef Vector2<dint> Vector2i; ///< 2-component vector of integer values.
typedef Vector2<duint> Vector2ui; ///< 2-component vector of unsigned integer values.
typedef Vector2<dfloat> Vector2f; ///< 2-component vector of floating point values.
typedef Vector2<ddouble> Vector2d; ///< 2-component vector of high-precision floating point values.
typedef Vector3<dbyte> Vector3ub; ///< 3-component vector of unsigned byte values.
typedef Vector3<dint> Vector3i; ///< 3-component vector of integer values.
typedef Vector3<duint> Vector3ui; ///< 3-component vector of unsigned integer values.
typedef Vector3<dfloat> Vector3f; ///< 3-component vector of floating point values.
Expand Down
50 changes: 49 additions & 1 deletion doomsday/libshell/include/de/shell/protocol.h
Expand Up @@ -77,6 +77,54 @@ class LIBSHELL_PUBLIC LogEntryPacket : public Packet
Entries _entries;
};

/**
* Packet containing information about the players' current positions, colors,
* and names.
*/
class LIBSHELL_PUBLIC PlayerInfoPacket : public Packet
{
public:
struct Player
{
int number;
Vector2i position;
String name;
Vector3ub color;

Player(int num = 0,
Vector2i const &pos = Vector2i(),
String const &plrName = "",
Vector3ub const &plrColor = Vector3ub())
: number(num),
position(pos),
name(plrName),
color(plrColor)
{}
};

typedef QMap<int, Player> Players;

public:
PlayerInfoPacket();

void add(Player const &player);

int count() const;

Player const &player(int number) const;

Players players() const;

// Implements ISerializable.
void operator >> (Writer &to) const;
void operator << (Reader &from);

static Packet *fromBlock(Block const &block);

private:
DENG2_PRIVATE(d)
};

/**
* Packet containing an outline of a map's lines.
*
Expand Down Expand Up @@ -146,7 +194,7 @@ class LIBSHELL_PUBLIC Protocol : public de::Protocol
GameState, ///< Current state of the game (mode, map).
Leaderboard, ///< Frags leaderboard.
MapOutline, ///< Sectors of the map for visual overview.
PlayerPositions ///< Current player positions.
PlayerInfo ///< Current player names, colors, positions.
};

public:
Expand Down
73 changes: 73 additions & 0 deletions doomsday/libshell/src/protocol.cpp
Expand Up @@ -106,6 +106,72 @@ Packet *LogEntryPacket::fromBlock(Block const &block)
return constructFromBlock<LogEntryPacket>(block, LOG_ENTRY_PACKET_TYPE);
}

// PlayerInfoPacket ----------------------------------------------------------

static char const *PLAYER_INFO_PACKET_TYPE = "PlrI";

DENG2_PIMPL_NOREF(PlayerInfoPacket)
{
Players players;
};

PlayerInfoPacket::PlayerInfoPacket()
: Packet(PLAYER_INFO_PACKET_TYPE), d(new Instance)
{}

void PlayerInfoPacket::add(Player const &player)
{
d->players.insert(player.number, player);
}

int PlayerInfoPacket::count() const
{
return d->players.size();
}

PlayerInfoPacket::Player const &PlayerInfoPacket::player(int number) const
{
DENG2_ASSERT(d->players.contains(number));
return d->players[number];
}

PlayerInfoPacket::Players PlayerInfoPacket::players() const
{
return d->players;
}

void PlayerInfoPacket::operator >> (Writer &to) const
{
Packet::operator >> (to);

to << duint32(d->players.size());
foreach(Player const &p, d->players)
{
to << dbyte(p.number) << p.position << p.name << p.color;
}
}

void PlayerInfoPacket::operator << (Reader &from)
{
d->players.clear();

Packet::operator << (from);

duint32 count;
from >> count;
while(count-- > 0)
{
Player p;
from.readAs<dbyte>(p.number) >> p.position >> p.name >> p.color;
d->players.insert(p.number, p);
}
}

Packet *PlayerInfoPacket::fromBlock(Block const &block)
{
return constructFromBlock<PlayerInfoPacket>(block, PLAYER_INFO_PACKET_TYPE);
}

// MapOutlinePacket ----------------------------------------------------------

static char const *MAP_OUTLINE_PACKET_TYPE = "MpOL";
Expand Down Expand Up @@ -184,6 +250,7 @@ Protocol::Protocol()
define(ChallengePacket::fromBlock);
define(LogEntryPacket::fromBlock);
define(MapOutlinePacket::fromBlock);
define(PlayerInfoPacket::fromBlock);
}

Protocol::PacketType Protocol::recognize(Packet const *packet)
Expand All @@ -206,6 +273,12 @@ Protocol::PacketType Protocol::recognize(Packet const *packet)
return MapOutline;
}

if(packet->type() == PLAYER_INFO_PACKET_TYPE)
{
DENG2_ASSERT(dynamic_cast<PlayerInfoPacket const *>(packet) != 0);
return PlayerInfo;
}

// One of the generic-format packets?
RecordPacket const *rec = dynamic_cast<RecordPacket const *>(packet);
if(rec)
Expand Down
1 change: 1 addition & 0 deletions doomsday/server/include/shelluser.h
Expand Up @@ -54,6 +54,7 @@ class ShellUser : public de::shell::Link

void sendGameState();
void sendMapOutline();
void sendPlayerInfo();

protected slots:
void handleIncomingPackets();
Expand Down
5 changes: 4 additions & 1 deletion doomsday/server/include/shellusers.h
Expand Up @@ -50,11 +50,14 @@ class ShellUsers : public QObject, public IMapChangeObserver

void currentMapChanged();

public slots:
void sendPlayerInfoToAll();

protected slots:
void userDisconnected();

private:
QSet<ShellUser *> _users;
DENG2_PRIVATE(d)
};

#endif // SERVER_SHELLUSERS_H
34 changes: 34 additions & 0 deletions doomsday/server/src/shelluser.cpp
Expand Up @@ -29,7 +29,9 @@
#include "games.h"
#include "Game"
#include "def_main.h"
#include "network/net_main.h"
#include "map/gamemap.h"
#include "map/p_players.h"

using namespace de;

Expand Down Expand Up @@ -96,6 +98,7 @@ void ShellUser::sendInitialUpdate()

sendGameState();
sendMapOutline();
sendPlayerInfo();
}

void ShellUser::sendGameState()
Expand Down Expand Up @@ -164,6 +167,37 @@ void ShellUser::sendMapOutline()
*this << *packet;
}

void ShellUser::sendPlayerInfo()
{
if(!theMap) return;

QScopedPointer<shell::PlayerInfoPacket> packet(new shell::PlayerInfoPacket);

for(uint i = 1; i < DDMAXPLAYERS; ++i)
{
if(!ddPlayers[i].shared.inGame || !ddPlayers[i].shared.mo)
continue;

shell::PlayerInfoPacket::Player info;

info.number = i;
info.name = clients[i].name;
info.position = de::Vector2i(ddPlayers[i].shared.mo->origin[VX],
ddPlayers[i].shared.mo->origin[VY]);

/**
* @todo Player color is presently game-side data. Therefore, this
* packet should be constructed by libcommon (or player color should be
* moved to the engine).
*/
// info.color = ?

packet->add(info);
}

*this << *packet;
}

void ShellUser::handleIncomingPackets()
{
forever
Expand Down
47 changes: 41 additions & 6 deletions doomsday/server/src/shellusers.cpp
Expand Up @@ -18,17 +18,43 @@
*/

#include "shellusers.h"
#include <QTimer>

ShellUsers::ShellUsers()
static int const PLAYER_INFO_INTERVAL = 2500; // ms

DENG2_PIMPL_NOREF(ShellUsers)
{
QSet<ShellUser *> users;
QTimer *infoTimer;

Instance()
{
infoTimer = new QTimer;
infoTimer->setInterval(PLAYER_INFO_INTERVAL);
}

~Instance()
{
delete infoTimer;
}
};

ShellUsers::ShellUsers() : d(new Instance)
{
audienceForMapChange += this;

// Player information is sent periodically to all shell users.
connect(d->infoTimer, SIGNAL(timeout()), this, SLOT(sendPlayerInfoToAll()));
d->infoTimer->start();
}

ShellUsers::~ShellUsers()
{
d->infoTimer->stop();

audienceForMapChange -= this;

foreach(ShellUser *user, _users)
foreach(ShellUser *user, d->users)
{
delete user;
}
Expand All @@ -38,23 +64,32 @@ void ShellUsers::add(ShellUser *user)
{
LOG_INFO("New shell user from %s") << user->address();

_users.insert(user);
d->users.insert(user);
connect(user, SIGNAL(disconnected()), this, SLOT(userDisconnected()));

user->sendInitialUpdate();
}

int ShellUsers::count() const
{
return _users.size();
return d->users.size();
}

void ShellUsers::currentMapChanged()
{
foreach(ShellUser *user, _users)
foreach(ShellUser *user, d->users)
{
user->sendGameState();
user->sendMapOutline();
user->sendPlayerInfo();
}
}

void ShellUsers::sendPlayerInfoToAll()
{
foreach(ShellUser *user, d->users)
{
user->sendPlayerInfo();
}
}

Expand All @@ -63,7 +98,7 @@ void ShellUsers::userDisconnected()
DENG2_ASSERT(dynamic_cast<ShellUser *>(sender()) != 0);

ShellUser *user = static_cast<ShellUser *>(sender());
_users.remove(user);
d->users.remove(user);

LOG_INFO("Shell user from %s has disconnected") << user->address();

Expand Down
4 changes: 4 additions & 0 deletions doomsday/tools/shell/shell-gui/src/linkwindow.cpp
Expand Up @@ -431,6 +431,10 @@ void LinkWindow::handleIncomingPackets()
d->status->setMapOutline(*static_cast<MapOutlinePacket *>(packet.data()));
break;

case shell::Protocol::PlayerInfo:
d->status->setPlayerInfo(*static_cast<PlayerInfoPacket *>(packet.data()));
break;

default:
break;
}
Expand Down

0 comments on commit 5b6068a

Please sign in to comment.