[9746] Implement show realm version and build in realm list.

* Rename `realmlist`.`color` field to `realmflags`

* Client 2.x and later support show in realm list supported
  client version for specific realm.

  For client 1.x this implemented by adding version to name
  in similar way as it look in more recent clients.

  For enable version show each affected realm must have in `realmflags` set
  flag 4.

  For realm work with not officially supported builds (build > last suported)
  will show version 0.0.0 and correct build value.
This commit is contained in:
VladimirMangos 2010-04-14 08:50:29 +04:00
parent 88139a7857
commit 822ec31cb9
10 changed files with 157 additions and 78 deletions

View file

@ -21,7 +21,7 @@
DROP TABLE IF EXISTS `realmd_db_version`; DROP TABLE IF EXISTS `realmd_db_version`;
CREATE TABLE `realmd_db_version` ( CREATE TABLE `realmd_db_version` (
`required_9010_01_realmd_realmlist` bit(1) default NULL `required_9746_01_realmd_realmlist` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
-- --
@ -157,7 +157,7 @@ CREATE TABLE `realmlist` (
`address` varchar(32) NOT NULL default '127.0.0.1', `address` varchar(32) NOT NULL default '127.0.0.1',
`port` int(11) NOT NULL default '8085', `port` int(11) NOT NULL default '8085',
`icon` tinyint(3) unsigned NOT NULL default '0', `icon` tinyint(3) unsigned NOT NULL default '0',
`color` tinyint(3) unsigned NOT NULL default '2', `realmflags` tinyint(3) unsigned NOT NULL default '0' COMMENT 'Supported masks: 0x1 (invalid, not show in realm list), 0x4 (show version and build), 0x20 (new players), 0x40 (recommended)',
`timezone` tinyint(3) unsigned NOT NULL default '0', `timezone` tinyint(3) unsigned NOT NULL default '0',
`allowedSecurityLevel` tinyint(3) unsigned NOT NULL default '0', `allowedSecurityLevel` tinyint(3) unsigned NOT NULL default '0',
`population` float unsigned NOT NULL default '0', `population` float unsigned NOT NULL default '0',

View file

@ -0,0 +1,9 @@
ALTER TABLE realmd_db_version CHANGE COLUMN required_9010_01_realmd_realmlist required_9746_01_realmd_realmlist bit;
ALTER TABLE realmlist
CHANGE COLUMN color realmflags tinyint(3) unsigned NOT NULL default '0'
COMMENT 'Supported masks: 0x1 (invalid, not show in realm list), 0x4 (show version and build), 0x20 (new players), 0x40 (recommended)';
UPDATE realmlist
SET realmflags = realmflags & ~(0x01 | 0x04 | 0x20 | 0x40) ;

View file

@ -118,6 +118,7 @@ pkgdata_DATA = \
9728_01_mangos_gossip_menu_option.sql \ 9728_01_mangos_gossip_menu_option.sql \
9735_01_mangos_spell_proc_event.sql \ 9735_01_mangos_spell_proc_event.sql \
9735_02_mangos_spell_chain.sql \ 9735_02_mangos_spell_chain.sql \
9746_01_realmd_realmlist.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -216,4 +217,5 @@ EXTRA_DIST = \
9728_01_mangos_gossip_menu_option.sql \ 9728_01_mangos_gossip_menu_option.sql \
9735_01_mangos_spell_proc_event.sql \ 9735_01_mangos_spell_proc_event.sql \
9735_02_mangos_spell_chain.sql \ 9735_02_mangos_spell_chain.sql \
9746_01_realmd_realmlist.sql \
README README

View file

@ -46,24 +46,4 @@ enum AuthResult
WOW_FAIL_USE_BATTLENET = 0x12, ///< WOW_FAIL_OTHER This account is now attached to a Battle.net account. Please login with your Battle.net account email address and password. WOW_FAIL_USE_BATTLENET = 0x12, ///< WOW_FAIL_OTHER This account is now attached to a Battle.net account. Please login with your Battle.net account email address and password.
}; };
// will only support WoW 1.12.1/1.12.2 , WoW:TBC 2.4.3 and official release for WoW:WotLK and later, client builds 10505, 8606, 6005, 5875
// if you need more from old build then add it in cases in realmd sources code
// list sorted from high to low build and first build used as low bound for accepted by default range (any > it will accepted by realmd at least)
#define EXPECTED_REALMD_CLIENT_BUILD \
{ \
11723, /* 3.3.3a and higher */ \
11403, /* 3.3.2 */ \
11159, /* 3.3.0a */ \
10505, /* 3.2.2a */ \
8606, /* 2.4.3 */ \
6005, /* 1.12.2 */ \
5875, /* 1.12.1 */ \
0 \
}
// At update excepted builds please update if need define DEFAULT_MAX_LEVEL
// in DBCEnum.h to default max player level expected by build
// and also in mangosd.conf.in
#endif #endif

View file

@ -234,6 +234,8 @@ AuthSocket::AuthSocket(ISocketHandler &h) : TcpSocket(h)
pPatch = NULL; pPatch = NULL;
_accountSecurityLevel = SEC_PLAYER; _accountSecurityLevel = SEC_PLAYER;
_build = 0;
} }
/// Close patch file descriptor before leaving /// Close patch file descriptor before leaving
@ -579,22 +581,7 @@ bool AuthSocket::_HandleLogonProof()
ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C)); ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C));
///- Check if the client has one of the expected version numbers ///- Check if the client has one of the expected version numbers
bool valid_version = false; bool valid_version = FindBuildInfo(_build) != NULL;
int accepted_versions[] = EXPECTED_REALMD_CLIENT_BUILD;
if (_build >= accepted_versions[0]) // first build is low bound of always accepted range
valid_version = true;
else
{
// continue from 1 with explict equal check
for(int i = 1; accepted_versions[i]; ++i)
{
if(_build == accepted_versions[i])
{
valid_version = true;
break;
}
}
}
/// <ul><li> If the client has no valid version /// <ul><li> If the client has no valid version
if(!valid_version) if(!valid_version)
@ -961,13 +948,30 @@ void AuthSocket::LoadRealmlist(ByteBuffer &pkt, uint32 acctid)
else else
AmountOfCharacters = 0; AmountOfCharacters = 0;
// Show offline state for unsupported client builds bool ok_build = std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end();
uint8 color = (std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end()) ? i->second.color : 2;
color = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 2 : color; RealmBuildInfo const* buildInfo = ok_build ? FindBuildInfo(_build) : NULL;
if (!buildInfo)
buildInfo = &i->second.realmBuildInfo;
RealmFlags realmflags = i->second.realmflags;
// 1.x clients not support explicitly REALM_FLAG_SPECIFYBUILD, so manually form similar name as show in more recent clients
std::string name = i->first;
if (realmflags & REALM_FLAG_SPECIFYBUILD)
{
char buf[20];
snprintf(buf, 20," (%u,%u,%u)", buildInfo->major_version, buildInfo->minor_version, buildInfo->bugfix_version);
name += buf;
}
// Show offline state for unsupported client builds and locked realms (1.x clients not support locked state show)
if (!ok_build || (i->second.allowedSecurityLevel >= _accountSecurityLevel))
realmflags = RealmFlags(realmflags | REALM_FLAG_OFFLINE);
pkt << uint32(i->second.icon); // realm type pkt << uint32(i->second.icon); // realm type
pkt << uint8(color); // if 2, then realm is offline pkt << uint8(realmflags); // realmflags
pkt << i->first; // name pkt << name; // name
pkt << i->second.address; // address pkt << i->second.address; // address
pkt << float(i->second.populationLevel); pkt << float(i->second.populationLevel);
pkt << uint8(AmountOfCharacters); pkt << uint8(AmountOfCharacters);
@ -1005,14 +1009,26 @@ void AuthSocket::LoadRealmlist(ByteBuffer &pkt, uint32 acctid)
else else
AmountOfCharacters = 0; AmountOfCharacters = 0;
bool ok_build = std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end();
RealmBuildInfo const* buildInfo = ok_build ? FindBuildInfo(_build) : NULL;
if (!buildInfo)
buildInfo = &i->second.realmBuildInfo;
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
RealmFlags realmFlags = i->second.realmflags;
// Show offline state for unsupported client builds // Show offline state for unsupported client builds
uint8 color = (std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end()) ? i->second.color : 2; if (!ok_build)
realmFlags = RealmFlags(realmFlags | REALM_FLAG_OFFLINE);
if (!buildInfo)
realmFlags = RealmFlags(realmFlags & ~REALM_FLAG_SPECIFYBUILD);
pkt << uint8(i->second.icon); // realm type (this is second column in Cfg_Configs.dbc) pkt << uint8(i->second.icon); // realm type (this is second column in Cfg_Configs.dbc)
pkt << uint8(lock); // flags, if 0x01, then realm locked pkt << uint8(lock); // flags, if 0x01, then realm locked
pkt << uint8(color); // see enum RealmFlags pkt << uint8(realmFlags); // see enum RealmFlags
pkt << i->first; // name pkt << i->first; // name
pkt << i->second.address; // address pkt << i->second.address; // address
pkt << float(i->second.populationLevel); pkt << float(i->second.populationLevel);
@ -1020,13 +1036,13 @@ void AuthSocket::LoadRealmlist(ByteBuffer &pkt, uint32 acctid)
pkt << uint8(i->second.timezone); // realm category (Cfg_Categories.dbc) pkt << uint8(i->second.timezone); // realm category (Cfg_Categories.dbc)
pkt << uint8(0x2C); // unk, may be realm number/id? pkt << uint8(0x2C); // unk, may be realm number/id?
/*if(realmFlags & REALM_FLAG_SPECIFYBUILD) if (realmFlags & REALM_FLAG_SPECIFYBUILD)
{ {
pkt << uint8(0); // major pkt << uint8(buildInfo->major_version);
pkt << uint8(0); // minor pkt << uint8(buildInfo->minor_version);
pkt << uint8(0); // revision pkt << uint8(buildInfo->bugfix_version);
pkt << uint16(0); // build pkt << uint16(_build);
}*/ }
} }
pkt << uint16(0x0010); pkt << uint16(0x0010);

View file

@ -34,19 +34,6 @@
#include "Auth/Sha1.h" #include "Auth/Sha1.h"
#include "ByteBuffer.h" #include "ByteBuffer.h"
enum RealmFlags
{
REALM_FLAG_NONE = 0x00,
REALM_FLAG_INVALID = 0x01,
REALM_FLAG_OFFLINE = 0x02,
REALM_FLAG_SPECIFYBUILD = 0x04, // client will show realm version in RealmList screen in form "RealmName (major.minor.revision.build)"
REALM_FLAG_UNK1 = 0x08,
REALM_FLAG_UNK2 = 0x10,
REALM_FLAG_NEW_PLAYERS = 0x20,
REALM_FLAG_RECOMMENDED = 0x40,
REALM_FLAG_FULL = 0x80
};
/// Handle login commands /// Handle login commands
class AuthSocket: public TcpSocket class AuthSocket: public TcpSocket
{ {

View file

@ -31,6 +31,36 @@ INSTANTIATE_SINGLETON_1( RealmList );
extern DatabaseType loginDatabase; extern DatabaseType loginDatabase;
// will only support WoW 1.12.1/1.12.2 , WoW:TBC 2.4.3 and official release for WoW:WotLK and later, client builds 10505, 8606, 6005, 5875
// if you need more from old build then add it in cases in realmd sources code
// list sorted from high to low build and first build used as low bound for accepted by default range (any > it will accepted by realmd at least)
static RealmBuildInfo ExpectedRealmdClientBuilds[] = {
{11723, 3, 3, 3, 'a'}, // highest supported build, also auto accept all above for simplify future supported builds testing
{11403, 3, 3, 2, ' '},
{11159, 3, 3, 0, 'a'},
{10505, 3, 2, 2, 'a'},
{8606, 2, 4, 3, ' '},
{6005, 1,12, 2, ' '},
{5875, 1,12, 1, ' '},
{0, 0, 0, 0, ' '} // terminator
};
RealmBuildInfo const* FindBuildInfo(uint16 _build)
{
// first build is low bound of always accepted range
if (_build >= ExpectedRealmdClientBuilds[0].build)
return &ExpectedRealmdClientBuilds[0];
// continue from 1 with explicit equal check
for(int i = 1; ExpectedRealmdClientBuilds[i].build; ++i)
if(_build == ExpectedRealmdClientBuilds[i].build)
return &ExpectedRealmdClientBuilds[i];
// none appropriate build
return NULL;
}
RealmList::RealmList( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) RealmList::RealmList( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL))
{ {
} }
@ -50,14 +80,16 @@ void RealmList::Initialize(uint32 updateInterval)
UpdateRealms(true); UpdateRealms(true);
} }
void RealmList::UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, const char* builds) void RealmList::UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, RealmFlags realmflags, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, const char* builds)
{ {
realmflags = RealmFlags(realmflags | REALM_FLAG_SPECIFYBUILD);
///- Create new if not exist or update existed ///- Create new if not exist or update existed
Realm& realm = m_realms[name]; Realm& realm = m_realms[name];
realm.m_ID = ID; realm.m_ID = ID;
realm.icon = icon; realm.icon = icon;
realm.color = color; realm.realmflags = realmflags;
realm.timezone = timezone; realm.timezone = timezone;
realm.allowedSecurityLevel = allowedSecurityLevel; realm.allowedSecurityLevel = allowedSecurityLevel;
realm.populationLevel = popu; realm.populationLevel = popu;
@ -71,6 +103,19 @@ void RealmList::UpdateRealm( uint32 ID, const std::string& name, const std::stri
realm.realmbuilds.insert(build); realm.realmbuilds.insert(build);
} }
uint16 first_build = !realm.realmbuilds.empty() ? *realm.realmbuilds.begin() : 0;
realm.realmBuildInfo.build = first_build;
realm.realmBuildInfo.major_version = 0;
realm.realmBuildInfo.minor_version = 0;
realm.realmBuildInfo.bugfix_version = 0;
realm.realmBuildInfo.hotfix_version = ' ';
if (first_build)
if (RealmBuildInfo const* bInfo = FindBuildInfo(first_build))
if (bInfo->build == first_build)
realm.realmBuildInfo = *bInfo;
///- Append port to IP address. ///- Append port to IP address.
std::ostringstream ss; std::ostringstream ss;
ss << address << ":" << port; ss << address << ":" << port;
@ -97,7 +142,7 @@ void RealmList::UpdateRealms(bool init)
sLog.outDetail("Updating Realm List..."); sLog.outDetail("Updating Realm List...");
//// 0 1 2 3 4 5 6 7 8 9 //// 0 1 2 3 4 5 6 7 8 9
QueryResult *result = loginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population, realmbuilds FROM realmlist WHERE color <> 3 ORDER BY name" ); QueryResult *result = loginDatabase.Query( "SELECT id, name, address, port, icon, realmflags, timezone, allowedSecurityLevel, population, realmbuilds FROM realmlist WHERE (realmflags & 1) = 0 ORDER BY name" );
///- Circle through results and add them to the realm map ///- Circle through results and add them to the realm map
if(result) if(result)
@ -108,7 +153,20 @@ void RealmList::UpdateRealms(bool init)
uint8 allowedSecurityLevel = fields[7].GetUInt8(); uint8 allowedSecurityLevel = fields[7].GetUInt8();
UpdateRealm(fields[0].GetUInt32(), fields[1].GetCppString(),fields[2].GetCppString(),fields[3].GetUInt32(),fields[4].GetUInt8(), fields[5].GetUInt8(), fields[6].GetUInt8(), (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), fields[8].GetFloat(), fields[9].GetString() ); uint8 realmflags = fields[5].GetUInt8();
if (realmflags & ~(REALM_FLAG_NEW_PLAYERS|REALM_FLAG_RECOMMENDED|REALM_FLAG_SPECIFYBUILD))
{
sLog.outError("Realm allowed have only NEWPLAYERS (mask 0x20), or RECOMENDED (mask 0x40), or SPECIFICBUILD (mask 0x04) flags in DB");
realmflags &= (REALM_FLAG_NEW_PLAYERS|REALM_FLAG_RECOMMENDED|REALM_FLAG_SPECIFYBUILD);
}
UpdateRealm(
fields[0].GetUInt32(), fields[1].GetCppString(),fields[2].GetCppString(),fields[3].GetUInt32(),
fields[4].GetUInt8(), RealmFlags(realmflags), fields[6].GetUInt8(),
(allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR),
fields[8].GetFloat(), fields[9].GetString());
if(init) if(init)
sLog.outString("Added realm \"%s\"", fields[1].GetString()); sLog.outString("Added realm \"%s\"", fields[1].GetString());
} while( result->NextRow() ); } while( result->NextRow() );

View file

@ -25,17 +25,44 @@
#include "Common.h" #include "Common.h"
enum RealmFlags
{
REALM_FLAG_NONE = 0x00,
REALM_FLAG_INVALID = 0x01,
REALM_FLAG_OFFLINE = 0x02,
REALM_FLAG_SPECIFYBUILD = 0x04, // client will show realm version in RealmList screen in form "RealmName (major.minor.revision.build)"
REALM_FLAG_UNK1 = 0x08,
REALM_FLAG_UNK2 = 0x10,
REALM_FLAG_NEW_PLAYERS = 0x20,
REALM_FLAG_RECOMMENDED = 0x40,
REALM_FLAG_FULL = 0x80
};
struct RealmBuildInfo
{
int build;
int major_version;
int minor_version;
int bugfix_version;
int hotfix_version;
};
RealmBuildInfo const* FindBuildInfo(uint16 _build);
typedef std::set<uint32> RealmBuilds;
/// Storage object for a realm /// Storage object for a realm
struct Realm struct Realm
{ {
std::string address; std::string address;
uint8 icon; uint8 icon;
uint8 color; RealmFlags realmflags; // realmflags
uint8 timezone; uint8 timezone;
uint32 m_ID; uint32 m_ID;
AccountTypes allowedSecurityLevel; AccountTypes allowedSecurityLevel; // current allowed join security level (show as locked for not fit accounts)
float populationLevel; float populationLevel;
std::set<uint32> realmbuilds; RealmBuilds realmbuilds; // list of supported builds (updated in DB by mangosd)
RealmBuildInfo realmBuildInfo; // build info for show version in list
}; };
/// Storage object for the list of realms on the server /// Storage object for the list of realms on the server
@ -58,7 +85,7 @@ class RealmList
uint32 size() const { return m_realms.size(); } uint32 size() const { return m_realms.size(); }
private: private:
void UpdateRealms(bool init); void UpdateRealms(bool init);
void UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, const char* builds); void UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, RealmFlags realmflags, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, const char* builds);
private: private:
RealmMap m_realms; ///< Internal map of realms RealmMap m_realms; ///< Internal map of realms
uint32 m_UpdateInterval; uint32 m_UpdateInterval;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9745" #define REVISION_NR "9746"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -2,5 +2,5 @@
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_9702_01_characters_item" #define REVISION_DB_CHARACTERS "required_9702_01_characters_item"
#define REVISION_DB_MANGOS "required_9735_02_mangos_spell_chain" #define REVISION_DB_MANGOS "required_9735_02_mangos_spell_chain"
#define REVISION_DB_REALMD "required_9010_01_realmd_realmlist" #define REVISION_DB_REALMD "required_9746_01_realmd_realmlist"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__