Add /t server command for team chat

New command /t that can be used in game to send chats that only appear
to players on the same team. Observing players cannot use team chat.
This commit is contained in:
Nathan Fulton 2016-08-24 22:46:42 -04:00
parent f6dd61415f
commit abb1823956
17 changed files with 393 additions and 18 deletions

View File

@ -260,9 +260,15 @@ void PlayerMgr::SetAllies(Player **applr, int cplrs, SideMask sidmAllies)
{
// Set allies
for (int n = 0; n < cplrs; n++)
for (int n = 0; n < cplrs; n++) {
applr[n]->SetAllies(sidmAllies);
// Send this to the server so it can use it for ally chat
if (gptra != NULL) {
gptra->UpdateAllies(applr[n]->GetSide(), sidmAllies);
}
}
// Recalc enemies. Clear first
Gob *pgobT;

View File

@ -421,6 +421,8 @@ public:
virtual bool SendNetMessage(NetMessage *pnm) = 0;
virtual void LeaveGame() = 0;
virtual void OnEvent(Event *pevt) = 0;
virtual void UpdateAllies(Side side, SideMask sidmAllies) = 0;
virtual void DisconnectSharedAccounts() = 0;
virtual ITransportCallback *SetCallback(ITransportCallback *ptcb);
virtual ITransportCallback *GetCallback();
virtual IGameCallback *SetGameCallback(IGameCallback *pgcb);

View File

@ -214,6 +214,22 @@ bool LoginForm::AttemptLogin() {
"This server does not allow anonymous logins. Please login with an account.");
return false;
case knLoginResultAccountInUse:
{
bool fYes = false;
fYes = HtMessageBox(kidfMessageBoxQuery, kfMbKeepTimersEnabled | kfMbWhiteBorder,
"Login Failure", "Your account is already logged in to this server with another device. Would you like to disconnect that device and then login?");
// Does the user want to disconnect logged in devices?
if (fYes && gptra != NULL) {
gptra->DisconnectSharedAccounts();
// Try to login again
return AttemptLogin();
}
return false;
}
case knLoginResultFail:
default:
if (!handler_.anonymous()) {

View File

@ -4,6 +4,7 @@
#include "game/serviceurls.h"
#include "game/chooseserverform.h"
#include "mpshared/xpump.h"
#include "mpshared/mpht.h"
namespace wi {
@ -943,4 +944,20 @@ void XTransport::OnWriteEvent(base::Socket *socket) {
void XTransport::OnCloseEvent(base::Socket *socket) {
}
void XTransport::UpdateAllies(Side side, SideMask sidmAllies) {
if (error_ || xpump_.IsClosed()) {
return;
}
if (state_ == XTS_ROOM) {
return;
}
if (state_ == XTS_GAME) {
xpump_.Send(XMsgGameUpdateAllies::ToBuffer(dword(side), dword(sidmAllies)));
return;
}
}
void XTransport::DisconnectSharedAccounts() {
xpump_.Send(XMsgDisconnectSharedAccounts::ToBuffer());
}
} // namespace wi

View File

@ -40,6 +40,8 @@ public:
dword *gameid);
virtual dword CanJoinGame(dword gameid);
virtual void LeaveRoom(dword hint);
virtual void UpdateAllies(Side side, SideMask sidmAllies);
virtual void DisconnectSharedAccounts();
virtual dword JoinGame(dword gameid, dword roomid);
virtual bool SendNetMessage(NetMessage *pnm);

View File

@ -57,6 +57,8 @@ const byte XMSG_GAMEUPDATERESULT = 0xd6;
const byte XMSG_GAMEKILLED = 0xd7;
const byte XMSG_GAMELEAVE = 0xd8;
const byte XMSG_GAMELEAVERESULT = 0xd9;
const byte XMSG_GAMEUPDATEALLIES = 0xda;
const byte XMSG_DISCONNECTSHAREDACCOUNTS = 0xe0;
STARTLABEL(XMsgLabels)
LABEL(XMSG_NONE)
@ -108,6 +110,8 @@ STARTLABEL(XMsgLabels)
LABEL(XMSG_GAMEKILLED)
LABEL(XMSG_GAMELEAVE)
LABEL(XMSG_GAMELEAVERESULT)
LABEL(XMSG_GAMEUPDATEALLIES)
LABEL(XMSG_DISCONNECTSHAREDACCOUNTS)
ENDLABEL(XMsgLabels)
} // namespace wi

View File

@ -79,6 +79,7 @@ const dword knLoginResultStaleToken = 3;
const dword knLoginResultAuthDown = 4;
const dword knLoginResultNoPassword = 5;
const dword knLoginResultNoAnons = 6;
const dword knLoginResultAccountInUse = 7;
STARTLABEL(LoginResults)
LABEL(knLoginResultSuccess)
@ -88,6 +89,7 @@ STARTLABEL(LoginResults)
LABEL(knLoginResultAuthDown)
LABEL(knLoginResultNoPassword)
LABEL(knLoginResultNoAnons)
LABEL(knLoginResultAccountInUse)
ENDLABEL(LoginResults)
const dword knSignOutResultSuccess = 0;
@ -181,6 +183,8 @@ typedef XMsgS2<XMSG_GAMERECEIVECHAT, kcbPlayerName, kcbChatMax> XMsgGameReceiveC
typedef XMsg1<XMSG_GAMEKILLED> XMsgGameKilled;
typedef XMsg0<XMSG_GAMELEAVE> XMsgGameLeave;
typedef XMsg1<XMSG_GAMELEAVERESULT> XMsgGameLeaveResult;
typedef XMsg2<XMSG_GAMEUPDATEALLIES> XMsgGameUpdateAllies;
typedef XMsg0<XMSG_DISCONNECTSHAREDACCOUNTS> XMsgDisconnectSharedAccounts;
struct XMsgShowMessage : public XMsg {
XMsgShowMessage(const char *message, dword ipRedirect, bool disconnect) :

View File

@ -323,6 +323,12 @@ XMsg *XPump::XMsgFromBuffer(base::ByteBuffer& bb, dword cb) {
case XMSG_GAMELEAVERESULT:
return XMsgGameLeaveResult::FromBuffer(bb, cb);
case XMSG_GAMEUPDATEALLIES:
return XMsgGameUpdateAllies::FromBuffer(bb, cb);
case XMSG_DISCONNECTSHAREDACCOUNTS:
return XMsgDisconnectSharedAccounts::FromBuffer(bb, cb);
default:
return NULL;
}
@ -681,6 +687,20 @@ void XPump::DispatchXMsg(XMsg *pmsg) {
}
break;
case XMSG_GAMEUPDATEALLIES:
{
XMsgGameUpdateAllies *pmsgT = (XMsgGameUpdateAllies *)pmsg;
// side, allies
notify_->OnUpdateAllies(pmsgT->dw0_, pmsgT->dw1_);
}
break;
case XMSG_DISCONNECTSHAREDACCOUNTS:
{
notify_->OnDisconnectSharedAccounts();
}
break;
default:
notify_->OnError(-1);
Assert(false);

View File

@ -69,10 +69,12 @@ public:
virtual void OnGameSendChat(const char *chat) { Assert(); }
virtual void OnGameReceiveChat(const char *player, const char *chat)
{ Assert(); }
virtual void OnUpdateAllies(dword side, dword sidmAllies) { Assert(); }
virtual void OnGameNetMessage(NetMessage **ppnm) { Assert(); }
virtual void OnGameKilled(dword gameid) { Assert(); }
virtual void OnGameLeave() { Assert(); }
virtual void OnGameLeaveResult(dword result) { Assert(); }
virtual void OnDisconnectSharedAccounts() { Assert(); }
virtual bool OnMessages() { return false; }
virtual void OnCloseOk() { return; }
virtual void OnError(int error) { Assert(); }

View File

@ -23,7 +23,7 @@ Endpoint::Endpoint(Server& server, base::Socket *socket, dword id,
protocolid_(0), state_(ES_HANDSHAKE), game_(NULL), echo_(true),
roomid_(0), name_(NULL), anonymous_(true), missed_(0), okecho_(false),
admin_(false), muted_(false), sigvisible_(false), seechat_(false),
roomlimiter_(2, 120) {
roomlimiter_(2, 120), teamchat_(false) {
did_[0] = 0;
xpump_.Attach(socket, this, server.log());
}
@ -156,10 +156,20 @@ void Endpoint::OnLogin(const char *username, const char *token, const char *did)
return;
}
// Success. Take in the new name, transition to ES_READY
// Endpoint has been authed, so take in the new name
RememberName(name_);
delete name_;
name_ = AllocString(base::Format::ToString(username, id_));
// Moderators are allowed to login with multiple devices
if (!server_.AccountSharing() && !IsModerator()) {
if (server_.SharedAccountExists(this, username)) {
xpump_.Send(XMsgLoginResult::ToBuffer(knLoginResultAccountInUse));
return;
}
}
// Success. Transition to ES_READY
xpump_.Send(XMsgLoginResult::ToBuffer(knLoginResultSuccess));
anonymous_ = false;
SetState(ES_READY);
@ -556,6 +566,9 @@ void Endpoint::OnGameJoin(dword gameid, dword roomid) {
game_->SignalOnDelete.connect(this, &Endpoint::OnGameDelete);
game->AddPlayer(this);
// Team chat should be turned off by default
teamchat_ = false;
SetState(ES_GAME);
}
@ -712,6 +725,9 @@ ModeratorCommand Endpoint::GetModeratorCommand(const char *chat) {
if (strcmp(arg.c_str(), "/ann") == 0) {
return kModeratorCommandAnnouncements;
}
if (strcmp(arg.c_str(), "/t") == 0) {
return kModeratorCommandTeam;
}
return kModeratorCommandUnknown;
}
@ -750,6 +766,51 @@ bool Endpoint::ProcessCommand(const char *chat, std::string *response) {
// This will get processed by the game.
return false;
case kModeratorCommandTeam:
{
// Player not in game
if (state_ != ES_GAME || game_ == NULL) {
*response = "Command not available.";
return true;
}
if (!game_->CanSendTeamChat(this, true)) {
teamchat_ = false;
return false;
}
std::string dummy;
std::string msg;
const char *rest;
GetArgument(chat, 0, &dummy, &rest);
msg = rest;
if (msg.empty()) {
// Toggle team chat
teamchat_ = !teamchat_;
if (teamchat_) {
this->xpump().Send(XMsgGameReceiveChat::ToBuffer("",
"Team chat has been toggled ON."));
} else {
this->xpump().Send(XMsgGameReceiveChat::ToBuffer("",
"Team chat has been toggled OFF."));
}
} else {
if (!teamchat_) {
// Turn on team chat so OnGameSendChat() will process
// it as a team chat then turn it back off.
teamchat_ = true;
this->OnGameSendChat(msg.c_str());
teamchat_ = false;
} else {
this->OnGameSendChat(msg.c_str());
}
}
*response = "";
return true;
}
case kModeratorCommandFlag:
// Write an entry into the log
{
@ -779,17 +840,17 @@ bool Endpoint::ProcessCommand(const char *chat, std::string *response) {
bool swap = game_->IsSwapAllowed(this);
if (anon) {
if (swap) {
*response = "/mute, /unmute, /anon, /swap, /kick, /flag [msg], /help.";
*response = "/mute, /unmute, /anon, /swap, /kick, /flag [msg], /t [msg], /help.";
} else {
*response = "/mute, /unmute, /anon, /kick, /flag [msg], /help.";
*response = "/mute, /unmute, /anon, /kick, /flag [msg], /t [msg], /help.";
}
} else if (swap) {
*response = "/mute, /unmute, /swap, /kick, /flag [msg], /help.";
*response = "/mute, /unmute, /swap, /kick, /flag [msg], /t [msg], /help.";
} else {
*response = "/mute, /unmute, /kick, /flag [msg], /help.";
*response = "/mute, /unmute, /kick, /flag [msg], /t [msg], /help.";
}
} else {
*response = "/mute, /unmute, /kick, /flag [msg], /help.";
*response = "/mute, /unmute, /kick, /flag [msg], /t [msg], /help.";
}
break;
@ -1358,13 +1419,13 @@ bool Endpoint::ProcessCommand(const char *chat, std::string *response) {
case kModeratorCommandHelp:
if (IsAdmin()) {
if (state_ == ES_GAME) {
*response = "/ids [all] [lobby] [roomid] [gameid], /mute <id> [minutes], /unmute <id>, /ban <id> [minutes], /rooms, /kill <roomid>, /games <roomid>, /names <id>, /w <id>, /m, /title <roomid>, /clear, /filter, /sig, /see, /perm <roomid>, /reg [server] [roomid], /swap, /anon, /rules, /flag [msg], /ann [msg], /help.";
*response = "/ids [all] [lobby] [roomid] [gameid], /mute <id> [minutes], /unmute <id>, /ban <id> [minutes], /rooms, /kill <roomid>, /games <roomid>, /names <id>, /w <id>, /m, /title <roomid>, /clear, /filter, /sig, /see, /perm <roomid>, /reg [server] [roomid], /swap, /anon, /rules, /flag [msg], /ann [msg], /t [msg], /help.";
} else {
*response = "/ids [all] [lobby] [roomid] [gameid], /mute <id> [minutes], /unmute <id>, /kick <id> [minutes], /ban <id> [minutes], /rooms, /kill <roomid>, /games <roomid>, /names <id>, /w <id>, /m, /title <roomid>, /clear, /filter, /sig, /see, /perm <roomid>, /reg [server] [roomid], /rules, /flag [msg], /ann [msg], /help.";
}
} else {
if (state_ == ES_GAME) {
*response = "/ids [all] [lobby] [roomid] [gameid], /mute <id> [minutes], /unmute <id>, /rooms, /games <roomid>, /w <id>, /m, /title <roomid>, /sig, /see, /swap, /anon, /rules, /flag [msg], /help.";
*response = "/ids [all] [lobby] [roomid] [gameid], /mute <id> [minutes], /unmute <id>, /rooms, /games <roomid>, /w <id>, /m, /title <roomid>, /sig, /see, /swap, /anon, /rules, /flag [msg], /t [msg], /help.";
} else {
*response = "/ids [all] [lobby] [roomid] [gameid], /mute <id> [minutes], /unmute <id>, /kick <id> [minutes], /rooms, /games <roomid>, /w <id>, /m, /title <roomid>, /sig, /see, /rules, /flag [msg], /help.";
}
@ -1416,14 +1477,26 @@ void Endpoint::OnGameSendChat(const char *chat) {
Room *room = server_.lobby().FindRoom(roomid_);
if (room != NULL && !room->moderated()) {
// Unmoderated rooms aren't filtered
game_->SendChat(this, chat, NULL);
if (teamchat_) {
game_->SendTeamChat(this, chat, NULL);
} else {
game_->SendChat(this, chat, NULL);
}
} else {
// Moderated rooms are filtered
const char *filtered;
if (FilterChat(chat, &filtered)) {
game_->SendChat(this, filtered, chat);
if (teamchat_) {
game_->SendTeamChat(this, filtered, chat);
} else {
game_->SendChat(this, filtered, chat);
}
} else {
game_->SendChat(this, filtered, NULL);
if (teamchat_) {
game_->SendTeamChat(this, filtered, NULL);
} else {
game_->SendChat(this, filtered, NULL);
}
}
}
}
@ -1455,6 +1528,8 @@ void Endpoint::OnGameLeave() {
game_->RemovePlayer(this, knDisconnectReasonLeftGame);
game_ = NULL;
teamchat_ = false;
// Stop logging with the game id
xpump_.SetLogId(0);
@ -1518,6 +1593,12 @@ void Endpoint::OnCloseOk() {
Dispose();
}
void Endpoint::OnUpdateAllies(dword side, dword sidmAllies) {
if (state_ == ES_GAME && game_ != NULL) {
game_->SetAllies((SideMask)side, (SideMask)sidmAllies);
}
}
void Endpoint::OnHeartbeat() {
// If a game is playing, there is a game timer to monitor clients
if (game_ != NULL && game_->playing()) {
@ -1630,4 +1711,8 @@ dword Endpoint::gameid() {
return game_ == NULL ? 0 : game_->id();
}
void Endpoint::OnDisconnectSharedAccounts() {
server_.DisconnectSharedAccounts(this, name_);
}
} // namespace wi

View File

@ -8,6 +8,7 @@
#include "base/messagequeue.h"
#include "inc/basictypes.h"
#include "mpshared/xpump.h"
#include "mpshared/mpht.h"
#include "server/levelinfo.h"
#include "server/lobby.h"
#include "server/tokenbucket.h"
@ -31,7 +32,7 @@ enum ModeratorCommand {
kModeratorCommandMods, kModeratorCommandWhisper, kModeratorCommandTitle,
kModeratorCommandRegisteredOnly, kModeratorCommandAnonBlock,
kModeratorCommandSwap, kModeratorCommandFlag, kModeratorCommandHelp,
kModeratorCommandAnnouncements
kModeratorCommandAnnouncements, kModeratorCommandTeam
};
class Endpoint : public base::MessageHandler, XPumpNotify,
@ -105,6 +106,8 @@ private:
virtual void OnError(int error);
virtual void OnClose(int error);
virtual void OnCloseOk();
virtual void OnUpdateAllies(dword side, dword sidmAllies);
virtual void OnDisconnectSharedAccounts();
XPump xpump_;
State state_;
@ -126,6 +129,7 @@ private:
bool muted_;
bool sigvisible_;
bool seechat_;
bool teamchat_;
std::vector<std::string> old_names_;
std::string chat_fragment_;
TokenBucket roomlimiter_;

View File

@ -945,6 +945,17 @@ const char *Game::ColorFromSide(int side) {
return s_colors[side];
}
const char *Game::ColorCharFromSide(int side) {
// 0: gray, 1: blue, 2: red, 3: yellow, 4: cyan
static const char *s_colors[] = {
"g", "b", "r", "y", "c"
};
if (side < 0 || side >= ARRAYSIZE(s_colors)) {
return "unknown";
}
return s_colors[side];
}
bool Game::IsSwapAllowed(Endpoint *endpoint) {
if (playing_) {
return false;
@ -1171,4 +1182,145 @@ bool Game::IsAnonBlockAllowed(Endpoint *endpoint) {
return true;
}
void Game::SetAllies(SideMask side, SideMask sidmAllies) {
Player *player = HumanPlayerFromColorChar(ColorCharFromSide(side));
if (player != NULL)
player->SetAllies(sidmAllies);
}
Player *Game::HumanPlayerFromEndpoint(Endpoint *endpoint) {
Player *pplr;
for (int i = 0; i < kcPlayersMax; i++) {
pplr = playerMgr_.GetPlayer(i);
if (pplr->endpoint() == endpoint) {
break;
} else {
pplr = NULL;
}
}
if (pplr == NULL) {
return NULL;
}
if (pplr->endpoint() == NULL) {
return NULL;
}
if (pplr->flags() & (kfPlrComputer | kfPlrComputerOvermind |
kfPlrUnfulfilled | kfPlrObserver | kfPlrDisconnectBroadcasted)) {
return NULL;
}
if ((pplr->flags() & kfPlrInUse) == 0) {
return NULL;
}
return pplr;
}
void Game::SendTeamChat(Endpoint *endpoint, const char *chat, const char *unfiltered) {
if (endpoint == NULL) {
return;
}
if (!CanSendTeamChat(endpoint, true)) {
return;
}
// This won't include observing players
Player *pendplr = HumanPlayerFromEndpoint(endpoint);
if (pendplr == NULL) {
return;
}
// Player name
const char *name = base::Format::ToString("%s to team", endpoint->GetChatName().c_str());
// Players
Player *playerBlue, *playerRed, *playerYellow, *playerCyan;
std::vector<Player *> players;
players.push_back(playerBlue);
players.push_back(playerRed);
players.push_back(playerYellow);
players.push_back(playerCyan);
// The endpoint sending the chat sees it regardless of the value in pendplr->allies()
endpoint->xpump().Send(XMsgGameReceiveChat::ToBuffer(name, chat));
// If this endpoint is a mod, send unfiltered chat too
if (unfiltered != NULL && endpoint->seechat()) {
endpoint->xpump().Send(XMsgGameReceiveChat::ToBuffer("", unfiltered));
}
SideMask sides[kcPlayersMax] = {ksideNeutral, ksidmSide1, ksidmSide2, ksidmSide3, ksidmSide4};
// Loop through the four human sides
for (int i = 1; i < kcPlayersMax; i++) {
// Is this an ally?
if (pendplr->allies() & sides[i]) {
// Skip if this ally is the sending player
if (pendplr->side() == i)
continue;
// This won't include observing players
players[i] = HumanPlayerFromColorChar(ColorCharFromSide(i));
if (players[i] == NULL)
continue;
// Is this ally muted?
if (players[i]->endpoint()->muted())
continue;
// Send the message to the ally
players[i]->endpoint()->xpump().Send(
XMsgGameReceiveChat::ToBuffer(name, chat));
// Send the unfiltered version if the ally is a mod
if (unfiltered != NULL && players[i]->endpoint()->seechat()) {
players[i]->endpoint()->xpump().Send(
XMsgGameReceiveChat::ToBuffer("", unfiltered));
}
// Log the chat
Room *room = server_.lobby().FindRoom(roomid_);
const char *pszRoomName = NULL;
bool private_room = false;
if (room != NULL) {
pszRoomName = room->name();
private_room = (room->password()[0] != 0);
}
if (unfiltered != NULL) {
server_.logger().LogGameChat(endpoint, roomid_, pszRoomName,
private_room, id(), info().title(), unfiltered);
} else {
server_.logger().LogGameChat(endpoint, roomid_, pszRoomName,
private_room, id(), info().title(), chat);
}
}
}
}
bool Game::CanSendTeamChat(Endpoint *endpoint, bool broadcast) {
// Game not started yet
if (!playing()) {
if (broadcast) {
endpoint->xpump().Send(XMsgGameReceiveChat::ToBuffer("",
"You cannot use team chat until the game starts."));
}
return false;
}
Player *pplr = HumanPlayerFromEndpoint(endpoint);
if (pplr == NULL) {
// If pplr is NULL, assume it's because the player is observing
if (broadcast) {
endpoint->xpump().Send(XMsgGameReceiveChat::ToBuffer("",
"You cannot use team chat while in observe mode."));
}
return false;
}
return true;
}
} // namespace wi

View File

@ -54,6 +54,8 @@ public:
void RemovePlayer(Endpoint *endpoint, int nReason, bool disconnect = true);
void SendChat(Endpoint *endpoint, const char *chat,
const char *unfiltered = NULL);
void SendTeamChat(Endpoint *endpoint, const char *chat,
const char *unfiltered = NULL);
void SendAdminChat(const char *name, const char *chat,
bool mods_only = false);
void OnNetMessage(Endpoint *endpoint, NetMessage *pnm);
@ -63,6 +65,8 @@ public:
void OnHeartbeat();
std::vector<std::string> GetIdsString(Endpoint *endpoint);
void KickPlayers();
void SetAllies(SideMask side, SideMask sidmAllies);
bool CanSendTeamChat(Endpoint *endpoint, bool broadcast);
base::signal1<Game *> SignalOnDelete;
base::signal1<Game *> SignalOnInProgress;
@ -96,6 +100,8 @@ private:
std::string *response, bool *broadcast);
const char *ColorFromSide(int side);
Player *HumanPlayerFromColorChar(const char *psz);
Player *HumanPlayerFromEndpoint(Endpoint *endpoint);
const char *ColorCharFromSide(int side);
void SwapPlayersCommand(Endpoint *endpoint, const char *chat,
std::string *response);

View File

@ -163,6 +163,9 @@ int main(int argc, char **argv)
bool checksync = FindArg(argc, argv, "--checksync");
RLOG() << "Sync checking turned " << (checksync ? "ON." : "OFF.");
bool accountsharing = FindArg(argc, argv, "--accountsharing");
RLOG() << "Account sharing turned " << (accountsharing ? "ON." : "OFF.");
std::string log_file = ParseString(argc, argv, "--log_file");
wi::XMsgLog *xmsglog = NULL;
if (log_file.size() != 0) {
@ -179,7 +182,7 @@ int main(int argc, char **argv)
wi::Server server(stats, xmsglog, cache, server_id, checksync,
max_rooms, max_games_per_room, max_players_per_room,
max_players, modfile, badwordsfile);
max_players, modfile, badwordsfile, accountsharing);
base::SocketAddress listen_address = GetListenAddress(argc, argv);
if (!server.Listen(listen_address)) {

View File

@ -59,6 +59,8 @@ public:
bool statslocked() { return havestats_ && (ws_.ff & kfwsLocked) != 0; }
const base::SocketAddress& address() { return address_; }
const char *did() { return did_; }
SideMask allies() { return allies_; }
void SetAllies(SideMask sm) { allies_ = sm; }
private:
base::SocketAddress address_;
@ -80,6 +82,7 @@ private:
bool havestats_;
bool anonymous_;
char did_[64];
SideMask allies_;
};
} // namespace wi

View File

@ -23,14 +23,15 @@ const dword kffEndpointIdFreeMaskAfterShift = 0x1f;
Server::Server(StatsPoster& poster, XMsgLog *log, LevelInfoCache& cache,
dword id, bool checksync, int max_rooms, int max_games_per_room,
int max_players_per_room, int max_players,
const std::string& modlist_path, const std::string& badwords_path) :
const std::string& modlist_path, const std::string& badwords_path,
bool account_sharing) :
poster_(poster), log_(log), cache_(cache),
lobby_(this, max_rooms, max_games_per_room, max_players_per_room),
id_(id), checksync_(checksync), max_players_(max_players),
modlist_watcher_(modlist_path), badwords_(badwords_path),
listener_(NULL), gameidCounter_(1), endpointidCounter_(1),
endpoint_count_thread_safe_(0), updater_(NULL),
logger_("log", id), anons_allowed_(true) {
logger_("log", id), anons_allowed_(true), account_sharing_(account_sharing) {
start_time_ = base::GetSecondsUnixEpocUTC();
@ -372,4 +373,47 @@ void Server::SetAnonsAllowed(bool anons_allowed) {
anons_allowed_ = anons_allowed;
}
bool Server::SharedAccountExists(Endpoint *endpointAsker, const char *name) {
EndpointMap::iterator it = endpointmap_.begin();
if (it->second->name() != NULL) {
for (; it != endpointmap_.end(); it++) {
// Do the names match?
if (strcmp(name, it->second->name()) == 0) {
// Don't count endpointAsker
if (endpointAsker->id() != it->second->id()) {
// We found a shared account
return true;
}
}
}
}
return false;
}
void Server::DisconnectSharedAccounts(Endpoint *endpointAsker, const char *name) {
EndpointMap::iterator it = endpointmap_.begin();
if (it->second->name() != NULL) {
for (; it != endpointmap_.end(); it++) {
// Do the names match?
if (strcmp(name, it->second->name()) == 0) {
// Son't disconnect the asker, only other endpoints
if (endpointAsker->id() != it->second->id()) {
// We found a shared account, dispose of it
it->second->Dispose();
}
}
}
}
}
bool Server::AccountSharing() {
return account_sharing_;
}
} // namespace wi

View File

@ -33,7 +33,8 @@ public:
Server(StatsPoster& stats, XMsgLog *log, LevelInfoCache& cache,
dword id, bool checksync, int max_rooms, int max_games_per_room,
int max_players_per_room, int max_players,
const std::string& modlist_path, const std::string& badwords_path);
const std::string& modlist_path, const std::string& badwords_path,
bool account_sharing);
~Server();
bool Listen(const base::SocketAddress& addr);
@ -45,12 +46,15 @@ public:
bool IsModerator(const char *name);
bool IsAdmin(const char *name);
bool AnonsAllowed();
bool AccountSharing();
void SetAnonsAllowed(bool anons_allowed);
dword GetChatterId(Endpoint *endpointAsker, Endpoint *endpoint);
Endpoint *GetEndpointFromChatterId(dword id);
const char *GetChatRules();
std::string GetAnnouncements();
void SetAnnouncements(std::string announcements);
bool SharedAccountExists(Endpoint *endpointAsker, const char *name);
void DisconnectSharedAccounts(Endpoint *endpointAsker, const char *name);
ChatLimiter& chatlimiter() { return chatlimiter_; }
LevelInfoCache& cache() { return cache_; }
@ -89,6 +93,7 @@ private:
LevelInfoCache& cache_;
bool checksync_;
bool anons_allowed_;
bool account_sharing_;
dword gameidCounter_;
dword endpointidCounter_;
dword start_time_;