/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "StdAfx.h"
#include
#include "../shared/AuthCodes.h"
#include "../shared/svn_revision.h"
bool VerifyName(const char * name, size_t nlen)
{
static char * bannedCharacters = "\t\v\b\f\a\n\r\\\"\'\? <>[](){}_=+-|/!@#$%^&*~`.,0123456789\0";
char * p;
for(size_t i = 0; i < nlen; ++i)
{
p = bannedCharacters;
while(*p != 0 && name[i] != *p && name[i] != 0)
++p;
if(*p != 0)
return false;
}
return true;
}
void CapitalizeString(string& arg)
{
if(arg.length() == 0) return;
arg[0] = toupper(arg[0]);
for(uint32 x = 1; x < arg.size(); ++x)
arg[x] = tolower(arg[x]);
}
void WorldSession::HandleCharEnumOpcode( WorldPacket & recv_data )
{
/*uint32 start_time = getMSTime();
// loading characters
QueryResult* result = CharacterDatabase.Query("SELECT guid, level, race, class, gender, bytes, bytes2, guildid, name, positionX, positionY, positionZ, mapId, zoneId, banned, restState, deathstate, forced_rename_pending FROM characters WHERE acct=%u ORDER BY guid", GetAccountId());
uint8 num = 0;
// should be more than enough.. 200 bytes per char..
WorldPacket data((result ? result->GetRowCount() * 200 : 1));
// parse m_characters and build a mighty packet of
// characters to send to the client.
data.SetOpcode(SMSG_CHAR_ENUM);
data << num;
SetSide(0);
if( result )
{
Player *plr;
uint64 guid;
Field *fields;
do
{
fields = result->Fetch();
guid = fields[0].GetUInt32();
plr = objmgr.GetPlayer(guid);
if(plr)
{
// we already have that player in world... for some strange reason...
continue;
}
plr = new Player(HIGHGUID_PLAYER, guid);
ASSERT(plr);
plr->SetSession(this);
// added to catch an assertion failure at Player::LoadFromDB function.
plr->LoadFromDB_Light( fields, guid );
sLog.outDebug("Loaded char guid "I64FMTD" [%s] from account %d for enum build.",guid,plr->GetName(), GetAccountId());
//printf("Guid: "I64FMT"\n", plr->GetGUID());
plr->BuildEnumData( &data );
_side|=(plr->GetTeam()+1);
plr->ok_to_remove = true;
delete plr;
num++;
}
while( result->NextRow() );
delete result;
}
data.put(0, num);
sLog.outDetail("[Character Enum] Built in %u ms.", getMSTime() - start_time);
SendPacket( &data );*/
struct player_item
{
uint32 displayid;
uint8 invtype;
};
player_item items[20];
uint32 slot;
uint32 i;
ItemPrototype * proto;
//uint32 start_time = getMSTime();
// loading characters
QueryResult* result = CharacterDatabase.Query("SELECT guid, level, race, class, gender, bytes, bytes2, guildid, name, positionX, positionY, positionZ, mapId, zoneId, banned, restState, deathstate, forced_rename_pending FROM characters WHERE acct=%u ORDER BY guid", GetAccountId());
QueryResult * res;
CreatureInfo *info = NULL;
uint8 num = 0;
// should be more than enough.. 200 bytes per char..
WorldPacket data((result ? result->GetRowCount() * 200 : 1));
// parse m_characters and build a mighty packet of
// characters to send to the client.
data.SetOpcode(SMSG_CHAR_ENUM);
data << num;
if( result )
{
uint64 guid;
uint8 Class;
uint32 bytes2;
Field *fields;
do
{
fields = result->Fetch();
guid = fields[0].GetUInt32();
bytes2 = fields[6].GetUInt32();
Class = fields[3].GetUInt8();
/* build character enum, w0000t :p */
data << fields[0].GetUInt64(); // guid
data << fields[8].GetString(); // name
data << fields[2].GetUInt8(); // race
data << fields[3].GetUInt8(); // class
data << fields[4].GetUInt8(); // gender
data << fields[5].GetUInt32(); // PLAYER_BYTES
data << uint8(bytes2 & 0xFF); // facial hair
data << fields[1].GetUInt8(); // Level
data << fields[13].GetUInt32(); // zoneid
data << fields[12].GetUInt32(); // Mapid
data << fields[11].GetFloat(); // X
data << fields[10].GetFloat(); // Y
data << fields[9].GetFloat(); // Z
data << fields[7].GetUInt32(); // GuildID
if(fields[14].GetBool())
{
//data << (uint32)7; // Banned (cannot login)
data << uint32(0x01A04040);
}
else if(fields[17].GetBool())
data << uint32(0x00A04342); // wtf blizz? :P (rename pending)
else if(fields[16].GetUInt32() != 0)
data << (uint32)8704; // Dead (displaying as Ghost)
else
data << uint32(1); // alive
data << fields[15].GetUInt8(); // Rest State
if(Class==9 || Class==3)
{
res = CharacterDatabase.Query("SELECT entryid FROM playerpets WHERE ownerguid="I64FMTD" AND active=1", guid);
if(res)
{
info = CreatureNameStorage.LookupEntry(res->Fetch()[0].GetUInt32());
delete res;
}
else
info=NULL;
}
else
info=NULL;
if(info) //PET INFO uint32 displayid, uint32 level, uint32 familyid
data << uint32(info->DisplayID) << uint32(10) << uint32(info->Family);
else
data << uint32(0) << uint32(0) << uint32(0);
res = CharacterDatabase.Query("SELECT slot, entry FROM playeritems WHERE ownerguid=%u and containerslot=-1 and slot < 19 and slot >= 0", GUID_LOPART(guid));
memset(items, 0, sizeof(player_item) * 20);
if(res)
{
do
{
proto = ItemPrototypeStorage.LookupEntry(res->Fetch()[1].GetUInt32());
if(proto)
{
slot = res->Fetch()[0].GetUInt32();
items[slot].displayid = proto->DisplayInfoID;
items[slot].invtype = proto->InventoryType;
}
} while(res->NextRow());
delete res;
}
for( i = 0; i < 20; ++i )
data << items[i].displayid << items[i].invtype;
num++;
}
while( result->NextRow() );
delete result;
}
data.put(0, num);
//Log.Debug("Character Enum", "Built in %u ms.", getMSTime() - start_time);
SendPacket( &data );
}
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 10);
std::string name;
uint8 race, class_;
recv_data >> name >> race >> class_;
recv_data.rpos(0);
if(!VerifyName(name.c_str(), name.length()))
{
OutPacket(SMSG_CHAR_CREATE, 1, "\x31");
return;
}
if(objmgr.GetPlayerInfoByName(name) != 0)
{
OutPacket(SMSG_CHAR_CREATE, 1, "\x31");
return;
}
if(!sHookInterface.OnNewCharacter(race, class_, this, name.c_str()))
{
OutPacket(SMSG_CHAR_CREATE, 1, "\x31");
return;
}
name = WorldDatabase.EscapeString(name);
QueryResult * result = WorldDatabase.Query("SELECT COUNT(*) FROM banned_names WHERE name = '%s'", name.c_str());
if(result)
{
if(result->Fetch()[0].GetUInt32() > 0)
{
// That name is banned!
OutPacket(SMSG_CHAR_CREATE, 1, "\x50"); // You cannot use that name
delete result;
return;
}
delete result;
}
// loading characters
//checking number of chars is useless since client will not allow to create more than 10 chars
//as the 'create' button will not appear (unless we want to decrease maximum number of characters)
Player * pNewChar = objmgr.CreatePlayer();
pNewChar->SetSession(this);
if(!pNewChar->Create( recv_data ))
{
// failed.
pNewChar->ok_to_remove = true;
delete pNewChar;
return;
}
QueryResult * resulta = CharacterDatabase.Query("SELECT race FROM characters WHERE acct = %u AND race in (1,3,4,7,11)", _accountId);
QueryResult * resulth = CharacterDatabase.Query("SELECT race FROM characters WHERE acct = %u AND race in (2,5,8,9,10)", _accountId);
SetSide(0);
if (resulta)
SetSide(1);
if (resulth)
SetSide(2);
//Same Faction limitation only applies to PVP and RPPVP realms :)
uint32 realmType = sLogonCommHandler.GetRealmType();
if(!HasGMPermissions() && (realmType==REALMTYPE_PVP||realmType==REALMTYPE_RPPVP))
{
if(
((pNewChar->GetTeam()== 0) && (_side == 2))||
((pNewChar->GetTeam()== 1) && (_side == 1))
)
{
pNewChar->ok_to_remove = true;
delete pNewChar;
WorldPacket data(1);
data.SetOpcode(SMSG_CHAR_CREATE);
data << (uint8)ALL_CHARS_ON_PVP_REALM_MUST_AT_SAME_SIDE;
SendPacket( &data );
return;
}
}
pNewChar->UnSetBanned();
pNewChar->addSpell(22027); // Remove Insignia
if(pNewChar->getClass() == WARLOCK)
{
pNewChar->AddSummonSpell(416, 3110); // imp fireball
pNewChar->AddSummonSpell(417, 19505);
pNewChar->AddSummonSpell(1860, 3716);
pNewChar->AddSummonSpell(1863, 7814);
}
pNewChar->SaveToDB(true);
PlayerInfo *pn=new PlayerInfo ;
pn->guid = pNewChar->GetGUID();
pn->name = pNewChar->GetName();
pn->cl = pNewChar->getClass();
pn->race = pNewChar->getRace();
pn->gender = pNewChar->getGender();
pn->publicNote="";
pn->officerNote="";
pn->m_Group=0;
pn->subGroup=0;
pn->team = pNewChar->GetTeam ();
objmgr.AddPlayerInfo(pn);
pNewChar->ok_to_remove = true;
delete pNewChar;
// CHAR_CREATE_SUCCESS
OutPacket(SMSG_CHAR_CREATE, 1, "\x2E");
sLogonCommHandler.UpdateAccountCount(GetAccountId(), 1);
}
/* FOR 1.10.1
SMSG_CHAR_CREATE Error Codes:
0x00 Success
0x01 Failure
0x02 Canceled
0x03 Disconnect from server
0x04 Failed to connect
0x05 Connected
0x06 Wrong client version
0x07 Connecting to server
0x08 Negotiating security
0x09 Negotiating security complete
0x0A Negotiating security failed
0x0B Authenticating
0x0C Authentication successful
0x0D Authentication failed
0x0E Login unavailable - Please contact Tech Support
0x0F Server is not valid
0x10 System unavailable
0x11 System error
0x12 Billing system error
0x13 Account billing has expired
0x14 Wrong client version
0x15 Unknown account
0x16 Incorrect password
0x17 Session expired
0x18 Server Shutting Down
0x19 Already logged in
0x1A Invalid login server
0x1B Position in Queue: 0
0x1C This account has been banned
0x1D This character is still logged on
0x1E Your WoW subscription has expired
0x1F This session has timed out
0x20 This account has been temporarily suspended
0x21 Access to this account blocked by parental controls
0x22 Retrieving realmlist
0x23 Realmlist retrieved
0x24 Unable to connect to realmlist server
0x25 Invalid realmlist
0x26 The game server is currently down
0x27 Creating account
0x28 Account created
0x29 Account creation failed
0x2A Retrieving character list
0x2B Character list retrieved
0x2C Error retrieving character list
0x2D Creating character
0x2E Character created
0x2F Error creating character
0x30 Character creation failed
0x31 That name is unavailable
0x32 Creation of that race/class is disabled
0x33 You cannot have both horde and alliance character at pvp realm
0x33 All characters on a PVP realm must be on the same team
0x34 You already have maximum number of characters
0x35 You already have maximum number of characters
0x36 The server is currently queued
0x37 Only players who have characters on this realm..
0x38 Creation of that race requires an account that has been upgraded to the approciate expansion
0x39 Deleting character
0x3A Character deleted
0x3B Char deletion failed
0x3c Entering world of warcraft
0x3D Login successful
0x3E World server is down
0x3F A character with that name already exists
0x40 No instance server available
0x41 Login failed
0x42 Login for that race/class is disabled
0x43 Character not found
0x44 Enter a name for your character
0x45 Names must be atleast 2 characters long
0x46 Names must be no more then 12 characters
0x47 Names can only contain letters
0x48 Names must contain only one language
0x49 That name contains profanity
0x4A That name is unavailable
0x4B You cannot use an apostrophe
0x4C You can only have one apostrophe
0x4D You cannot use the same letter three times consecutively
0x4E You cannit use space as the first or last character of your name
0x4F
0x50 Invalid character name
0x51
All further codes give the number in dec.
*/
void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 8);
uint8 fail = 0x3A;
uint64 guid;
recv_data >> guid;
if(objmgr.GetPlayer(guid) != NULL)
{
// "Char deletion failed"
fail = 0x3B;
} else {
Player* plr = new Player( HIGHGUID_PLAYER, GUID_LOPART(guid));
ASSERT(plr);
plr->SetSession(this);
if(!plr->LoadFromDB( GUID_LOPART(guid)))
{
// Disconnect us
sCheatLog.writefromsession(this, "Tried to delete non-existant player %u\n", guid);
Disconnect();
plr->ok_to_remove = true;
delete plr;
//sObjHolder.Delete(plr);
return;
}
plr->DeleteFromDB();
//if charter leader
if(plr->m_charter)
{
plr->m_charter->RemoveSignature(plr->GetGUID());
if(plr->m_charter->GetLeader() == plr->GetGUIDLow())
{
plr->m_charter->Destroy();
}
}
Guild *pGuild = objmgr.GetGuild(plr->GetGuildId());
if(pGuild)
{
if(pGuild->GetGuildLeaderGuid() == plr->GetGUID())
{
pGuild->DeleteGuildMembers();
pGuild->RemoveFromDb();
}
else
pGuild->DeleteGuildMember(plr->GetGUID());
}
sPlrLog.write("Account: %s | IP: %s >> Deleted player %s", GetAccountName().c_str(), GetSocket()->GetRemoteIP().c_str(), plr->GetName());
plr->ok_to_remove = true;
delete plr;
/* remove player info */
objmgr.DeletePlayerInfo(guid);
}
OutPacket(SMSG_CHAR_DELETE, 1, &fail);
}
void WorldSession::HandleCharRenameOpcode(WorldPacket & recv_data)
{
WorldPacket data(SMSG_CHAR_RENAME, recv_data.size() + 1);
uint64 guid;
string name;
recv_data >> guid >> name;
PlayerInfo * pi = objmgr.GetPlayerInfo(guid);
if(pi == 0) return;
QueryResult * result = CharacterDatabase.Query("SELECT forced_rename_pending FROM characters WHERE guid = %u AND acct = %u",
(uint32)guid, _accountId);
if(result == 0)
{
delete result;
return;
}
delete result;
// Check name for rule violation.
const char * szName=name.c_str();
for(uint32 x=0;x90&&(int)szName[x]<97)||(int)szName[x]>122)
{
data << uint8(0x31);
data << guid << name;
SendPacket(&data);
return;
}
}
name = WorldDatabase.EscapeString(name);
QueryResult * result2 = WorldDatabase.Query("SELECT COUNT(*) FROM banned_names WHERE name = '%s'", name.c_str());
if(result2)
{
if(result2->Fetch()[0].GetUInt32() > 0)
{
// That name is banned!
data << uint8(0x31);
data << guid << name;
SendPacket(&data);
}
delete result2;
}
// Check if name is in use.
if(objmgr.GetPlayerInfoByName(name) != 0)
{
data << uint8(0x31);
data << guid << name;
SendPacket(&data);
return;
}
// correct capitalization
CapitalizeString(name);
// If we're here, the name is okay.
pi->name = name;
CharacterDatabase.WaitExecute("UPDATE characters SET name = '%s' WHERE guid = %u", name.c_str(), (uint32)guid);
CharacterDatabase.WaitExecute("UPDATE characters SET forced_rename_pending = 0 WHERE guid = %u", (uint32)guid);
data << uint8(0) << guid << name;
SendPacket(&data);
}
void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 8);
uint64 playerGuid = 0;
sLog.outDebug( "WORLD: Recvd Player Logon Message" );
recv_data >> playerGuid; // this is the GUID selected by the player
PlayerLogin((uint32)playerGuid, 0, 0);
}
bool WorldSession::PlayerLogin(uint32 playerGuid, uint32 forced_map_id, uint32 forced_instance_id)
{
if(objmgr.GetPlayer(playerGuid) != NULL)
{
// A character with that name already exists 0x3E
uint8 respons = CHAR_LOGIN_DUPLICATE_CHARACTER;
OutPacket(SMSG_CHARACTER_LOGIN_FAILED, 1, &respons);
return false;
}
Player* plr = new Player(HIGHGUID_PLAYER,playerGuid);
ASSERT(plr);
plr->SetSession(this);
m_bIsWLevelSet = false;
if(!plr->LoadFromDB(playerGuid))
{
// kick em.
//sCheatLog.writefromsession(this, "Tried to log in with invalid player guid %u.", playerGuid);
//Disconnect();
plr->ok_to_remove = true;
delete plr;
uint8 respons = CHAR_LOGIN_NO_CHARACTER;
OutPacket(SMSG_CHARACTER_LOGIN_FAILED, 1, &respons);
return false;
}
SetPlayer(plr);
m_MoverWoWGuid.Init(plr->GetGUID());
// copy to movement array
movement_packet[0] = m_MoverWoWGuid.GetNewGuidMask();
memcpy(&movement_packet[1], m_MoverWoWGuid.GetNewGuid(), m_MoverWoWGuid.GetNewGuidLen());
#ifndef USING_BIG_ENDIAN
StackWorldPacket<20> datab(CMSG_DUNGEON_DIFFICULTY);
#else
WorldPacket datab(CMSG_DUNGEON_DIFFICULTY, 20);
#endif
datab << plr->iInstanceType;
datab << uint32(0x01);
datab << uint32(0x00);
SendPacket(&datab);
/* world preload */
datab.Initialize(SMSG_LOGIN_VERIFY_WORLD);
datab << plr->GetMapId();
datab << plr->GetPositionX()
<< plr->GetPositionY()
<< plr->GetPositionZ()
<< plr->GetOrientation();
SendPacket(&datab);
plr->LoadPropertiesFromDB();
plr->UpdateAttackSpeed();
// Make sure our name exists (for premade system)
PlayerInfo * info = objmgr.GetPlayerInfo(plr->GetGUID());
if(info == 0)
{
info = new PlayerInfo;
info->cl = plr->getClass();
info->gender = plr->getGender();
info->guid = plr->GetGUID();
info->name = plr->GetName();
info->lastLevel = plr->getLevel();
info->lastOnline = time(NULL);
info->lastZone = plr->GetZoneId();
info->officerNote = "";
info->publicNote = "";
info->race = plr->getRace();
info->Rank = plr->GetPVPRank();
info->team = plr->GetTeam();
info->m_Group=0;
info->subGroup=0;
objmgr.AddPlayerInfo(info);
}
plr->m_playerInfo = info;
// account data == UI config
#ifndef USING_BIG_ENDIAN
StackWorldPacket<128> data(SMSG_ACCOUNT_DATA_MD5);
#else
WorldPacket data(SMSG_ACCOUNT_DATA_MD5, 128);
#endif
for (int i = 0; i < 8; i++)
{
AccountDataEntry* acct_data = GetAccountData(i);
if (!acct_data->data)
{
data << uint64(0) << uint64(0); // Nothing.
continue;
}
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, acct_data->data, acct_data->sz);
uint8 md5hash[MD5_DIGEST_LENGTH];
MD5_Final(md5hash, &ctx);
#ifndef USING_BIG_ENDIAN
data.Write(md5hash, MD5_DIGEST_LENGTH);
#else
data.append(md5hash, MD5_DIGEST_LENGTH);
#endif
}
SendPacket(&data);
// Set TIME OF LOGIN
CharacterDatabase.Execute (
"UPDATE characters SET online = 1 WHERE guid = %u" , plr->GetGUIDLow());
bool enter_world = true;
#ifndef CLUSTERING
// Find our transporter and add us if we're on one.
if(plr->m_TransporterGUID != 0)
{
Transporter * pTrans = objmgr.GetTransporter(plr->m_TransporterGUID);
if(pTrans)
{
float c_tposx = pTrans->GetPositionX() + plr->m_TransporterX;
float c_tposy = pTrans->GetPositionY() + plr->m_TransporterY;
float c_tposz = pTrans->GetPositionZ() + plr->m_TransporterZ;
if(plr->GetMapId() != pTrans->GetMapId()) // loaded wrong map
{
plr->SetMapId(pTrans->GetMapId());
#ifndef USING_BIG_ENDIAN
StackWorldPacket<20> dataw(SMSG_NEW_WORLD);
#else
WorldPacket dataw(SMSG_NEW_WORLD, 20);
#endif
dataw << pTrans->GetMapId() << c_tposx << c_tposy << c_tposz << plr->GetOrientation();
SendPacket(&dataw);
// shit is sent in worldport ack.
enter_world = false;
}
plr->SetPosition(c_tposx, c_tposy, c_tposz, plr->GetOrientation(), false);
plr->m_CurrentTransporter = pTrans;
pTrans->AddPlayer(plr);
}
}
#endif
sLog.outString("Player %s (%s %s %s), logged in.", plr->GetName(), plr->getGender() ? "Female" : "Male",
sCharRaceStore.LookupString(plr->myRace->name2), sCharClassStore.LookupString(plr->myClass->name));
#ifndef CLUSTERING
// send extended message
sWorld.BroadcastExtendedMessage(this, "[SM:PLRLOGIN:%u:%u]%s", plr->getRace(), plr->getClass(), plr->GetName());
if(HasFlag(ACCOUNT_FLAG_XTEND_INFO))
{
// send gm list
stringstream ssg;
uint32 c = 0;
for(set::iterator itr = sWorld.gmList.begin(); itr != sWorld.gmList.end(); ++itr)
{
if((*itr)->GetPlayer())
{
ssg << *(*itr)->GetPlayer()->GetNameString();
ssg << ",";
++c;
}
}
_player->BroadcastMessage("[SM:GMLIST:%s]", ssg.str().c_str());
}
if(HasGMPermissions())
{
sWorld.BroadcastExtendedMessage(this, "[SM:GMLOGIN]%s", plr->GetName());
}
#endif
if(plr->GetTeam() == 1)
sWorld.HordePlayers++;
else
sWorld.AlliancePlayers++;
#ifndef CLUSTERING
// send info
sWorld.BroadcastExtendedMessage(0, "[SM:INFO:%u:%u]", sWorld.HordePlayers, sWorld.AlliancePlayers);
#endif
if(plr->m_FirstLogin && !HasGMPermissions())
{
uint32 racecinematic = plr->myRace->cinematic_id;
OutPacket(SMSG_TRIGGER_CINEMATIC, 4, &racecinematic);
}
sLog.outDetail( "WORLD: Created new player for existing players (%s)", plr->GetName() );
// Login time, will be used for played time calc
plr->m_playedtime[2] = (uint32)time(NULL);
//Issue a message telling all guild members that this player has signed on
if(plr->IsInGuild())
{
Guild *pGuild = objmgr.GetGuild( plr->GetGuildId() );
if(pGuild)
{
WorldPacket data(50);
data.Initialize(SMSG_GUILD_EVENT);
data << uint8(GUILD_EVENT_MOTD);
data << uint8(0x01);
data << pGuild->GetGuildMotd();
SendPacket(&data);
data.Initialize(SMSG_GUILD_EVENT);
data << uint8(GUILD_EVENT_HASCOMEONLINE);
data << uint8(0x01);
data << plr->GetName();
data << plr->GetGUID();
pGuild->SendMessageToGuild(0,&data,G_MSGTYPE_ALL);
}
}
// Send online status to people having this char in friendlist
sSocialMgr.LoggedIn( GetPlayer() );
// Send MOTD
_player->BroadcastMessage(sWorld.GetMotd());
// Send revision (if enabled)
if(sWorld.sendRevisionOnJoin)
{
uint32 rev = g_getRevision();
#ifdef HOARD
_player->BroadcastMessage("You are playing on %sAscent r%u/%s-%s-%s-Hoard", MSG_COLOR_WHITE,
rev, CONFIG, PLATFORM_TEXT, ARCH);
#else
_player->BroadcastMessage("You are playing on %sAscent r%u/%s-%s-%s %s(www.ascentemu.com)", MSG_COLOR_WHITE,
rev, CONFIG, PLATFORM_TEXT, ARCH, MSG_COLOR_LIGHTBLUE);
#endif
}
if(sWorld.SendStatsOnJoin)
{
_player->BroadcastMessage("Online Players: %s%u |rPeak: %s%u|r Accepted Connections: %s%u",
MSG_COLOR_WHITE, sWorld.GetSessionCount(), MSG_COLOR_WHITE, sWorld.PeakSessionCount, MSG_COLOR_WHITE, sWorld.mAcceptedConnections);
}
// Calculate rested experience if there is time between lastlogoff and now
uint32 currenttime = (uint32)time(NULL);
float timediff = currenttime - plr->m_timeLogoff;
if(plr->m_timeLogoff > 0 && plr->GetUInt32Value(UNIT_FIELD_LEVEL) < plr->GetUInt32Value(PLAYER_FIELD_MAX_LEVEL)) // if timelogoff = 0 then it's the first login
{
if(plr->m_isResting)
{
// We are resting at an inn, calculate XP and add it.
uint32 RestXP = plr->CalculateRestXP((uint32)timediff);
plr->AddRestXP(RestXP);
sLog.outDebug("REST: Added %d of rest XP.", RestXP);
plr->ApplyPlayerRestState(true);
}
else if(timediff > 0)
{
// We are resting in the wilderness at a slower rate.
uint32 RestXP = plr->CalculateRestXP((uint32)timediff);
RestXP >>= 2; // divide by 4 because its at 1/4 of the rate
plr->AddRestXP(RestXP);
}
}
#ifdef CLUSTERING
plr->SetInstanceID(forced_instance_id);
plr->SetMapId(forced_map_id);
#else
sHookInterface.OnEnterWorld2(_player);
#endif
if(enter_world)
{
plr->SendInitialLogonPackets();
plr->AddToWorld();
}
sInstanceSavingManager.BuildSavedInstancesForPlayer(plr);
objmgr.AddPlayer(_player);
return true;
}
bool ChatHandler::HandleRenameCommand(const char * args, WorldSession * m_session)
{
// prevent buffer overflow
if(strlen(args) > 100)
return false;
char name1[100];
char name2[100];
if(sscanf(args, "%s %s", name1, name2) != 2)
return false;
if(VerifyName(name2, strlen(name2)) == false)
{
RedSystemMessage(m_session, "That name is invalid or contains invalid characters.");
return true;
}
string new_name = name2;
string oldn = name1;//some crazy func, dunno who invented that shit...
PlayerInfo * pi = objmgr.GetPlayerInfoByName(oldn);
if(pi == 0)
{
RedSystemMessage(m_session, "Player not found with this name.");
return true;
}
pi->name = new_name;
// look in world for him
Player * plr = objmgr.GetPlayer(pi->guid);
if(plr != 0)
{
plr->SetName(new_name);
BlueSystemMessageToPlr(plr, "%s changed your name to '%s'.", m_session->GetPlayer()->GetName(), new_name.c_str());
plr->SaveToDB(false);
}
else
{
CharacterDatabase.WaitExecute("UPDATE characters SET name = '%s' WHERE guid = %u", CharacterDatabase.EscapeString(new_name).c_str(), (uint32)pi->guid);
}
GreenSystemMessage(m_session, "Changed name of '%s' to '%s'.", name1, name2);
return true;
}