hostile-takeover/game/lobbyform.cpp
Nathan Fulton 72566c33bd Add server feature for clients to receive chats while in lobby
Clients can receive chats while in lobby state by having the shell form
present a HtMessageBox with the chat and the player is it from. This
feature was designed to be used with the moderator whisper command.
2016-08-31 22:43:35 -04:00

389 lines
11 KiB
C++

#include "game/lobbyform.h"
#include "game/createroomform.h"
#include "game/roomform.h"
#include "server/room.h"
namespace wi {
LobbyForm::LobbyForm(LoginHandler& handler, const std::string& server_name) :
handler_(handler), server_name_(server_name), refresh_(true),
lurkers_(0), zipdone_(false), selected_main_(false) {
}
LobbyForm::~LobbyForm() {
}
void LobbyForm::ShowJoinMessage(dword result) {
// Show an appropriate message if it was not a success
const char *message = NULL;
switch (result) {
case knLobbyJoinResultSuccess:
break;
case knLobbyJoinResultNotLoggedIn:
message = "Not logged in";
break;
case knLobbyJoinResultFull:
message = "Lobby is full, try again later.";
break;
case knLobbyJoinResultFail:
default:
message = "Failure entering lobby";
break;
}
if (message != NULL) {
HtMessageBox(kfMbWhiteBorder, "Enter Lobby Problem", message);
}
}
dword LobbyForm::DoForm(LoginHandler &handler, const std::string& server_name,
RoomInfo *joininfo) {
// The user is logged in by the time this gets called.
LobbyForm *pfrm = (LobbyForm *)gpmfrmm->LoadForm(gpiniForms, kidfLobby,
new LobbyForm(handler, server_name));
if (pfrm == NULL) {
return false;
}
int result = 0;
pfrm->DoModal(&result);
*joininfo = pfrm->joininfo();
delete pfrm;
if (result == kidcSignOut) {
return knLobbyResultSignOut;
}
if (result == kidcCancel) {
return knLobbyResultDone;
}
if (result == kidcJoinRoom) {
return knLobbyResultEnterRoom;
}
return knLobbyResultDone;
}
bool LobbyForm::DoModal(int *presult, Sfx sfxShow, Sfx sfxHide) {
char name[kcbPlayerName*2];
handler_.GetPlayerName(name, sizeof(name));
LabelControl *plbl = (LabelControl *)GetControlPtr(kidcPlayerName);
plbl->Show(false);
plbl = (LabelControl *)GetControlPtr(kidcPlayerNameLabel);
const char *s = base::Format::ToString("%s / %s", name,
server_name_.c_str());
plbl->SetText(s);
ListControl *plstc = (ListControl *)GetControlPtr(kidcRoomList);
Rect rcList;
plstc->GetRect(&rcList);
Font *pfnt = plstc->GetFont();
int cxPrivate = pfnt->GetTextExtent("PRIVATE");
int cxStart = rcList.Width() / 20; // 10;
plstc->SetTabStops(0, cxStart, rcList.Width() - cxStart - cxPrivate);
plstc->SetTabFlags(0, kfLstTabEllipsis, 0);
GetControlPtr(kidcJoinRoom)->Show(false);
Show(true);
gptra->SetCallback(this);
dword result = gptra->JoinLobby(this);
if (result != knLobbyJoinResultSuccess) {
gptra->SetCallback(NULL);
ShowJoinMessage(result);
*presult = 0;
return false;
}
bool success = ShellForm::DoModal(presult, sfxShow, sfxHide);
gptra->LeaveLobby();
gptra->SetCallback(NULL);
return success;
}
void LobbyForm::OnControlSelected(word idc) {
switch (idc) {
case kidcNewRoom:
OnCreateRoom();
break;
case kidcJoinRoom:
OnJoinRoom();
break;
case kidcCancel:
case kidcSignOut:
EndForm(idc);
break;
}
}
void LobbyForm::OnControlNotify(word idc, int nNotify) {
if (idc == kidcRoomList && nNotify == knNotifySelectionChange) {
Refresh(0);
}
Form::OnControlNotify(idc, nNotify);
}
void LobbyForm::OnJoinRoom() {
ListControl *plstc = (ListControl *)GetControlPtr(kidcRoomList);
dword roomid = (dword)(pword)plstc->GetSelectedItemData();
RoomMap::iterator it = map_.find(roomid);
if (it == map_.end()) {
return;
}
if (it->second.priv) {
HostInitiateAsk("Enter Password:", kcbPassword - 1,
it->second.password.c_str(), knKeyboardAskDefault,
true);
return;
}
InitiateJoinRoom(it->second);
}
void LobbyForm::OnCreateRoom() {
char roomname[kcbRoomname];
char password[kcbPassword];
if (!CreateRoomForm::DoForm(roomname, sizeof(roomname), password,
sizeof(password))) {
return;
}
if (gptra == NULL) {
return;
}
dword roomid;
dword result = gptra->CreateRoom(roomname, password, &roomid);
switch (result) {
case knLobbyCreateRoomResultSuccess:
{
// Update the list and select the created room, in case
// the join fails.
Refresh(-1);
ListControl *plstc = (ListControl *)GetControlPtr(kidcRoomList);
refresh_ = false;
plstc->Select(FindIndex(roomid), true, true);
refresh_ = true;
// OnAddRoom has been called already. Shove the password
// into the info and join the room.
RoomMap::iterator it = map_.find(roomid);
if (it != map_.end()) {
it->second.password = password;
InitiateJoinRoom(it->second);
}
}
break;
case knLobbyCreateRoomResultFail:
HtMessageBox(kfMbWhiteBorder, "Create Room",
"Error creating this room.");
break;
case knLobbyCreateRoomResultFull:
HtMessageBox(kfMbWhiteBorder, "Create Room", "Too many rooms. Join an existing room");
break;
case knLobbyCreateRoomResultExists:
HtMessageBox(kfMbWhiteBorder, "Create Room",
"A room with this name already exists.");
break;
}
}
int LobbyForm::FindIndex(dword roomid) {
int index = 0;
RoomMap::iterator it = map_.begin();
for (; it != map_.end(); it++) {
if (it->first == roomid) {
return index;
}
index++;
}
return -1;
}
void LobbyForm::InitiateJoinRoom(const RoomInfo& info) {
if (gptra == NULL) {
return;
}
// Before joining, check to see if this room is joinable.
// Actually joining also checks, but this is a way to provide the user
// with feedback before exiting this form (actual joining happens
// in RoomForm).
dword result = gptra->CanJoinRoom(info.roomid, info.password.c_str());
RoomForm::ShowJoinMessage(result);
switch (result) {
case knRoomJoinResultWrongPassword:
OnJoinRoom();
break;
case knRoomJoinResultSuccess:
joininfo_ = info;
EndForm(kidcJoinRoom);
break;
}
}
void LobbyForm::Refresh(int ct) {
if (!refresh_) {
return;
}
if (ct == -1) {
timer_.Stop();
OnTimeout(0);
return;
}
if (ct == 0) {
timer_.Stop();
}
if (timer_.IsStarted()) {
return;
}
timer_.Start(this, ct * 10);
}
void LobbyForm::OnTimeout(int id) {
refresh_ = false;
ListControl *plstc = (ListControl *)GetControlPtr(kidcRoomList);
dword roomid = (dword)(pword)plstc->GetSelectedItemData();
if (!selected_main_) {
roomid = kroomidMain;
}
plstc->Clear();
RoomMap::iterator it = map_.begin();
for (; it != map_.end(); it++) {
RoomInfo& info = it->second;
const char *s;
if (info.priv) {
s = base::Format::ToString("\t%s (%d %s, %d %s)\tPRIVATE",
info.name.c_str(), info.cPlayers,
info.cPlayers == 1 ? "player" : "players",
info.cGames,
info.cGames == 1 ? "game" : "games");
} else {
s = base::Format::ToString("\t%s (%d %s, %d %s)",
info.name.c_str(), info.cPlayers,
info.cPlayers == 1 ? "player" : "players",
info.cGames,
info.cGames == 1 ? "game" : "games");
}
plstc->Add(s, (void *)(pword)info.roomid);
}
int selected = FindIndex(roomid);
if (selected < 0 && map_.size() != 0) {
plstc->Select(0, true, true);
} else {
plstc->Select(selected, true);
selected_main_ = true;
}
Control *pctl = GetControlPtr(kidcJoinRoom);
refresh_ = true;
pctl->Show(plstc->GetSelectedItemIndex() >= 0);
}
void LobbyForm::OnLurkerCount(dword count) {
lurkers_ = count;
if (zipdone_) {
LabelControl *plbl = (LabelControl *)GetControlPtr(kidcLurkerCount);
plbl->SetText(base::Format::ToString("Lurkers: %d", count));
}
}
void LobbyForm::OnZipDone() {
zipdone_ = true;
OnLurkerCount(lurkers_);
}
void LobbyForm::OnAddRoom(const char *name, dword roomid, bool priv,
dword cPlayers, dword cGames) {
RoomInfo info;
info.name = name;
info.roomid = roomid;
info.priv = priv;
info.cPlayers = cPlayers;
info.cGames = cGames;
map_.insert(RoomMap::value_type(roomid, info));
Refresh();
}
void LobbyForm::OnRemoveRoom(dword roomid) {
RoomMap::iterator it = map_.find(roomid);
if (it == map_.end()) {
LOG() << "Couldn't find room!";
return;
}
map_.erase(it);
Refresh();
}
void LobbyForm::OnUpdateRoom(dword roomid, dword cPlayers, dword cGames) {
RoomMap::iterator it = map_.find(roomid);
if (it == map_.end()) {
LOG() << "Couldn't find room!";
return;
}
it->second.cPlayers = cPlayers;
it->second.cGames = cGames;
Refresh();
}
void LobbyForm::OnStatusUpdate(char *pszStatus) {
}
void LobbyForm::OnConnectionClose() {
Event evt;
memset(&evt, 0, sizeof(evt));
evt.idf = m_idf;
evt.eType = connectionCloseEvent;
gevm.PostEvent(&evt);
}
void LobbyForm::OnShowMessage(const char *message) {
message_ = message;
Event evt;
memset(&evt, 0, sizeof(evt));
evt.idf = m_idf;
evt.eType = showMessageEvent;
gevm.PostEvent(&evt);
}
bool LobbyForm::OnFilterEvent(Event *pevt) {
if (pevt->eType == askStringEvent) {
if (gptra == NULL) {
return true;
}
char s[512];
HostGetAskString(s, sizeof(s));
ListControl *plstc = (ListControl *)GetControlPtr(kidcRoomList);
dword roomid = (dword)(pword)plstc->GetSelectedItemData();
RoomMap::iterator it = map_.find(roomid);
if (it != map_.end()) {
it->second.password = s;
InitiateJoinRoom(it->second);
}
return true;
}
if (pevt->eType == connectionCloseEvent) {
HtMessageBox(kfMbWhiteBorder, "Comm Problem", "The server has closed your connection.");
EndForm(kidcCancel);
return true;
}
if (pevt->eType == showMessageEvent) {
HtMessageBox(kfMbWhiteBorder, "Server Message", message_.c_str());
message_ = "";
return true;
}
return false;
}
void LobbyForm::OnReceiveChat(const char *player, const char *chat) {
const char *s = base::Format::ToString("%s: %s", player, chat);
HtMessageBox(kfMbWhiteBorder | kfMbKeepTimersEnabled, player, s);
}
} // namespace wi