openclonk/src/network/C4League.cpp

714 lines
24 KiB
C++
Raw Permalink Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2006-2009, RedWolf Design GmbH, http://www.clonk.de/
2016-04-03 18:18:29 +00:00
* Copyright (c) 2009-2016, The OpenClonk Team and contributors
2009-05-08 13:28:41 +00:00
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
2009-05-08 13:28:41 +00:00
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
2009-05-08 13:28:41 +00:00
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
2009-05-08 13:28:41 +00:00
*/
/* engine handler of league system */
#include "C4Include.h"
#include "network/C4League.h"
2009-05-08 13:28:41 +00:00
#include "control/C4RoundResults.h"
#include "graphics/C4GraphicsResource.h"
2009-05-08 13:28:41 +00:00
// *** C4LeagueRequestHead
void C4LeagueRequestHead::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdEnumEntry<C4LeagueAction> Actions[] =
2010-03-28 18:58:01 +00:00
{
{ "Start", C4LA_Start },
{ "Update", C4LA_Update },
{ "End", C4LA_End },
{ "Join", C4LA_PlrAuthCheck },
2009-05-08 13:28:41 +00:00
2010-03-28 18:58:01 +00:00
{ "", C4LA_RefQuery },
{ "Auth", C4LA_PlrAuth },
2009-05-08 13:28:41 +00:00
2010-03-28 18:58:01 +00:00
{ "ReportDisconnect", C4LA_ReportDisconnect },
};
2009-05-08 13:28:41 +00:00
pComp->Value(mkNamingAdapt(mkEnumAdaptT<uint8_t>(eAction, Actions), "Action", C4LA_RefQuery));
pComp->Value(mkNamingAdapt(mkParAdapt(CSID, StdCompiler::RCT_IdtfAllowEmpty), "CSID", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(AUID, StdCompiler::RCT_IdtfAllowEmpty), "AUID", ""));
2009-05-08 13:28:41 +00:00
// Auth
pComp->Value(mkNamingAdapt(mkParAdapt(Account, StdCompiler::RCT_All), "Account", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(Password, StdCompiler::RCT_All), "Password", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(NewAccount, StdCompiler::RCT_All), "NewAccount", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(NewPassword, StdCompiler::RCT_All), "NewPassword", ""));
pComp->Value(mkNamingAdapt(fRememberLogin, "RememberLogin", false));
2009-05-08 13:28:41 +00:00
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueRequestHead::SetAuth(const char *szAccount, const char *szPassword, bool fRememberLogin)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Account = szAccount;
Password = szPassword;
this->fRememberLogin = fRememberLogin;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueRequestHead::SetNewAccount(const char *szNewAccount)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
NewAccount = szNewAccount;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueRequestHead::SetNewPassword(const char *szNewPassword)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
NewPassword = szNewPassword;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueReportDisconnectHead
void C4LeagueReportDisconnectHead::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
// inherited fields
C4LeagueRequestHead::CompileFunc(pComp);
// reason
StdEnumEntry<C4LeagueDisconnectReason> Reasons[] =
2010-03-28 18:58:01 +00:00
{
{ "", C4LDR_Unknown },
{ "ConnectionFailed", C4LDR_ConnectionFailed},
{ "Desync", C4LDR_Desync },
};
pComp->Value(mkNamingAdapt(mkEnumAdaptT<uint8_t>(eReason, Reasons), "Reason", C4LDR_Unknown));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueRequestHeadEnd
void C4LeagueRequestHeadEnd::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4LeagueRequestHead::CompileFunc(pComp);
pComp->Value(mkNamingAdapt(mkParAdapt(RecordName, StdCompiler::RCT_All), "RecordName", ""));
2010-03-28 18:58:01 +00:00
if (RecordName.getLength())
2009-05-08 13:28:41 +00:00
pComp->Value(mkNamingAdapt(mkHexAdapt(RecordSHA, sizeof(RecordSHA)), "RecordSHA"));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueResponseHead
void C4LeagueResponseHead::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
pComp->Value(mkNamingAdapt(mkParAdapt(Status, StdCompiler::RCT_IdtfAllowEmpty), "Status", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(CSID, StdCompiler::RCT_IdtfAllowEmpty), "CSID", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(Message, StdCompiler::RCT_All), "Message", ""));
2009-05-08 13:28:41 +00:00
// Auth
pComp->Value(mkNamingAdapt(mkParAdapt(Account, StdCompiler::RCT_All), "Account", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(AUID, StdCompiler::RCT_All), "AUID", ""));
2009-05-08 13:28:41 +00:00
pComp->Value(mkNamingAdapt(mkParAdapt(FBID, StdCompiler::RCT_All), "FBID", ""));
pComp->Value(mkNamingAdapt(mkParAdapt(LoginToken, StdCompiler::RCT_All), "LoginToken", ""));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueResponseHeadStart
void C4LeagueResponseHeadStart::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Base members
C4LeagueResponseHead::CompileFunc(pComp);
// League name
pComp->Value(mkNamingAdapt(League, "League", ""));
pComp->Value(mkNamingAdapt(StreamingAddr, "StreamTo", ""));
pComp->Value(mkNamingCountAdapt(fHaveSeed, "Seed"));
2010-03-28 18:58:01 +00:00
if (fHaveSeed)
2009-05-08 13:28:41 +00:00
pComp->Value(mkNamingAdapt(iSeed, "Seed", (int32_t)0));
pComp->Value(mkNamingAdapt(iMaxPlayers, "MaxPlayers", (int32_t)0));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueResponseHeadUpdate
void C4LeagueResponseHeadUpdate::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Base members
C4LeagueResponseHead::CompileFunc(pComp);
// League name
pComp->Value(mkNamingAdapt(League, "League", ""));
// player infos
pComp->Value(mkNamingAdapt(PlrInfos, "PlayerInfos"));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueRequestHeadAuthCheck
int32_t C4LeagueResponseHeadAuthCheck::getScore(const char *szLeague) const
2010-03-28 18:58:01 +00:00
{
for (int32_t i = 0; i < C4NetMaxLeagues; i++)
if (Leagues[i] == szLeague)
2009-05-08 13:28:41 +00:00
return Scores[i];
return 0;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
int32_t C4LeagueResponseHeadAuthCheck::getRank(const char *szLeague) const
2010-03-28 18:58:01 +00:00
{
for (int32_t i = 0; i < C4NetMaxLeagues; i++)
if (Leagues[i] == szLeague)
2009-05-08 13:28:41 +00:00
return Ranks[i];
return 0;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
int32_t C4LeagueResponseHeadAuthCheck::getRankSymbol(const char *szLeague) const
2010-03-28 18:58:01 +00:00
{
for (int32_t i = 0; i < C4NetMaxLeagues; i++)
if (Leagues[i] == szLeague)
2009-05-08 13:28:41 +00:00
return RankSymbols[i];
return 0;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
const char *C4LeagueResponseHeadAuthCheck::getProgressData(const char *szLeague) const
{
// progress data is the same for all leagues
return ProgressData.getData();
}
2009-05-08 13:28:41 +00:00
void C4LeagueResponseHeadAuthCheck::CompileFunc(StdCompiler *pComp)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Base members
C4LeagueResponseHead::CompileFunc(pComp);
// Leagues, Scores, Ranks
pComp->Value(mkNamingAdapt(mkArrayAdapt(Leagues, C4NetMaxLeagues, ""), "League"));
pComp->Value(mkNamingAdapt(mkArrayAdapt(Scores, C4NetMaxLeagues, 0), "Score"));
pComp->Value(mkNamingAdapt(mkArrayAdapt(Ranks, C4NetMaxLeagues, 0), "Rank"));
pComp->Value(mkNamingAdapt(mkArrayAdapt(RankSymbols, C4NetMaxLeagues, 0), "RankSymbol"));
// Progress data (per scenario; not per league)
pComp->Value(mkNamingAdapt(mkParAdapt(ProgressData, StdCompiler::RCT_All), "ProgressData", ""));
2009-05-08 13:28:41 +00:00
// Clan tag
pComp->Value(mkNamingAdapt(mkParAdapt(ClanTag, StdCompiler::RCT_All), "ClanTag", ""));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueFBIDList
void C4LeagueFBIDList::Clear()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
while (pFirst)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
FBIDItem *pDel = pFirst;
pFirst = pDel->pNext;
delete pDel;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueFBIDList::FindFBIDByAccount(const char *szAccount, StdStrBuf *pFBIDOut)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert(szAccount);
if (!szAccount) return false;
for (FBIDItem *pItem = pFirst; pItem; pItem = pItem->pNext)
if (pItem->Account == szAccount)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (pFBIDOut) pFBIDOut->Copy(pItem->FBID);
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
return false;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueFBIDList::RemoveFBIDByAccount(const char *szAccount)
2010-03-28 18:58:01 +00:00
{
FBIDItem *pPrev = nullptr, *pItem = pFirst;
2010-03-28 18:58:01 +00:00
while (pItem)
{
2009-05-08 13:28:41 +00:00
// Delete?
2010-03-28 18:58:01 +00:00
if (pItem->Account == szAccount)
{
2009-05-08 13:28:41 +00:00
(pPrev ? pPrev->pNext : pFirst) = pItem->pNext;
delete pItem;
return;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Next
pPrev = pItem; pItem = pItem->pNext;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueFBIDList::AddFBID(const char *szFBID, const char *szAccount)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// add new FBID item to head of list
assert(szFBID); assert(szAccount);
// remove any existing FBIDs
RemoveFBIDByAccount(szAccount);
// add new entry
FBIDItem *pNewItem = new FBIDItem();
pNewItem->FBID.Copy(szFBID);
pNewItem->Account.Copy(szAccount);
pNewItem->pNext = pFirst;
pFirst = pNewItem;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
class DisconnectData
2010-03-28 18:58:01 +00:00
{
private:
C4LeagueFBIDList &rFBIDList;
const C4ClientPlayerInfos &rPlayerInfos;
public:
DisconnectData(C4LeagueFBIDList &rFBIDList, const C4ClientPlayerInfos &rPlayerInfos)
2009-05-08 13:28:41 +00:00
: rFBIDList(rFBIDList), rPlayerInfos(rPlayerInfos) {}
2010-03-28 18:58:01 +00:00
void CompileFunc(StdCompiler *pComp)
{
if (pComp->isDeserializer())
2010-03-28 18:58:01 +00:00
{
// compiling not yet needed
assert(!"DisconnectData::CompileFunc not defined for compiler!");
}
else
{
// decompiling: Compile all joined and not removed player infos.
// Compile them even if they're not in the FBID-List, but omit
// the FBID (used for host message)
int32_t i=0; C4PlayerInfo *pInfo;
while ((pInfo = rPlayerInfos.GetPlayerInfo(i++)))
if (pInfo->IsJoined() && !pInfo->IsRemoved())
2009-05-08 13:28:41 +00:00
{
2010-03-28 18:58:01 +00:00
pComp->Name("Player");
try
{
pComp->Value(mkNamingAdapt(mkDecompileAdapt(pInfo->GetID()), "ID"));
StdCopyStrBuf sFBID;
if (rFBIDList.FindFBIDByAccount(pInfo->getLeagueAccount(), &sFBID)) pComp->Value(mkNamingAdapt(mkParAdapt(sFBID, StdCompiler::RCT_IdtfAllowEmpty), "FBID"));
}
catch (StdCompiler::Exception *)
{
2009-05-08 13:28:41 +00:00
pComp->NameEnd();
2010-03-28 18:58:01 +00:00
throw;
}
pComp->NameEnd();
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
}
};
2009-05-08 13:28:41 +00:00
// *** C4LeagueClient
bool C4LeagueClient::Start(const C4Network2Reference &Ref)
2010-03-28 18:58:01 +00:00
{
// Create query
eCurrAction = C4LA_Start;
2009-05-08 13:28:41 +00:00
C4LeagueRequestHead Head(eCurrAction);
StdStrBuf QueryText = DecompileToBuf<StdCompilerINIWrite>(
2010-03-28 18:58:01 +00:00
mkInsertAdapt(
mkNamingAdapt(Head, "Request"),
mkNamingAdapt(mkDecompileAdapt(Ref), "Reference"),
false));
// Perform query
2009-05-08 13:28:41 +00:00
return Query(QueryText.getData(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::GetStartReply(StdStrBuf *pMessage, StdStrBuf *pLeague, StdStrBuf *pStreamingAddr, int32_t *pSeed, int32_t *pMaxPlayers)
2010-03-28 18:58:01 +00:00
{
if (!isSuccess() || eCurrAction != C4LA_Start) return false;
// Parse response head
C4LeagueResponseHeadStart Head;
2010-03-28 18:58:01 +00:00
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(Head, "Response"), ResultString, "Start Reply"))
2009-05-08 13:28:41 +00:00
return false;
// Get message, league and seed
2010-03-28 18:58:01 +00:00
if (pMessage)
pMessage->Copy(Head.getMessage());
2010-03-28 18:58:01 +00:00
if (pLeague)
2009-05-08 13:28:41 +00:00
pLeague->Copy(Head.getLeague());
2010-03-28 18:58:01 +00:00
if (pStreamingAddr)
2009-05-08 13:28:41 +00:00
pStreamingAddr->Copy(Head.getStreamingAddr());
2010-03-28 18:58:01 +00:00
if (pSeed && Head.haveSeed())
2009-05-08 13:28:41 +00:00
*pSeed = Head.getSeed();
2010-03-28 18:58:01 +00:00
if (pMaxPlayers)
2009-05-08 13:28:41 +00:00
*pMaxPlayers = Head.getMaxPlayers();
// No success?
2010-03-28 18:58:01 +00:00
if (!Head.isSuccess())
return false;
// Got no CSID or empty CSID?
if (!Head.getCSID() || !*Head.getCSID() || *Head.getCSID() == '\0')
2010-03-28 18:58:01 +00:00
{
if (pMessage)
2009-05-08 13:28:41 +00:00
pMessage->Copy(LoadResStr("IDS_LGA_INVALIDRESPONSE3"));
return false;
2010-03-28 18:58:01 +00:00
}
// So save back CSID
CSID = Head.getCSID();
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::Update(const C4Network2Reference &Ref)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert(CSID.getLength());
// Create query
eCurrAction = C4LA_Update;
2009-05-08 13:28:41 +00:00
C4LeagueRequestHead Head(eCurrAction, CSID.getData());
StdStrBuf QueryText = DecompileToBuf<StdCompilerINIWrite>(
2010-03-28 18:58:01 +00:00
mkInsertAdapt(
mkNamingAdapt(Head, "Request"),
mkNamingAdapt(mkDecompileAdapt(Ref), "Reference"),
false));
// Perform query
2009-05-08 13:28:41 +00:00
return Query(QueryText.getData(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::GetUpdateReply(StdStrBuf *pMessage, C4ClientPlayerInfos *pPlayerLeagueInfos)
2010-03-28 18:58:01 +00:00
{
C4LeagueResponseHeadUpdate Reply;
2010-03-28 18:58:01 +00:00
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(Reply, "Response"), ResultString, "Update Reply"))
2009-05-08 13:28:41 +00:00
return false;
// Get message
2010-03-28 18:58:01 +00:00
if (pMessage)
pMessage->Copy(Reply.getMessage());
// get plr infos
if (pPlayerLeagueInfos)
*pPlayerLeagueInfos = Reply.GetPlrInfos();
// Success
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::End(const C4Network2Reference &Ref, const char *szRecordName, const BYTE *pRecordSHA)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert(CSID.getLength());
// Create query
eCurrAction = C4LA_End;
2009-05-08 13:28:41 +00:00
C4LeagueRequestHeadEnd Head(eCurrAction, CSID.getData(), szRecordName, pRecordSHA);
StdStrBuf QueryText = DecompileToBuf<StdCompilerINIWrite>(
2010-03-28 18:58:01 +00:00
mkInsertAdapt(
mkNamingAdapt(Head, "Request"),
mkNamingAdapt(mkDecompileAdapt(Ref), "Reference"),
false));
// Perform query
2009-05-08 13:28:41 +00:00
return Query(QueryText.getData(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::GetEndReply(StdStrBuf *pMessage, C4RoundResultsPlayers *pRoundResults)
2010-03-28 18:58:01 +00:00
{
// Parse response head
C4LeagueResponseHead Head;
2010-03-28 18:58:01 +00:00
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(Head, "Response"), ResultString, "End Reply"))
2009-05-08 13:28:41 +00:00
return false;
// Get message
2010-03-28 18:58:01 +00:00
if (pMessage)
pMessage->Copy(Head.getMessage());
2010-03-28 18:58:01 +00:00
if (pRoundResults)
CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(mkNamingAdapt(*pRoundResults, "PlayerInfos"), "Response"), ResultString, "Round Results");
// Done
return Head.isSuccess();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::Auth(const C4PlayerInfo &PlrInfo, const char *szAccount, const char *szPassword, const char *szNewAccount, const char *szNewPassword, bool fRememberLogin)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Build header
eCurrAction = C4LA_PlrAuth;
2009-05-08 13:28:41 +00:00
C4LeagueRequestHead Head(eCurrAction);
Head.SetAuth(szAccount, szPassword, fRememberLogin);
2010-03-28 18:58:01 +00:00
if (szNewAccount)
2009-05-08 13:28:41 +00:00
Head.SetNewAccount(szNewAccount);
2010-03-28 18:58:01 +00:00
if (szNewPassword)
2009-05-08 13:28:41 +00:00
Head.SetNewPassword(szNewPassword);
// Create query
2009-05-08 13:28:41 +00:00
StdStrBuf QueryText = DecompileToBuf<StdCompilerINIWrite>(
2010-03-28 18:58:01 +00:00
mkInsertAdapt(
mkNamingAdapt(Head, "Request"),
mkNamingAdapt(mkDecompileAdapt(PlrInfo), "PlrInfo"),
false));
// Perform query
2009-05-08 13:28:41 +00:00
return Query(QueryText.getData(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::GetAuthReply(StdStrBuf *pMessage, StdStrBuf *pAUID, StdStrBuf *pAccount, bool *pRegister, StdStrBuf *pLoginToken)
2010-03-28 18:58:01 +00:00
{
C4LeagueResponseHead Head;
2010-03-28 18:58:01 +00:00
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(Head, "Response"), ResultString, "Auth Reply"))
2009-05-08 13:28:41 +00:00
return false;
// Get message & account
2010-03-28 18:58:01 +00:00
if (pMessage)
pMessage->Copy(Head.getMessage());
2010-03-28 18:58:01 +00:00
if (pAccount)
2009-05-08 13:28:41 +00:00
pAccount->Copy(Head.getAccount());
2010-03-28 18:58:01 +00:00
if (pRegister)
2009-05-08 13:28:41 +00:00
*pRegister = Head.isStatusRegister();
if (pLoginToken)
pLoginToken->Copy(Head.getLoginToken());
2009-05-08 13:28:41 +00:00
// No success?
2010-03-28 18:58:01 +00:00
if (!Head.isSuccess())
2009-05-08 13:28:41 +00:00
return false;
// Check AUID
2010-03-28 18:58:01 +00:00
if (!Head.getAUID() || !*Head.getAUID())
{
2009-05-08 13:28:41 +00:00
pMessage->Ref(LoadResStr("IDS_MSG_LEAGUESERVERREPLYWITHOUTA"));
return false;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Success
2010-03-28 18:58:01 +00:00
if (pAUID)
2009-05-08 13:28:41 +00:00
pAUID->Copy(Head.getAUID());
FBIDList.AddFBID(Head.getFBID(), Head.getAccount());
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::AuthCheck(const C4PlayerInfo &PlrInfo)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert(CSID.getLength());
// Build header
eCurrAction = C4LA_PlrAuthCheck;
2009-05-08 13:28:41 +00:00
C4LeagueRequestHead Head(eCurrAction, CSID.getData(), PlrInfo.getAuthID());
// Create query
2009-05-08 13:28:41 +00:00
StdStrBuf QueryText = DecompileToBuf<StdCompilerINIWrite>(
2010-03-28 18:58:01 +00:00
mkInsertAdapt(
mkNamingAdapt(Head, "Request"),
mkNamingAdapt(mkDecompileAdapt(PlrInfo), "PlrInfo"),
false));
// Perform query
2009-05-08 13:28:41 +00:00
return Query(QueryText.getData(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::GetAuthCheckReply(StdStrBuf *pMessage, const char *szLeague, C4PlayerInfo *pPlrInfo)
2010-03-28 18:58:01 +00:00
{
// Parse response head
C4LeagueResponseHeadAuthCheck Head;
2010-03-28 18:58:01 +00:00
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(Head, "Response"), ResultString, "Auth Check Reply"))
2009-05-08 13:28:41 +00:00
return false;
// Get message and additional data
2010-03-28 18:58:01 +00:00
if (pMessage)
2009-05-08 13:28:41 +00:00
pMessage->Copy(Head.getMessage());
2010-03-28 18:58:01 +00:00
if (szLeague && pPlrInfo)
pPlrInfo->SetLeagueData(Head.getAccount(), Head.getClanTag(), Head.getScore(szLeague), Head.getRank(szLeague), Head.getRankSymbol(szLeague), Head.getProgressData(szLeague));
2009-05-08 13:28:41 +00:00
return Head.isSuccess();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::ReportDisconnect(const C4ClientPlayerInfos &rFeedbackClient, C4LeagueDisconnectReason eReason)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Build header
eCurrAction = C4LA_ReportDisconnect;
C4LeagueReportDisconnectHead Head(CSID.getData(), eReason);
// Create query
StdStrBuf QueryText = DecompileToBuf<StdCompilerINIWrite>(
2010-03-28 18:58:01 +00:00
mkInsertAdapt(
mkNamingAdapt(Head, "Request"),
mkNamingAdapt(DisconnectData(FBIDList, rFeedbackClient), "PlayerInfos"),
false));
2009-05-08 13:28:41 +00:00
// Perform query
return Query(QueryText.getData(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueClient::GetReportDisconnectReply(StdStrBuf *pMessage)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Parse response head
C4LeagueResponseHead Head;
2010-03-28 18:58:01 +00:00
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkNamingAdapt(Head, "Response"), ResultString, "Report Disconnect"))
2009-05-08 13:28:41 +00:00
return false;
// Get message
2010-03-28 18:58:01 +00:00
if (pMessage)
pMessage->Copy(Head.getMessage());
2009-05-08 13:28:41 +00:00
// Done
return Head.isSuccess();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// *** C4LeagueSignupDialog
C4LeagueSignupDialog::C4LeagueSignupDialog(const char *szPlayerName, const char *szLeagueName, const char *szLeagueServerName, const char *szAccountPref, const char *szPassPref, bool fWarnThirdParty, bool fRegister, bool fRememberLogin)
: C4GUI::Dialog(C4GUI_MessageDlgWdt, 100 /* will be resized as needed */, FormatString(LoadResStr("IDS_DLG_LEAGUESIGNUPON"), szLeagueServerName).getData(), false), strPlayerName(szPlayerName), pChkRememberLogin(nullptr)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get positions
C4GUI::ComponentAligner caMain(GetClientRect(), C4GUI_DefDlgIndent, C4GUI_DefDlgIndent, true);
// place icon
C4Rect rcIcon = caMain.GetFromLeft(C4GUI_IconWdt); rcIcon.Hgt = C4GUI_IconHgt;
C4GUI::Icon *pIcon = new C4GUI::Icon(rcIcon, C4GUI::Ico_Ex_League); AddElement(pIcon);
caMain.GetFromRight(C4GUI_IconWdt/2);
// place message label
// use text with line breaks
StdStrBuf sMsg, sMsgBroken;
2010-03-28 18:58:01 +00:00
if (fRegister)
2009-05-08 13:28:41 +00:00
sMsg.Format(LoadResStr("IDS_MSG_LEAGUE_REGISTRATION"), szPlayerName);
else
sMsg.Format(LoadResStr("IDS_MSG_PASSWORDFORPLAYER"), szPlayerName);
int32_t iLabelHgt = ::GraphicsResource.TextFont.BreakMessage(sMsg.getData(), caMain.GetInnerWidth(), &sMsgBroken, true);
C4GUI::Label *pLblMessage = new C4GUI::Label(sMsgBroken.getData(), caMain.GetFromTop(iLabelHgt), ALeft, C4GUI_MessageFontClr, &::GraphicsResource.TextFont);
2009-05-08 13:28:41 +00:00
AddElement(pLblMessage);
// registering and no account pref available
if (fRegister && (!szAccountPref || !szAccountPref[0]))
// use player name as default for league name
szAccountPref = szPlayerName;
// place username input box
bool fSideEdits=true; int iCtrlHeight;
StdStrBuf sAccountTxt; sAccountTxt.Copy(LoadResStr("IDS_CTL_LEAGUE_ACCOUNT"));
C4GUI::LabeledEdit::GetControlSize(nullptr, &iCtrlHeight, sAccountTxt.getData(), nullptr, fSideEdits);
2009-05-08 13:28:41 +00:00
AddElement(pEdtAccount = new C4GUI::LabeledEdit(caMain.GetFromTop(iCtrlHeight), sAccountTxt.getData(), fSideEdits, szAccountPref));
// registering? Make password field optional
2010-03-28 18:58:01 +00:00
if (fRegister)
{
2009-05-08 13:28:41 +00:00
// place the checkbox
const char *szChkPasswordCaption = LoadResStr("IDS_CTL_LEAGUE_CHK_PLRPW");
C4GUI::CheckBox::GetStandardCheckBoxSize(nullptr, &iCtrlHeight, szChkPasswordCaption, nullptr);
2009-05-08 13:28:41 +00:00
AddElement(pChkPassword = new C4GUI::CheckBox(caMain.GetFromTop(iCtrlHeight), szChkPasswordCaption, false));
pChkPassword->SetOnChecked(new C4GUI::CallbackHandlerNoPar<C4LeagueSignupDialog>(this, &C4LeagueSignupDialog::OnChkPassword));
pChkPassword->SetToolTip(LoadResStr("IDS_DESC_LEAGUECHECKPASSWORD"));
// place password edit boxes
C4GUI::ComponentAligner caTemp = caMain;
const char *szEdtPassCaption = LoadResStr("IDS_CTL_LEAGUE_PLRPW");
const char *szEdtPass2Caption = LoadResStr("IDS_CTL_LEAGUE_PLRPW2");
C4GUI::LabeledEdit::GetControlSize(nullptr, &iCtrlHeight, szEdtPassCaption, nullptr, fSideEdits);
2009-05-08 13:28:41 +00:00
AddElement(pEdtPass = new C4GUI::LabeledEdit(caTemp.GetFromTop(iCtrlHeight), szEdtPassCaption, fSideEdits, szPassPref));
AddElement(pEdtPass2 = new C4GUI::LabeledEdit(caTemp.GetFromTop(iCtrlHeight), szEdtPass2Caption, fSideEdits, szPassPref));
// hide them
pEdtPass->SetVisibility(false);
pEdtPass2->SetVisibility(false);
// save how much to move the controls later
iEdtPassSpace = caTemp.GetHeight() - caMain.GetHeight();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// No password checkbox
pChkPassword = nullptr;
2009-05-08 13:28:41 +00:00
// But a password edit box
const char *szEdtPassCaption = LoadResStr("IDS_CTL_LEAGUE_PLRPW");
C4GUI::LabeledEdit::GetControlSize(nullptr, &iCtrlHeight, szEdtPassCaption, nullptr, fSideEdits);
2009-05-08 13:28:41 +00:00
AddElement(pEdtPass = new C4GUI::LabeledEdit(caMain.GetFromTop(iCtrlHeight), szEdtPassCaption, fSideEdits, szPassPref));
// No second password edit box
pEdtPass2 = nullptr;
// remember login-checkbox
const char *szRememberPasswordCaption = LoadResStr("IDS_CTL_LEAGUE_CHK_REMEMBERLOGIN");
C4GUI::CheckBox::GetStandardCheckBoxSize(nullptr, &iCtrlHeight, szRememberPasswordCaption, nullptr);
AddElement(pChkRememberLogin = new C4GUI::CheckBox(caMain.GetFromTop(iCtrlHeight), szRememberPasswordCaption, fRememberLogin));
pChkRememberLogin->SetToolTip(LoadResStr("IDS_DESC_REMEMBERLOGIN"));
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Set password box options
pEdtPass->GetEdit()->SetPasswordMask('*');
2010-03-28 18:58:01 +00:00
if (pEdtPass2)
{
2009-05-08 13:28:41 +00:00
pEdtPass2->GetEdit()->SetPasswordMask('*');
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// place confirmation buttons
C4GUI::ComponentAligner caButtonArea(caMain.GetFromTop(C4GUI_ButtonAreaHgt), 0,0);
C4Rect rcBtn = caButtonArea.GetCentered(2*C4GUI_DefButton2Wdt+C4GUI_DefButton2HSpace, C4GUI_ButtonHgt);
rcBtn.Wdt = C4GUI_DefButton2Wdt;
pBtnOK = new C4GUI::OKButton(rcBtn);
AddElement(pBtnOK);
rcBtn.x += C4GUI_DefButton2Wdt+C4GUI_DefButton2HSpace;
pBtnAbort = new C4GUI::CancelButton(rcBtn);
AddElement(pBtnAbort);
// resize to actually needed size
SetClientSize(GetClientRect().Wdt, GetClientRect().Hgt - caMain.GetHeight());
// initial focus
SetFocus(fRegister ? pEdtAccount->GetEdit() : pEdtPass->GetEdit(), false);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueSignupDialog::UserClose(bool fOK)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Abort? That's always okay
2010-03-28 18:58:01 +00:00
if (!fOK)
{
2009-05-08 13:28:41 +00:00
Dialog::UserClose(fOK);
2009-06-05 16:53:56 +00:00
::pGUI->ShowMessageModal(FormatString(LoadResStr("IDS_MSG_LEAGUESIGNUPCANCELLED"), strPlayerName.getData()).getData(), LoadResStr("IDS_DLG_LEAGUESIGNUP"), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Notify);
2009-05-08 13:28:41 +00:00
return;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Check for empty account name
const char *szAccount = pEdtAccount->GetText();
2010-03-28 18:58:01 +00:00
if (!szAccount || !*szAccount)
{
2009-05-08 13:28:41 +00:00
SetFocus(pEdtAccount->GetEdit(), false);
2009-06-05 16:53:56 +00:00
::pGUI->ShowMessageModal(LoadResStr("IDS_MSG_LEAGUEMISSINGUSERNAME"), LoadResStr("IDS_DLG_INVALIDENTRY"), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
2009-05-08 13:28:41 +00:00
return;
2010-03-28 18:58:01 +00:00
}
// Check for valid username if this is registration
if (pEdtPass2)
2010-03-28 18:58:01 +00:00
{
// Username contains invalid characters
if (SCharCountEx(szAccount, C4League_Name_Valid_Characters) != SLen(szAccount))
{
SetFocus(pEdtAccount->GetEdit(), false);
::pGUI->ShowMessageModal(LoadResStr("IDS_MSG_LEAGUEINVALIDUSERNAME"), LoadResStr("IDS_DLG_INVALIDENTRY"), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
return;
}
// Username is too short
if (SLen(szAccount) < 3)
{
SetFocus(pEdtAccount->GetEdit(), false);
::pGUI->ShowMessageModal(LoadResStr("IDS_MSG_LEAGUEUSERNAMETOOSHORT"), LoadResStr("IDS_DLG_INVALIDENTRY"), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
return;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Check password
2010-03-28 18:58:01 +00:00
if (!pChkPassword || pChkPassword->GetChecked())
{
2009-05-08 13:28:41 +00:00
// Check for empty password
const char *szPassword = pEdtPass->GetText();
2010-03-28 18:58:01 +00:00
if (!szPassword || !*szPassword)
{
2009-05-08 13:28:41 +00:00
SetFocus(pEdtPass->GetEdit(), false);
2009-06-05 16:53:56 +00:00
::pGUI->ShowMessageModal(LoadResStr("IDS_MSG_LEAGUEMISSINGPASSWORD"), LoadResStr("IDS_DLG_INVALIDENTRY"), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
2009-05-08 13:28:41 +00:00
return;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Check second password
2010-03-28 18:58:01 +00:00
if (pEdtPass2 && !SEqual(szPassword, pEdtPass2->GetText()))
{
2009-05-08 13:28:41 +00:00
SetFocus(pEdtPass2->GetEdit(), false);
pEdtPass2->GetEdit()->SetText("", false);
2009-06-05 16:53:56 +00:00
::pGUI->ShowMessageModal(LoadResStr("IDS_MSG_LEAGUEMISMATCHPASSWORD"), LoadResStr("IDS_DLG_INVALIDENTRY"), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
2009-05-08 13:28:41 +00:00
return;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Okay then
Dialog::UserClose(fOK);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4LeagueSignupDialog::ShowModal(const char *szPlayerName, const char *szLeagueName, const char *szLeagueServerName, StdStrBuf *psCUID, StdStrBuf *psPass, bool fWarnThirdParty, bool fRegister, bool *pfRememberLogin)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// show league signup dlg modally; return whether user pressed OK and change user and pass buffers in that case
assert(psCUID); assert(psPass);
if (!psCUID || !psPass) return false;
C4LeagueSignupDialog *pDlg = new C4LeagueSignupDialog(szPlayerName, szLeagueName, szLeagueServerName, psCUID->getData(), psPass->getData(), fWarnThirdParty, fRegister, *pfRememberLogin);
2009-06-05 16:53:56 +00:00
bool fResult = ::pGUI->ShowModalDlg(pDlg, false);
2009-05-08 13:28:41 +00:00
if (fResult)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
psCUID->Copy(pDlg->GetAccount());
2010-03-28 18:58:01 +00:00
if (pDlg->HasPass())
2009-05-08 13:28:41 +00:00
psPass->Copy(pDlg->GetPass());
else
psPass->Clear();
*pfRememberLogin = pDlg->GetRememberLogin();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
delete pDlg;
return fResult;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4LeagueSignupDialog::OnChkPassword()
2010-03-28 18:58:01 +00:00
{
if (!pChkPassword) return;
2009-05-08 13:28:41 +00:00
// Show password elements?
2010-03-28 18:58:01 +00:00
if (!pChkPassword->GetChecked())
{
2009-05-08 13:28:41 +00:00
// Enlarge dialog
C4Rect bnds = GetClientRect();
SetClientSize(bnds.Wdt, bnds.Hgt + iEdtPassSpace);
// Show edit controls
pEdtPass->SetVisibility(false);
pEdtPass2->SetVisibility(false);
// Move controls down
bnds = pBtnOK->GetBounds();
pBtnOK->SetPos(bnds.x, bnds.y + iEdtPassSpace);
bnds = pBtnAbort->GetBounds();
pBtnAbort->SetPos(bnds.x, bnds.y + iEdtPassSpace);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Shrink dialog
C4Rect bnds = GetClientRect();
SetClientSize(bnds.Wdt, bnds.Hgt - iEdtPassSpace);
// Hide edit controls
pEdtPass->SetVisibility(true);
pEdtPass2->SetVisibility(true);
// Move controls down
bnds = pBtnOK->GetBounds();
pBtnOK->SetPos(bnds.x, bnds.y - iEdtPassSpace);
bnds = pBtnAbort->GetBounds();
pBtnAbort->SetPos(bnds.x, bnds.y - iEdtPassSpace);
}
2010-03-28 18:58:01 +00:00
}