mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2026-04-09 12:21:26 -06:00
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:
parent
f6dd61415f
commit
abb1823956
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) :
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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(); }
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_;
|
||||
|
||||
152
server/game.cpp
152
server/game.cpp
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user