GiantsTools/ServerConsoleExample/ServerDialog.cpp

258 lines
6.7 KiB
C++

#include "pch.h"
#include "ServerConsoleApp.h"
#include "ServerDialog.h"
IMPLEMENT_DYNAMIC(ServerDialog, CDialogEx)
ServerDialog::ServerDialog(IGameServiceProvider* serviceProvider, CWnd* parent)
: CDialogEx(IDD_SERVER, parent),
m_serviceProvider(serviceProvider)
{
const auto& pGameServer = m_serviceProvider->Get<IGameServer>();
using namespace std::placeholders;
m_playerConnectedEventHandle = pGameServer->Listen(GameServerEventType::PlayerConnected, std::bind(&ServerDialog::HandlePlayerConnected, this, _1));
m_playerDisconnectedEventHandle = pGameServer->Listen(GameServerEventType::PlayerDisconnected, std::bind(&ServerDialog::HandlePlayerDisconnected, this, _1));
m_playerChatMessageHandle = pGameServer->Listen(GameServerEventType::ChatMessage, std::bind(&ServerDialog::HandleChatMessage, this, _1));
m_worldLoadedHandle = pGameServer->Listen(GameServerEventType::WorldLoaded, std::bind(&ServerDialog::HandleWorldLoaded, this, _1));
}
ServerDialog::~ServerDialog()
{
try
{
const auto& pGameServer = m_serviceProvider->Get<IGameServer>();
pGameServer->Unlisten(GameServerEventType::PlayerConnected, m_playerConnectedEventHandle);
pGameServer->Unlisten(GameServerEventType::PlayerDisconnected, m_playerDisconnectedEventHandle);
pGameServer->Unlisten(GameServerEventType::ChatMessage, m_playerChatMessageHandle);
pGameServer->Unlisten(GameServerEventType::WorldLoaded, m_worldLoadedHandle);
}
catch (...)
{
}
}
void ServerDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CONSOLE, ConsoleEditBox);
DDX_Control(pDX, IDC_PLAYERS, PlayersListCtrl);
DDX_Control(pDX, IDC_BAN, ButtonBan);
DDX_Control(pDX, IDC_KICK, ButtonKick);
}
void __stdcall ServerDialog::TimerCallback(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
((ServerDialog*)idEvent)->RefreshPlayers();
}
void ServerDialog::CloseDialog()
{
OnCancel();
}
void ServerDialog::ShowDialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
Create(IDD_SERVER);
ShowWindow(SW_SHOW);
}
BOOL ServerDialog::OnInitDialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog::OnInitDialog();
CreateColumns();
using namespace std::placeholders;
SetTimer((UINT_PTR)this, 1000, TimerCallback);
return TRUE;
}
void ServerDialog::CreateColumns()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
PlayersListCtrl.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 40);
PlayersListCtrl.InsertColumn(1, _T("Status"), LVCFMT_LEFT, 80);
PlayersListCtrl.InsertColumn(2, _T("Ping"), LVCFMT_LEFT, 40);
PlayersListCtrl.InsertColumn(3, _T("Score"), LVCFMT_LEFT, 80);
PlayersListCtrl.InsertColumn(4, _T("Team"), LVCFMT_LEFT, 80);
for (int i = 0; i < NumColumns; i++)
{
PlayersListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
}
}
void ServerDialog::PostNcDestroy()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog::PostNcDestroy();
}
void ServerDialog::OnOK()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!UpdateData(TRUE))
return;
DestroyWindow();
}
void ServerDialog::OnCancel()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ShowWindow(SW_HIDE);
DestroyWindow();
KillTimer((UINT_PTR)this);
m_pParentWnd->SendMessage(WM_CLOSE, 0, 0);
}
void ServerDialog::RefreshPlayers()
{
if (!m_hWnd)
{
return;
}
AFX_MANAGE_STATE(AfxGetStaticModuleState());
const int savedSelection = PlayersListCtrl.GetSelectionMark();
PlayersListCtrl.DeleteAllItems();
const auto& pTextLookupService = m_serviceProvider->Get<ITextLookupService>();
const auto& pGameServer = m_serviceProvider->Get<IGameServer>();
for (const auto& player : pGameServer->GetPlayers())
{
if (player->host)
{
continue; // Skip host player
}
LVITEM item{};
item.cColumns = NumColumns;
item.mask = LVIF_COLUMNS | LVIF_PARAM;
item.lParam = player->index;
const int index = PlayersListCtrl.InsertItem(&item);
PlayersListCtrl.SetItemText(index, 0, player->name.c_str());
PlayersListCtrl.SetItemText(index, 1, pTextLookupService->GetNetPlayerStateName(player->state).c_str());
PlayersListCtrl.SetItemText(index, 2, fmt::format(_T("{0}"), player->ping).c_str());
PlayersListCtrl.SetItemText(index, 3, fmt::format(_T("{0}"), player->score).c_str());
PlayersListCtrl.SetItemText(index, 4, pTextLookupService->GetPlayerTeamName(player->team).c_str());
}
PlayersListCtrl.SetSelectionMark(savedSelection);
}
EventListenerResult ServerDialog::HandlePlayerConnected(const GameServerEvent& event)
{
RefreshPlayers();
return EventListenerResult::Continue;
}
EventListenerResult ServerDialog::HandlePlayerDisconnected(const GameServerEvent& event)
{
RefreshPlayers();
return EventListenerResult::Continue;
}
EventListenerResult ServerDialog::HandleChatMessage(const GameServerEvent& event)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
const auto& chatMessageEvent = (const ChatMessageEvent&)event;
ConsoleEditBox.SetSel(-1, 0);
ConsoleEditBox.ReplaceSel(chatMessageEvent.message.data());
ConsoleEditBox.SetSel(-1, 0);
ConsoleEditBox.ReplaceSel("\n");
return EventListenerResult::Continue;
}
EventListenerResult ServerDialog::HandleWorldLoaded(const GameServerEvent& event)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
const auto& pGameServer = m_serviceProvider->Get<IGameServer>();
auto details = pGameServer->GetGameDetails();
return EventListenerResult::Continue;
// TODO: Connect to world state controls
}
BEGIN_MESSAGE_MAP(ServerDialog, CDialogEx)
ON_BN_CLICKED(IDC_BAN, &ServerDialog::OnBnClickedBan)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_PLAYERS, &ServerDialog::OnItemChanged)
ON_BN_CLICKED(IDC_KICK, &ServerDialog::OnBnClickedKick)
END_MESSAGE_MAP()
// ServerDialog message handlers
void ServerDialog::OnBnClickedBan()
{
const int selection = PlayersListCtrl.GetSelectionMark();
if (selection == -1)
{
return;
}
const PlayerIndex playerIndex = (PlayerIndex)PlayersListCtrl.GetItemData(selection);
if (playerIndex > 0)
{
const auto& pGameServer = m_serviceProvider->Get<IGameServer>();
pGameServer->BanPlayer(playerIndex);
}
}
void ServerDialog::OnBnClickedKick()
{
const int selection = PlayersListCtrl.GetSelectionMark();
if (selection == -1)
{
return;
}
const PlayerIndex playerIndex = (PlayerIndex)PlayersListCtrl.GetItemData(selection);
if (playerIndex > 0)
{
const auto& pGameServer = m_serviceProvider->Get<IGameServer>();
pGameServer->KickPlayer(playerIndex, KickReason::Removed);
}
}
void ServerDialog::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
const LPNMLISTVIEW pNMListView = (const LPNMLISTVIEW)(pNMHDR);
if (!(pNMListView->uChanged & LVIF_STATE))
{
return;
}
if ((pNMListView->uOldState & LVIS_SELECTED) == (pNMListView->uNewState & LVIS_SELECTED))
{
return;
}
ButtonKick.EnableWindow(TRUE);
ButtonBan.EnableWindow(TRUE);
*pResult = 0;
}