Changeset 6 for trunk/src/game

Show
Ignore:
Timestamp:
11/19/08 13:22:12 (17 years ago)
Author:
yumileroy
Message:

[svn] * Added ACE for Linux and Windows (Thanks Derex for Linux part and partial Windows part)
* Updated to 6721 and 676
* Fixed TrinityScript? logo
* Version updated to 0.2.6721.676

Original author: Neo2003
Date: 2008-10-04 06:17:19-05:00

Location:
trunk/src/game
Files:
39 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/game/AggressorAI.cpp

    r2 r6  
    4444AggressorAI::MoveInLineOfSight(Unit *u) 
    4545{ 
    46     if( i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) 
     46    // Ignore Z for flying creatures 
     47    if( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) 
    4748        return; 
     49     
    4850    if( !i_creature.getVictim() && !i_creature.hasUnitState(UNIT_STAT_STUNDED) && u->isTargetableForAttack() && 
    4951        ( i_creature.IsHostileTo( u ) /*|| u->getVictim() && i_creature.IsFriendlyTo( u->getVictim() )*/ ) && 
  • trunk/src/game/CharacterHandler.cpp

    r2 r6  
    2020#include "Database/DatabaseEnv.h" 
    2121#include "WorldPacket.h" 
    22 #include "WorldSocket.h" 
     22#include "SharedDefines.h" 
    2323#include "WorldSession.h" 
    2424#include "Opcodes.h" 
     
    367367    SendPacket( &data ); 
    368368 
    369     std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; 
     369    std::string IP_str = GetRemoteAddress().c_str(); 
    370370    sLog.outBasic("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); 
    371371    sLog.outChar("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); 
     
    417417        return; 
    418418 
    419     std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; 
     419    std::string IP_str = GetRemoteAddress(); 
    420420    sLog.outBasic("Account: %d (IP: %s) Delete Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); 
    421421    sLog.outChar("Account: %d (IP: %s) Delete Character:[%s] (guid: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); 
     
    735735        SendNotification("GM mode is ON"); 
    736736 
    737     std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; 
     737    std::string IP_str = GetRemoteAddress(); 
    738738    sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUID()); 
    739739 
     
    967967    CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); 
    968968 
    969     std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; 
     969    std::string IP_str = GetRemoteAddress(); 
    970970    sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",GetAccountId(),IP_str.c_str(),oldname.c_str(),GUID_LOPART(guid),newname.c_str()); 
    971971 
  • trunk/src/game/Chat.cpp

    r2 r6  
    194194    { 
    195195        { "all",            SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllCommand,           "", NULL }, 
     196        { "all_loot",       SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllLootCommand,       "", NULL }, 
     197        { "all_npc",        SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllNpcCommand,        "", NULL }, 
    196198        { "all_quest",      SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllQuestCommand,      "", NULL }, 
    197         { "all_loot",       SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllLootCommand,       "", NULL }, 
    198199        { "all_scripts",    SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllScriptsCommand,    "", NULL }, 
    199200        { "all_spell",      SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllSpellCommand,      "", NULL }, 
     
    213214        { "fishing_loot_template",       SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesFishingCommand,    "", NULL }, 
    214215        { "game_graveyard_zone",         SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGameGraveyardZoneCommand,       "", NULL }, 
     216        { "game_tele",                   SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGameTeleCommand,                "", NULL }, 
    215217        { "gameobject_involvedrelation", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGOQuestInvRelationsCommand,     "", NULL }, 
    216218        { "gameobject_loot_template",    SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL }, 
     
    220222        { "item_loot_template",          SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesItemCommand,       "", NULL }, 
    221223        { "mangos_string",               SEC_ADMINISTRATOR, &ChatHandler::HandleReloadMangosStringCommand,            "", NULL }, 
     224        { "npc_gossip",                  SEC_ADMINISTRATOR, &ChatHandler::HandleReloadNpcGossipCommand,               "", NULL }, 
     225        { "npc_trainer",                 SEC_ADMINISTRATOR, &ChatHandler::HandleReloadNpcTrainerCommand,              "", NULL }, 
     226        { "npc_vendor",                  SEC_ADMINISTRATOR, &ChatHandler::HandleReloadNpcVendorCommand,               "", NULL }, 
    222227        { "page_text",                   SEC_ADMINISTRATOR, &ChatHandler::HandleReloadPageTextsCommand,               "", NULL }, 
    223228        { "pickpocketing_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL}, 
     
    265270    }; 
    266271 
     272    static ChatCommand lookupPlayerCommandTable[] = 
     273    { 
     274        { "ip",            SEC_GAMEMASTER,     &ChatHandler::HandleLookupPlayerIpCommand,       "", NULL }, 
     275        { "account",       SEC_GAMEMASTER,     &ChatHandler::HandleLookupPlayerAccountCommand,  "", NULL }, 
     276        { "email",         SEC_GAMEMASTER,     &ChatHandler::HandleLookupPlayerEmailCommand,    "", NULL }, 
     277        { NULL,            0,                  NULL,                                            "", NULL } 
     278    }; 
     279 
    267280    static ChatCommand lookupCommandTable[] = 
    268281    { 
     
    275288        { "object",         SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupObjectCommand,        "", NULL }, 
    276289        { "quest",          SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupQuestCommand,         "", NULL }, 
     290        { "player",         SEC_GAMEMASTER,     NULL,                                           "", lookupPlayerCommandTable }, 
    277291        { "skill",          SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupSkillCommand,         "", NULL }, 
    278292        { "spell",          SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupSpellCommand,         "", NULL }, 
     
    11021116} 
    11031117 
     1118GameTele const* ChatHandler::extractGameTeleFromLink(char* text) 
     1119{ 
     1120    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r 
     1121    char* cId = extractKeyFromLink(text,"Htele"); 
     1122    if(!cId) 
     1123        return false; 
     1124 
     1125    // id case (explicit or from shift link) 
     1126    if(cId[0] >= '0' || cId[0] >= '9') 
     1127        if(uint32 id = atoi(cId)) 
     1128            return objmgr.GetGameTele(id); 
     1129 
     1130    return objmgr.GetGameTele(cId); 
     1131} 
  • trunk/src/game/Chat.h

    r2 r6  
    2727class Player; 
    2828class Unit; 
     29struct GameTele; 
    2930 
    3031struct LanguageDesc 
     
    151152        bool HandleReloadAllItemCommand(const char* args); 
    152153        bool HandleReloadAllLootCommand(const char* args); 
     154        bool HandleReloadAllNpcCommand(const char* args); 
    153155        bool HandleReloadAllQuestCommand(const char* args); 
    154156        bool HandleReloadAllScriptsCommand(const char* args); 
     
    165167        bool HandleReloadGameGraveyardZoneCommand(const char* args); 
    166168        bool HandleReloadGameObjectScriptsCommand(const char* args); 
     169        bool HandleReloadGameTeleCommand(const char* args); 
    167170        bool HandleReloadGOQuestRelationsCommand(const char* args); 
    168171        bool HandleReloadGOQuestInvRelationsCommand(const char* args); 
     
    178181        bool HandleReloadLootTemplatesSkinningCommand(const char* args); 
    179182        bool HandleReloadMangosStringCommand(const char* args); 
     183        bool HandleReloadNpcGossipCommand(const char* args); 
     184        bool HandleReloadNpcTrainerCommand(const char* args); 
     185        bool HandleReloadNpcVendorCommand(const char* args); 
    180186        bool HandleReloadQuestAreaTriggersCommand(const char* args); 
    181187        bool HandleReloadQuestEndScriptsCommand(const char* args); 
     
    265271        bool HandleAllowMovementCommand(const char* args); 
    266272        bool HandleGoCommand(const char* args); 
     273 
    267274        bool HandleLearnCommand(const char* args); 
    268275        bool HandleLearnAllCommand(const char* args); 
     
    275282        bool HandleLearnAllMySpellsCommand(const char* args); 
    276283        bool HandleLearnAllMyTalentsCommand(const char* args); 
     284 
     285        bool HandleLookupAreaCommand(const char* args); 
     286        bool HandleLookupCreatureCommand(const char* args); 
     287        bool HandleLookupEventCommand(const char* args); 
     288        bool HandleLookupFactionCommand(const char * args); 
     289        bool HandleLookupItemCommand(const char * args); 
     290        bool HandleLookupItemSetCommand(const char * args); 
     291        bool HandleLookupObjectCommand(const char* args); 
     292        bool HandleLookupPlayerIpCommand(const char* args); 
     293        bool HandleLookupPlayerAccountCommand(const char* args); 
     294        bool HandleLookupPlayerEmailCommand(const char* args); 
     295        bool HandleLookupQuestCommand(const char* args); 
     296        bool HandleLookupSkillCommand(const char* args); 
     297        bool HandleLookupSpellCommand(const char* args); 
     298        bool HandleLookupTeleCommand(const char * args); 
     299 
    277300        bool HandleCooldownCommand(const char* args); 
    278301        bool HandleUnLearnCommand(const char* args); 
     
    300323        bool HandleAddItemCommand(const char* args); 
    301324        bool HandleAddItemSetCommand(const char* args); 
    302         bool HandleLookupItemCommand(const char * args); 
    303         bool HandleLookupItemSetCommand(const char * args); 
     325 
    304326        bool HandleGuildCreateCommand(const char* args); 
    305327        bool HandleGuildInviteCommand(const char* args); 
     
    315337        bool HandleDelTeleCommand(const char * args); 
    316338        bool HandleListAurasCommand(const char * args); 
    317         bool HandleLookupTeleCommand(const char * args); 
    318339 
    319340        bool HandleResetHonorCommand(const char * args); 
     
    333354        bool HandleListObjectCommand(const char* args); 
    334355        bool HandleNearObjectCommand(const char* args); 
    335         bool HandleLookupAreaCommand(const char* args); 
    336         bool HandleLookupCreatureCommand(const char* args); 
    337         bool HandleLookupEventCommand(const char* args); 
    338         bool HandleLookupFactionCommand(const char * args); 
    339         bool HandleLookupObjectCommand(const char* args); 
    340         bool HandleLookupQuestCommand(const char* args); 
    341         bool HandleLookupSkillCommand(const char* args); 
    342         bool HandleLookupSpellCommand(const char* args); 
    343356        bool HandlePasswordCommand(const char* args); 
    344357        bool HandleLockAccountCommand(const char* args); 
     
    387400        char*     extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL); 
    388401        uint32    extractSpellIdFromLink(char* text); 
     402        GameTele const* extractGameTeleFromLink(char* text); 
    389403 
    390404        GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry); 
     
    395409        void ShowTicket(uint64 guid, char const* text, char const* time); 
    396410        uint32 GetTicketIDByNum(uint32 num); 
     411        bool LookupPlayerSearchCommand(QueryResult* result, int32 limit); 
    397412 
    398413        void SetSentErrorMessage(bool val){ sentErrorMessage = val;}; 
  • trunk/src/game/Creature.cpp

    r2 r6  
    4747#include "Policies/SingletonImp.h" 
    4848 
     49void TrainerSpellData::Clear() 
     50{ 
     51    for (TrainerSpellList::iterator itr = spellList.begin(); itr != spellList.end(); ++itr) 
     52        delete (*itr); 
     53    spellList.empty(); 
     54} 
     55 
     56TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const 
     57{ 
     58    for(TrainerSpellList::const_iterator itr = spellList.begin(); itr != spellList.end(); ++itr) 
     59        if((*itr)->spell == spell_id) 
     60            return *itr; 
     61 
     62    return NULL; 
     63} 
     64 
    4965Creature::Creature() : 
    5066Unit(), i_AI(NULL), 
    5167lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), 
    52 m_itemsLoaded(false), m_trainerSpellsLoaded(false), m_trainer_type(0), m_lootMoney(0), m_lootRecipient(0), 
     68m_itemsLoaded(false), m_lootMoney(0), m_lootRecipient(0), 
    5369m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), 
    54 m_gossipOptionLoaded(false),m_NPCTextId(0), m_emoteState(0), m_isPet(false), m_isTotem(false), 
     70m_gossipOptionLoaded(false),m_emoteState(0), m_isPet(false), m_isTotem(false), 
    5571m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), 
    5672m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), 
     
    7288    CleanupsBeforeDelete(); 
    7389 
    74     m_trainer_spells.clear(); 
    7590    m_vendor_items.clear(); 
    7691 
     
    91106    if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); 
    92107    Unit::RemoveFromWorld(); 
    93 } 
    94  
    95 void Creature::LoadTrainerSpells() 
    96 { 
    97     if(m_trainerSpellsLoaded) 
    98         return; 
    99  
    100     m_trainer_spells.clear(); 
    101     m_trainer_type = 0; 
    102  
    103     Field *fields; 
    104     QueryResult *result = WorldDatabase.PQuery("SELECT spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer WHERE entry = '%u'", GetEntry()); 
    105  
    106     if(!result) 
    107         return; 
    108  
    109     do 
    110     { 
    111         fields = result->Fetch(); 
    112  
    113         uint32 spellid = fields[0].GetUInt32(); 
    114         SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid); 
    115  
    116         if(!spellinfo) 
    117         { 
    118             sLog.outErrorDb("Trainer (Entry: %u ) has non existing spell %u",GetEntry(),spellid); 
    119             continue; 
    120         } 
    121  
    122         if(!SpellMgr::IsSpellValid(spellinfo)) 
    123         { 
    124             sLog.outErrorDb("LoadTrainerSpells: Trainer (Entry: %u) has broken learning spell %u.", GetEntry(), spellid); 
    125             continue; 
    126         } 
    127  
    128         if(SpellMgr::IsProfessionSpell(spellinfo->Id)) 
    129             m_trainer_type = 2; 
    130  
    131         TrainerSpell tspell; 
    132         tspell.spell        = spellinfo; 
    133         tspell.spellcost    = fields[1].GetUInt32(); 
    134         tspell.reqskill     = fields[2].GetUInt32(); 
    135         tspell.reqskillvalue= fields[3].GetUInt32(); 
    136         tspell.reqlevel     = fields[4].GetUInt32(); 
    137  
    138         m_trainer_spells.push_back(tspell); 
    139  
    140     } while( result->NextRow() ); 
    141  
    142     delete result; 
    143  
    144     m_trainerSpellsLoaded = true; 
    145108} 
    146109 
     
    551514        return false; 
    552515 
    553     if(m_trainer_spells.empty()) 
     516    TrainerSpellData const* trainer_spells = GetTrainerSpells(); 
     517 
     518 
     519    if(!trainer_spells || trainer_spells->spellList.empty()) 
    554520    { 
    555521        sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_TRAINER but have empty trainer spell list.", 
     
    719685                        break; 
    720686                    case GOSSIP_OPTION_TRAINER: 
    721                         // Lazy loading at first access 
    722                         LoadTrainerSpells(); 
    723  
    724687                        if(!isCanTrainingOf(pPlayer,false)) 
    725688                            cantalking=false; 
     
    757720            if(!gso->Option.empty() && cantalking ) 
    758721            {                                               //note for future dev: should have database fields for BoxMessage & BoxMoney 
    759                 pm->GetGossipMenu()->AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false); 
     722                pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false); 
    760723                ingso=gso; 
    761724            } 
     
    764727 
    765728    ///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-) 
    766     if(pm->GetGossipMenu()->MenuItemCount()==0 && !pm->GetQuestMenu()->MenuItemCount()) 
     729    if(pm->Empty()) 
    767730    { 
    768731        if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER)) 
    769732        { 
    770             LoadTrainerSpells();                            // Lazy loading at first access 
    771733            isCanTrainingOf(pPlayer,true);                  // output error message if need 
    772734        } 
     
    783745        return; 
    784746 
    785     GossipMenu* gossipmenu = player->PlayerTalkClass->GetGossipMenu(); 
     747    GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu(); 
    786748 
    787749    // in case empty gossip menu open quest menu if any 
    788     if (gossipmenu->MenuItemCount() == 0 && GetNpcTextId() == 0) 
     750    if (gossipmenu.Empty() && GetNpcTextId() == 0) 
    789751    { 
    790752        player->SendPreparedQuest(GetGUID()); 
     
    799761void Creature::OnGossipSelect(Player* player, uint32 option) 
    800762{ 
    801     GossipMenu* gossipmenu = player->PlayerTalkClass->GetGossipMenu(); 
    802     uint32 action=gossipmenu->GetItem(option).m_gAction; 
     763    GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu(); 
     764 
     765    if(option >= gossipmenu.MenuItemCount()) 
     766        return; 
     767 
     768    uint32 action=gossipmenu.GetItem(option).m_gAction; 
    803769    uint32 zoneid=GetZoneId(); 
    804770    uint64 guid=GetGUID(); 
     
    969935uint32 Creature::GetNpcTextId() 
    970936{ 
    971     // already loaded and cached 
    972     if(m_NPCTextId) 
    973         return m_NPCTextId; 
    974  
    975     QueryResult* result = WorldDatabase.PQuery("SELECT textid FROM npc_gossip WHERE npc_guid= '%u'", m_DBTableGuid); 
    976     if(result) 
    977     { 
    978         Field *fields = result->Fetch(); 
    979         m_NPCTextId = fields[0].GetUInt32(); 
    980         delete result; 
    981     } 
    982     else 
    983         m_NPCTextId = DEFAULT_GOSSIP_MESSAGE; 
    984  
    985     return m_NPCTextId; 
     937    if(uint32 pos = objmgr.GetNpcGossip(m_DBTableGuid)) 
     938        return pos; 
     939 
     940    return DEFAULT_GOSSIP_MESSAGE; 
    986941} 
    987942 
     
    14001355    m_vendor_items.clear(); 
    14011356 
    1402     QueryResult *result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry = '%u'", GetEntry()); 
    1403  
    1404     if(!result) 
     1357    VendorItemList const* vList = objmgr.GetNpcVendorItemList(GetEntry()); 
     1358    if(!vList) 
    14051359        return; 
    14061360 
    1407     do 
    1408     { 
    1409         Field *fields = result->Fetch(); 
    1410  
    1411         if (GetItemCount() >= MAX_VENDOR_ITEMS) 
    1412         { 
    1413             sLog.outErrorDb( "Vendor %u has too many items (%u >= %i). Check the DB!", GetEntry(), GetItemCount(), MAX_VENDOR_ITEMS ); 
    1414             break; 
    1415         } 
    1416  
    1417         uint32 item_id = fields[0].GetUInt32(); 
    1418         if(!sItemStorage.LookupEntry<ItemPrototype>(item_id)) 
    1419         { 
    1420             sLog.outErrorDb("Vendor %u have in item list non-existed item %u",GetEntry(),item_id); 
    1421             continue; 
    1422         } 
    1423  
    1424         uint32 ExtendedCost = fields[3].GetUInt32(); 
    1425         if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) 
    1426             sLog.outErrorDb("Item (Entry: %u) has wrong ExtendedCost (%u) for vendor (%u)",item_id,ExtendedCost,GetEntry()); 
    1427  
    1428         AddItem( item_id, fields[1].GetUInt32(), fields[2].GetUInt32(), ExtendedCost); 
    1429     } 
    1430     while( result->NextRow() ); 
    1431  
    1432     delete result; 
     1361    for (VendorItemList::const_iterator _item_iter = vList->begin(); _item_iter != vList->end(); ++_item_iter) 
     1362        AddItem( (*_item_iter)->item, (*_item_iter)->maxcount, (*_item_iter)->incrtime, (*_item_iter)->ExtendedCost); 
    14331363 
    14341364    m_itemsLoaded = true; 
     
    19921922    return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptName; 
    19931923} 
     1924 
     1925TrainerSpellData const* Creature::GetTrainerSpells() const 
     1926{ 
     1927    return objmgr.GetNpcTrainerSpells(GetEntry()); 
     1928} 
  • trunk/src/game/Creature.h

    r2 r6  
    124124    uint32 lastincr; 
    125125    uint32 ExtendedCost; 
    126 }; 
    127  
    128 struct TrainerSpell 
    129 { 
    130     SpellEntry const* spell; 
    131     uint32 spellcost; 
    132     uint32 reqskill; 
    133     uint32 reqskillvalue; 
    134     uint32 reqlevel; 
    135126}; 
    136127 
     
    301292#endif 
    302293 
     294struct TrainerSpell 
     295{ 
     296    uint32 spell; 
     297    uint32 spellcost; 
     298    uint32 reqskill; 
     299    uint32 reqskillvalue; 
     300    uint32 reqlevel; 
     301}; 
     302 
     303typedef std::vector<TrainerSpell*> TrainerSpellList; 
     304 
     305struct TrainerSpellData 
     306{ 
     307    TrainerSpellData() : trainerType(0) {} 
     308 
     309    TrainerSpellList spellList; 
     310    uint32 trainerType;                                     // trainer type based at trainer spells, can be different from creature_template value. 
     311                                                            // req. for correct show non-prof. trainers like weaponmaster, allowed values 0 and 2. 
     312 
     313    void Clear(); 
     314    TrainerSpell const* Find(uint32 spell_id) const; 
     315}; 
     316 
    303317typedef std::list<GossipOption> GossipOptionList; 
    304318 
     
    441455        } 
    442456 
    443         /*********************************************************/ 
    444         /***                    TRAINER SYSTEM                 ***/ 
    445         /*********************************************************/ 
    446         typedef std::list<TrainerSpell> SpellsList; 
    447         void LoadTrainerSpells();                           // must be called before access to trainer spells, lazy loading at first call 
    448         void ReloadTrainerSpells() { m_trainerSpellsLoaded = false; LoadTrainerSpells(); } 
    449         SpellsList const& GetTrainerSpells() const { return m_trainer_spells; } 
    450         uint32 GetTrainerType() const { return m_trainer_type; } 
     457        TrainerSpellData const* GetTrainerSpells() const; 
    451458 
    452459        CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } 
     
    559566        bool m_itemsLoaded;                                 // vendor items loading state 
    560567 
    561         // trainer spells 
    562         bool m_trainerSpellsLoaded;                         // trainer spells loading state 
    563         SpellsList m_trainer_spells; 
    564         uint32 m_trainer_type;                              // trainer type based at trainer spells, can be different from creature_template value. 
    565                                                             // req. for correct show non-prof. trainers like weaponmaster. 
    566568        void _RealtimeSetCreatureInfo(); 
    567569 
     
    581583        bool m_gossipOptionLoaded; 
    582584        GossipOptionList m_goptions; 
    583         uint32 m_NPCTextId;                                 // cached value 
    584585 
    585586        uint8 m_emoteState; 
  • trunk/src/game/CreatureAISelector.cpp

    r2 r6  
    5454        { 
    5555            if( creature->isGuard() ) 
    56                 ainame="GuardAI"; 
     56                ai_factory = ai_registry.GetRegistryItem("GuardAI");  
    5757            else if(creature->isPet() || creature->isCharmed()) 
    58                 ainame="PetAI"; 
     58                ai_factory = ai_registry.GetRegistryItem("PetAI"); 
    5959            else if(creature->isTotem()) 
    60                 ainame="TotemAI"; 
    61  
    62             ai_factory = ai_registry.GetRegistryItem( ainame.c_str() ); 
     60                ai_factory = ai_registry.GetRegistryItem("TotemAI"); 
    6361        } 
    6462 
  • trunk/src/game/GossipDef.cpp

    r2 r6  
    9292} 
    9393 
    94 PlayerMenu::PlayerMenu( WorldSession *Session ) 
    95 { 
    96     pGossipMenu = new GossipMenu(); 
    97     pQuestMenu  = new QuestMenu(); 
    98     pSession    = Session; 
     94PlayerMenu::PlayerMenu( WorldSession *session ) : pSession(session) 
     95{ 
    9996} 
    10097 
    10198PlayerMenu::~PlayerMenu() 
    10299{ 
    103     delete pGossipMenu; 
    104     delete pQuestMenu; 
     100    ClearMenus(); 
    105101} 
    106102 
    107103void PlayerMenu::ClearMenus() 
    108104{ 
    109     pGossipMenu->ClearMenu(); 
    110     pQuestMenu->ClearMenu(); 
     105    mGossipMenu.ClearMenu(); 
     106    mQuestMenu.ClearMenu(); 
    111107} 
    112108 
    113109uint32 PlayerMenu::GossipOptionSender( unsigned int Selection ) 
    114110{ 
    115     return pGossipMenu->MenuItemSender( Selection ); 
     111    return mGossipMenu.MenuItemSender( Selection ); 
    116112} 
    117113 
    118114uint32 PlayerMenu::GossipOptionAction( unsigned int Selection ) 
    119115{ 
    120     return pGossipMenu->MenuItemAction( Selection ); 
     116    return mGossipMenu.MenuItemAction( Selection ); 
    121117} 
    122118 
    123119bool PlayerMenu::GossipOptionCoded( unsigned int Selection ) 
    124120{ 
    125     return pGossipMenu->MenuItemCoded( Selection ); 
     121    return mGossipMenu.MenuItemCoded( Selection ); 
    126122} 
    127123 
     
    132128    data << uint32(0);                                      // new 2.4.0 
    133129    data << uint32( TitleTextId ); 
    134     data << uint32( pGossipMenu->MenuItemCount() );         // max count 0x0F 
    135  
    136     for ( unsigned int iI = 0; iI < pGossipMenu->MenuItemCount(); iI++ ) 
    137     { 
    138         GossipMenuItem const& gItem = pGossipMenu->GetItem(iI); 
     130    data << uint32( mGossipMenu.MenuItemCount() );         // max count 0x0F 
     131 
     132    for ( unsigned int iI = 0; iI < mGossipMenu.MenuItemCount(); iI++ ) 
     133    { 
     134        GossipMenuItem const& gItem = mGossipMenu.GetItem(iI); 
    139135        data << uint32( iI ); 
    140136        data << uint8( gItem.m_gIcon ); 
     
    151147    } 
    152148 
    153     data << uint32( pQuestMenu->MenuItemCount() );          // max count 0x20 
    154  
    155     for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ ) 
    156     { 
    157         QuestMenuItem const& qItem = pQuestMenu->GetItem(iI); 
     149    data << uint32( mQuestMenu.MenuItemCount() );          // max count 0x20 
     150 
     151    for ( uint16 iI = 0; iI < mQuestMenu.MenuItemCount(); iI++ ) 
     152    { 
     153        QuestMenuItem const& qItem = mQuestMenu.GetItem(iI); 
    158154        uint32 questID = qItem.m_qId; 
    159155        Quest const* pQuest = objmgr.GetQuestTemplate(questID); 
     
    358354    data << uint32(eEmote._Delay );                         // player emote 
    359355    data << uint32(eEmote._Emote );                         // NPC emote 
    360     data << uint8 ( pQuestMenu->MenuItemCount() ); 
    361  
    362     for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ ) 
    363     { 
    364         QuestMenuItem qmi=pQuestMenu->GetItem(iI); 
     356    data << uint8 ( mQuestMenu.MenuItemCount() ); 
     357 
     358    for ( uint16 iI = 0; iI < mQuestMenu.MenuItemCount(); iI++ ) 
     359    { 
     360        QuestMenuItem const& qmi = mQuestMenu.GetItem(iI); 
     361 
    365362        uint32 questID = qmi.m_qId; 
    366363        Quest const *pQuest = objmgr.GetQuestTemplate(questID); 
  • trunk/src/game/GossipDef.h

    r2 r6  
    109109        void AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded = false); 
    110110 
    111         unsigned int MenuItemCount() 
     111        unsigned int MenuItemCount() const 
    112112        { 
    113113            return m_gItems.size(); 
     114        } 
     115 
     116        bool Empty() const 
     117        { 
     118            return m_gItems.empty(); 
    114119        } 
    115120 
     
    138143        void ClearMenu(); 
    139144 
    140         uint8 MenuItemCount() 
     145        uint8 MenuItemCount() const 
    141146        { 
    142147            return m_qItems.size(); 
    143148        } 
     149 
     150        bool Empty() const 
     151        { 
     152            return m_qItems.empty(); 
     153        } 
     154 
    144155        bool HasItem( uint32 questid ); 
    145156 
     
    156167{ 
    157168    private: 
    158         GossipMenu* pGossipMenu; 
    159         QuestMenu* pQuestMenu; 
     169        GossipMenu mGossipMenu; 
     170        QuestMenu  mQuestMenu; 
    160171        WorldSession* pSession; 
    161172 
     
    164175        ~PlayerMenu(); 
    165176 
    166         GossipMenu* GetGossipMenu() { return pGossipMenu; } 
    167         QuestMenu* GetQuestMenu() { return pQuestMenu; } 
     177        GossipMenu& GetGossipMenu() { return mGossipMenu; } 
     178        QuestMenu& GetQuestMenu() { return mQuestMenu; } 
     179 
     180        bool Empty() const { return mGossipMenu.Empty() && mQuestMenu.Empty(); } 
    168181 
    169182        void ClearMenus(); 
  • trunk/src/game/GridNotifiers.h

    r2 r6  
    113113        bool i_ownTeamOnly; 
    114114        float i_dist; 
    115         MessageDistDeliverer(Player &pl, WorldPacket *msg, bool to_self, bool ownTeamOnly, float dist) : i_player(pl), i_message(msg), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly), i_dist(dist) {} 
     115        MessageDistDeliverer(Player &pl, WorldPacket *msg, float dist, bool to_self, bool ownTeamOnly) : i_player(pl), i_message(msg), i_dist(dist), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly) {} 
    116116        void Visit(PlayerMapType &m); 
    117117        template<class SKIP> void Visit(GridRefManager<SKIP> &) {} 
  • trunk/src/game/GuardAI.cpp

    r2 r6  
    3838void GuardAI::MoveInLineOfSight(Unit *u) 
    3939{ 
     40    // Ignore Z for flying creatures 
     41    if ( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) 
     42        return; 
     43 
    4044    if( !i_creature.getVictim() && u->isTargetableForAttack() && 
    4145        ( u->IsHostileToPlayers() || i_creature.IsHostileTo(u) /*|| u->getVictim() && i_creature.IsFriendlyTo(u->getVictim())*/ ) && 
     
    4347    { 
    4448        float attackRadius = i_creature.GetAttackDistance(u); 
    45         if(i_creature.IsWithinDistInMap(u,attackRadius) && i_creature.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE) 
     49        if(i_creature.IsWithinDistInMap(u,attackRadius)) 
    4650        { 
    4751            //Need add code to let guard support player 
  • trunk/src/game/Guild.cpp

    r2 r6  
    18061806        need_space = count; 
    18071807 
    1808     dest.push_back(GuildItemPosCount(slot,need_space)); 
    1809     count -= need_space; 
     1808    GuildItemPosCount newPosition = GuildItemPosCount(slot,need_space); 
     1809    if(!newPosition.isContainedIn(dest)) 
     1810    { 
     1811        dest.push_back(newPosition); 
     1812        count -= need_space; 
     1813    } 
     1814 
    18101815    return EQUIP_ERR_OK; 
    18111816} 
     
    18371842                    need_space = count; 
    18381843 
    1839                 dest.push_back(GuildItemPosCount(j,need_space)); 
     1844                GuildItemPosCount newPosition = GuildItemPosCount(j,need_space); 
     1845                if(!newPosition.isContainedIn(dest)) 
     1846                { 
     1847                    dest.push_back(newPosition); 
     1848                    count -= need_space; 
     1849 
     1850                    if(count==0) 
     1851                        return EQUIP_ERR_OK; 
     1852                } 
     1853            } 
     1854        } 
     1855        else 
     1856        { 
     1857            uint32 need_space = pSrcItem->GetMaxStackCount(); 
     1858            if(need_space > count) 
     1859                need_space = count; 
     1860 
     1861            GuildItemPosCount newPosition = GuildItemPosCount(j,need_space); 
     1862            if(!newPosition.isContainedIn(dest)) 
     1863            { 
     1864                dest.push_back(newPosition); 
    18401865                count -= need_space; 
    18411866 
     
    18431868                    return EQUIP_ERR_OK; 
    18441869            } 
    1845         } 
    1846         else 
    1847         { 
    1848             uint32 need_space = pSrcItem->GetMaxStackCount(); 
    1849             if(need_space > count) 
    1850                 need_space = count; 
    1851  
    1852             dest.push_back(GuildItemPosCount(j,need_space)); 
    1853             count -= need_space; 
    1854  
    1855             if(count==0) 
    1856                 return EQUIP_ERR_OK; 
    18571870        } 
    18581871    } 
     
    19391952    session->SendPacket(&data); 
    19401953} 
     1954 
     1955bool GuildItemPosCount::isContainedIn(GuildItemPosCountVec const &vec) const 
     1956{ 
     1957    for(GuildItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) 
     1958        if(itr->slot == this->slot) 
     1959            return true; 
     1960 
     1961    return false; 
     1962} 
     1963 
  • trunk/src/game/Guild.h

    r2 r6  
    217217{ 
    218218    GuildItemPosCount(uint8 _slot, uint8 _count) : slot(_slot), count(_count) {} 
     219 
     220    bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const; 
    219221 
    220222    uint8 slot; 
  • trunk/src/game/Language.h

    r2 r6  
    154154    LANG_COMMAND_TELE_NOTFOUND          = 164, 
    155155    LANG_COMMAND_TELE_PARAMETER         = 165, 
    156     LANG_COMMAND_TELE_NOREQUEST         = 166, 
    157     LANG_COMMAND_TELE_NOLOCATION        = 167, 
     156    LANG_COMMAND_TELE_NOLOCATION        = 166, 
     157    //                                    167               // not used 
    158158    LANG_COMMAND_TELE_LOCATION          = 168, 
    159159 
     
    301301    LANG_COMMAND_FACTION_NOREP_ERROR    = 326, 
    302302    LANG_FACTION_NOREPUTATION           = 327, 
     303    LANG_LOOKUP_PLAYER_ACCOUNT          = 328, 
     304    LANG_LOOKUP_PLAYER_CHARACTER        = 329, 
     305    LANG_NO_PLAYERS_FOUND               = 330, 
    303306 
    304307    // Room for more level 2 
     
    376379    LANG_COMMAND_TP_ADDEDERR            = 464, 
    377380    LANG_COMMAND_TP_DELETED             = 465, 
    378     LANG_COMMAND_TP_DELETEERR           = 466, 
     381    //                                    466,              // not used 
    379382 
    380383    LANG_COMMAND_TARGET_LISTAURAS       = 467, 
  • trunk/src/game/Level1.cpp

    r2 r6  
    15551555} 
    15561556 
    1557 //Teleport by game_tele entry 
    15581557bool ChatHandler::HandleModifyHonorCommand (const char* args) 
    15591558{ 
     
    15851584    Player* _player = m_session->GetPlayer(); 
    15861585 
    1587     char* cId = extractKeyFromLink((char*)args,"Htele");    // string or [name] Shift-click form |color|Htele:name|h[name]|h|r 
    1588     if(!cId) 
    1589         return false; 
    1590  
    1591     std::string name = cId; 
    1592     WorldDatabase.escape_string(name); 
    1593  
    1594     QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",name.c_str()); 
    1595     if (!result) 
     1586    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r 
     1587    GameTele const* tele = extractGameTeleFromLink((char*)args); 
     1588 
     1589    if (!tele) 
    15961590    { 
    15971591        SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); 
    1598         SetSentErrorMessage(true); 
    1599         return false; 
    1600     } 
    1601     Field *fields = result->Fetch(); 
    1602     float x = fields[0].GetFloat(); 
    1603     float y = fields[1].GetFloat(); 
    1604     float z = fields[2].GetFloat(); 
    1605     float ort = fields[3].GetFloat(); 
    1606     int mapid = fields[4].GetUInt16(); 
    1607     delete result; 
    1608  
    1609     if(!MapManager::IsValidMapCoord(mapid,x,y,x,ort)) 
    1610     { 
    1611         PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); 
    16121592        SetSentErrorMessage(true); 
    16131593        return false; 
     
    16241604        _player->SaveRecallPosition(); 
    16251605 
    1626     _player->TeleportTo(mapid, x, y, z, ort); 
     1606    _player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); 
    16271607    return true; 
    16281608} 
     
    17031683 
    17041684    std::string namepart = str; 
    1705     WorldDatabase.escape_string(namepart); 
    1706     QueryResult *result = WorldDatabase.PQuery("SELECT name FROM game_tele WHERE name "_LIKE_" '""%%%s%%""'",namepart.c_str()); 
    1707     if (!result) 
    1708     { 
    1709         SendSysMessage(LANG_COMMAND_TELE_NOREQUEST); 
    1710         SetSentErrorMessage(true); 
    1711         return false; 
    1712     } 
    1713     std::string reply; 
    1714     for (uint64 i=0; i < result->GetRowCount(); i++) 
    1715     { 
    1716         Field *fields = result->Fetch(); 
    1717         reply += "  |cffffffff|Htele:"; 
    1718         reply += fields[0].GetCppString(); 
    1719         reply += "|h["; 
    1720         reply += fields[0].GetCppString(); 
    1721         reply += "]|h|r\n"; 
    1722         result->NextRow(); 
    1723     } 
    1724     delete result; 
    1725  
    1726     if(reply.empty()) 
     1685    std::wstring wnamepart; 
     1686 
     1687    if(!Utf8toWStr(namepart,wnamepart)) 
     1688        return false; 
     1689 
     1690    // converting string that we try to find to lower case 
     1691    wstrToLower( wnamepart ); 
     1692 
     1693    GameTeleMap const & teleMap = objmgr.GetGameTeleMap(); 
     1694 
     1695    std::ostringstream reply; 
     1696    for(GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) 
     1697    { 
     1698        GameTele const* tele = &itr->second; 
     1699 
     1700        if(tele->wnameLow.find(wnamepart) == std::wstring::npos) 
     1701            continue; 
     1702 
     1703        reply << "  |cffffffff|Htele:"; 
     1704        reply << itr->first; 
     1705        reply << "|h["; 
     1706        reply << tele->name; 
     1707        reply << "]|h|r\n"; 
     1708    } 
     1709 
     1710    if(reply.str().empty()) 
    17271711        SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); 
    17281712    else 
    1729     { 
    1730         reply = GetMangosString(LANG_COMMAND_TELE_LOCATION) + reply; 
    1731         SendSysMessage(reply.c_str()); 
    1732     } 
     1713        PSendSysMessage(LANG_COMMAND_TELE_LOCATION,reply.str().c_str()); 
     1714 
    17331715    return true; 
    17341716} 
     
    18621844        return false; 
    18631845 
     1846    std::string name = pName; 
     1847 
     1848    if(!normalizePlayerName(name)) 
     1849    { 
     1850        SendSysMessage(LANG_PLAYER_NOT_FOUND); 
     1851        SetSentErrorMessage(true); 
     1852        return false; 
     1853    } 
     1854 
    18641855    char* tail = strtok(NULL, ""); 
    18651856    if(!tail) 
    18661857        return false; 
    18671858 
    1868     char* cId = extractKeyFromLink((char*)tail,"Htele");    // string or [name] Shift-click form |color|Htele:name|h[name]|h|r 
    1869     if(!cId) 
    1870         return false; 
    1871  
    1872     std::string location = cId; 
    1873  
    1874     std::string name = pName; 
    1875  
    1876     if(!normalizePlayerName(name)) 
    1877     { 
    1878         SendSysMessage(LANG_PLAYER_NOT_FOUND); 
    1879         SetSentErrorMessage(true); 
    1880         return false; 
    1881     } 
    1882  
    1883     WorldDatabase.escape_string(location); 
    1884     QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str()); 
    1885     if (!result) 
     1859    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r 
     1860    GameTele const* tele = extractGameTeleFromLink(tail); 
     1861    if(!tele) 
    18861862    { 
    18871863        SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); 
    1888         SetSentErrorMessage(true); 
    1889         return false; 
    1890     } 
    1891  
    1892     Field *fields = result->Fetch(); 
    1893     float x = fields[0].GetFloat(); 
    1894     float y = fields[1].GetFloat(); 
    1895     float z = fields[2].GetFloat(); 
    1896     float ort = fields[3].GetFloat(); 
    1897     int mapid = fields[4].GetUInt16(); 
    1898     delete result; 
    1899  
    1900     if(!MapManager::IsValidMapCoord(mapid,x,y,x,ort)) 
    1901     { 
    1902         PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); 
    19031864        SetSentErrorMessage(true); 
    19041865        return false; 
     
    19161877        } 
    19171878 
    1918         PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", location.c_str()); 
     1879        PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", tele->name.c_str()); 
    19191880 
    19201881        if (m_session->GetPlayer()->IsVisibleGloballyFor(chr)) 
     
    19311892            chr->SaveRecallPosition(); 
    19321893 
    1933         chr->TeleportTo(mapid,x,y,z,chr->GetOrientation()); 
     1894        chr->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); 
    19341895    } 
    19351896    else if (uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str())) 
    19361897    { 
    1937         PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetMangosString(LANG_OFFLINE), location.c_str()); 
    1938         Player::SavePositionInDB(mapid,x,y,z,ort,MapManager::Instance().GetZoneId(mapid,x,y),guid); 
     1898        PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str()); 
     1899        Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation,MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y),guid); 
    19391900    } 
    19401901    else 
     
    19581919    } 
    19591920 
    1960     char* cId = extractKeyFromLink((char*)args,"Htele");    // string or [name] Shift-click form |color|Htele:name|h[name]|h|r 
    1961     if(!cId) 
    1962         return false; 
    1963  
    1964     std::string location = cId; 
    1965  
    1966     WorldDatabase.escape_string(location); 
    1967     QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str()); 
    1968     if (!result) 
     1921    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r 
     1922    GameTele const* tele = extractGameTeleFromLink((char*)args); 
     1923    if(!tele) 
    19691924    { 
    19701925        SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); 
     
    19721927        return false; 
    19731928    } 
    1974     Field *fields = result->Fetch(); 
    1975     float x = fields[0].GetFloat(); 
    1976     float y = fields[1].GetFloat(); 
    1977     float z = fields[2].GetFloat(); 
    1978     float ort = fields[3].GetFloat(); 
    1979     int mapid = fields[4].GetUInt16(); 
    1980     delete result; 
    1981  
    1982     if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) 
    1983     { 
    1984         PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); 
    1985         SetSentErrorMessage(true); 
    1986         return false; 
    1987     } 
    19881929 
    19891930    Group *grp = player->GetGroup(); 
    1990  
    19911931    if(!grp) 
    19921932    { 
     
    20091949        } 
    20101950 
    2011         PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", location.c_str()); 
     1951        PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", tele->name.c_str()); 
    20121952 
    20131953        if (m_session->GetPlayer() != pl && m_session->GetPlayer()->IsVisibleGloballyFor(pl)) 
     
    20241964            pl->SaveRecallPosition(); 
    20251965 
    2026         pl->TeleportTo(mapid, x, y, z, ort); 
     1966        pl->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); 
    20271967    } 
    20281968 
  • trunk/src/game/Level2.cpp

    r2 r6  
    3434#include "GameEvent.h" 
    3535#include "SpellMgr.h" 
     36#include "AccountMgr.h" 
    3637#include "WaypointManager.h" 
    3738#include "Util.h" 
     
    208209            result = WorldDatabase.PQuery( 
    209210                "SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " 
    210                 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" '""%%%s%%""' ORDER BY order_ ASC LIMIT 1", 
     211                "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1", 
    211212                pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str()); 
    212213        } 
     
    39473948    return false; 
    39483949} 
     3950 
     3951bool ChatHandler::HandleLookupPlayerIpCommand(const char* args) 
     3952{ 
     3953   
     3954    if(!*args) 
     3955        return false; 
     3956 
     3957    std::string ip = strtok((char*)args, " "); 
     3958    char* limit_str = strtok(NULL, " "); 
     3959    int32 limit = limit_str ? atoi(limit_str) : -1; 
     3960 
     3961    loginDatabase.escape_string(ip); 
     3962 
     3963    QueryResult* result = loginDatabase.PQuery("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str()); 
     3964 
     3965    return LookupPlayerSearchCommand(result,limit); 
     3966} 
     3967 
     3968bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args) 
     3969{ 
     3970    if(!*args) 
     3971        return false; 
     3972 
     3973    std::string account = strtok((char*)args, " "); 
     3974    char* limit_str = strtok(NULL, " "); 
     3975    int32 limit = limit_str ? atoi(limit_str) : -1; 
     3976 
     3977    if(!AccountMgr::normilizeString(account)) 
     3978        return false; 
     3979 
     3980    loginDatabase.escape_string(account); 
     3981 
     3982    QueryResult* result = loginDatabase.PQuery("SELECT id,username FROM account WHERE username = '%s'", account.c_str()); 
     3983 
     3984    return LookupPlayerSearchCommand(result,limit); 
     3985} 
     3986 
     3987bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args) 
     3988{ 
     3989   
     3990    if(!*args) 
     3991        return false; 
     3992 
     3993    std::string email = strtok((char*)args, " "); 
     3994    char* limit_str = strtok(NULL, " "); 
     3995    int32 limit = limit_str ? atoi(limit_str) : -1; 
     3996 
     3997    loginDatabase.escape_string(email); 
     3998 
     3999    QueryResult* result = loginDatabase.PQuery("SELECT id,username FROM account WHERE email = '%s'", email.c_str()); 
     4000 
     4001    return LookupPlayerSearchCommand(result,limit); 
     4002} 
     4003 
     4004bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit) 
     4005{ 
     4006    if(!result) 
     4007    { 
     4008        PSendSysMessage(LANG_NO_PLAYERS_FOUND); 
     4009        SetSentErrorMessage(true); 
     4010        return false; 
     4011    } 
     4012 
     4013    int i =0; 
     4014    do 
     4015    { 
     4016        Field* fields = result->Fetch(); 
     4017        uint32 acc_id = fields[0].GetUInt32(); 
     4018        std::string acc_name = fields[1].GetCppString(); 
     4019         
     4020        QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id); 
     4021        if(chars) 
     4022        { 
     4023            PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id); 
     4024 
     4025            uint64 guid = 0; 
     4026            std::string name; 
     4027 
     4028            do 
     4029            { 
     4030                Field* charfields = chars->Fetch(); 
     4031                guid = charfields[0].GetUInt64(); 
     4032                name = charfields[1].GetCppString(); 
     4033 
     4034                PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid); 
     4035                ++i; 
     4036 
     4037            } while( chars->NextRow() && ( limit == -1 || i < limit ) ); 
     4038 
     4039            delete chars; 
     4040        } 
     4041    } while(result->NextRow()); 
     4042 
     4043    delete result; 
     4044 
     4045    return true; 
     4046} 
  • trunk/src/game/Level3.cpp

    r2 r6  
    6262{ 
    6363    HandleReloadAreaTriggerTeleportCommand(""); 
    64     //HandleReloadAreaTriggerTavernCommand(""); -- reloaded in HandleReloadAreaTriggerTavernCommand 
    65     //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand 
    6664    HandleReloadSkillFishingBaseLevelCommand(""); 
    6765 
     66    HandleReloadAllAreaCommand(""); 
    6867    HandleReloadAllLootCommand(""); 
     68    HandleReloadAllNpcCommand(""); 
    6969    HandleReloadAllQuestCommand(""); 
    7070    HandleReloadAllSpellCommand(""); 
     
    7474    HandleReloadReservedNameCommand(""); 
    7575    HandleReloadMangosStringCommand(""); 
     76    HandleReloadGameTeleCommand(""); 
    7677    return true; 
    7778} 
     
    7980bool ChatHandler::HandleReloadAllAreaCommand(const char*) 
    8081{ 
     82    //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand 
    8183    HandleReloadAreaTriggerTeleportCommand(""); 
    82     //HandleReloadAreaTriggerTavernCommand(""); -- reloaded in HandleReloadAreaTriggerTavernCommand 
     84    HandleReloadAreaTriggerTavernCommand(""); 
     85    HandleReloadGameGraveyardZoneCommand(""); 
     86    return true; 
     87} 
     88 
     89bool ChatHandler::HandleReloadAllLootCommand(const char*) 
     90{ 
     91    sLog.outString( "Re-Loading Loot Tables..." ); 
     92    LoadLootTables(); 
     93    SendGlobalSysMessage("DB tables `*_loot_template` reloaded."); 
     94    return true; 
     95} 
     96 
     97bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/) 
     98{ 
     99    HandleReloadNpcGossipCommand("a"); 
     100    HandleReloadNpcTrainerCommand("a"); 
     101    HandleReloadNpcVendorCommand("a"); 
    83102    return true; 
    84103} 
     
    92111    objmgr.LoadQuestRelations(); 
    93112    SendGlobalSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded."); 
    94     return true; 
    95 } 
    96  
    97 bool ChatHandler::HandleReloadAllLootCommand(const char*) 
    98 { 
    99     sLog.outString( "Re-Loading Loot Tables..." ); 
    100     LoadLootTables(); 
    101     SendGlobalSysMessage("DB tables `*_loot_template` reloaded."); 
    102113    return true; 
    103114} 
     
    321332} 
    322333 
     334bool ChatHandler::HandleReloadNpcGossipCommand(const char*) 
     335{ 
     336    sLog.outString( "Re-Loading `npc_gossip` Table!" ); 
     337    objmgr.LoadNpcTextId(); 
     338    SendGlobalSysMessage("DB table `npc_gossip` reloaded."); 
     339    return true; 
     340} 
     341 
     342bool ChatHandler::HandleReloadNpcTrainerCommand(const char*) 
     343{ 
     344    sLog.outString( "Re-Loading `npc_trainer` Table!" ); 
     345    objmgr.LoadTrainerSpell(); 
     346    SendGlobalSysMessage("DB table `npc_trainer` reloaded."); 
     347    return true; 
     348} 
     349 
     350bool ChatHandler::HandleReloadNpcVendorCommand(const char*) 
     351{ 
     352    sLog.outString( "Re-Loading `npc_vendor` Table!" ); 
     353    objmgr.LoadVendors(); 
     354    SendGlobalSysMessage("DB table `npc_vendor` reloaded."); 
     355    return true; 
     356} 
     357 
    323358bool ChatHandler::HandleReloadReservedNameCommand(const char*) 
    324359{ 
     
    548583 
    549584    SendGlobalSysMessage("DB table `game_graveyard_zone` reloaded."); 
     585 
     586    return true; 
     587} 
     588 
     589bool ChatHandler::HandleReloadGameTeleCommand(const char* /*arg*/) 
     590{ 
     591    sLog.outString( "Re-Loading Game Tele coordinates..."); 
     592 
     593    objmgr.LoadGameTele(); 
     594 
     595    SendGlobalSysMessage("DB table `game_tele` reloaded."); 
    550596 
    551597    return true; 
     
    38703916    if(!*args) 
    38713917        return false; 
    3872     QueryResult *result; 
     3918 
    38733919    Player *player=m_session->GetPlayer(); 
    3874     if (!player) return false; 
     3920    if (!player) 
     3921        return false; 
    38753922 
    38763923    std::string name = args; 
    3877     WorldDatabase.escape_string(name); 
    3878     result = WorldDatabase.PQuery("SELECT id FROM game_tele WHERE name = '%s'",name.c_str()); 
    3879     if (result) 
     3924 
     3925    if(objmgr.GetGameTele(name)) 
    38803926    { 
    38813927        SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST); 
    3882         delete result; 
    3883         SetSentErrorMessage(true); 
    3884         return false; 
    3885     } 
    3886  
    3887     float x = player->GetPositionX(); 
    3888     float y = player->GetPositionY(); 
    3889     float z = player->GetPositionZ(); 
    3890     float ort = player->GetOrientation(); 
    3891     int mapid = player->GetMapId(); 
    3892  
    3893     if(WorldDatabase.PExecuteLog("INSERT INTO game_tele (position_x,position_y,position_z,orientation,map,name) VALUES (%f,%f,%f,%f,%d,'%s')",x,y,z,ort,mapid,name.c_str())) 
     3928        SetSentErrorMessage(true); 
     3929        return false; 
     3930    } 
     3931 
     3932    GameTele tele; 
     3933    tele.position_x  = player->GetPositionX(); 
     3934    tele.position_y  = player->GetPositionY(); 
     3935    tele.position_z  = player->GetPositionZ(); 
     3936    tele.orientation = player->GetOrientation(); 
     3937    tele.mapId       = player->GetMapId(); 
     3938    tele.name        = name; 
     3939 
     3940    if(objmgr.AddGameTele(tele)) 
    38943941    { 
    38953942        SendSysMessage(LANG_COMMAND_TP_ADDED); 
     
    39113958 
    39123959    std::string name = args; 
    3913     WorldDatabase.escape_string(name); 
    3914  
    3915     QueryResult *result=WorldDatabase.PQuery("SELECT id FROM game_tele WHERE name = '%s'",name.c_str()); 
    3916     if (!result) 
     3960 
     3961    if(!objmgr.DeleteGameTele(name)) 
    39173962    { 
    39183963        SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); 
     
    39203965        return false; 
    39213966    } 
    3922     delete result; 
    3923  
    3924     if(WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",name.c_str())) 
    3925     { 
    3926         SendSysMessage(LANG_COMMAND_TP_DELETED); 
    3927     } 
    3928     else 
    3929     { 
    3930         SendSysMessage(LANG_COMMAND_TP_DELETEERR); 
    3931         SetSentErrorMessage(true); 
    3932         return false; 
    3933     } 
     3967 
     3968    SendSysMessage(LANG_COMMAND_TP_DELETED); 
    39343969    return true; 
    39353970} 
     
    47594794    if(Type == "ip") 
    47604795    { 
    4761         result = loginDatabase.PQuery("SELECT ip FROM ip_banned WHERE ip "_LIKE_" '""%%%s%%""'",Filter.c_str()); 
     4796        result = loginDatabase.PQuery("SELECT ip FROM ip_banned WHERE ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),Filter.c_str()); 
    47624797        if(!result) 
    47634798        { 
     
    47784813    if(Type == "account") 
    47794814    { 
    4780         result = loginDatabase.PQuery("SELECT id FROM account WHERE username "_LIKE_" '""%%%s%%""' ",Filter.c_str()); 
     4815        result = loginDatabase.PQuery("SELECT id FROM account WHERE username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),Filter.c_str()); 
    47814816        if (!result) 
    47824817        { 
     
    47884823    else if(Type == "characters") 
    47894824    { 
    4790         result = CharacterDatabase.PQuery("SELECT account FROM characters, WHERE name "_LIKE_" '""%%%s%%""' ",Filter.c_str()); 
     4825        result = CharacterDatabase.PQuery("SELECT account FROM characters, WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),Filter.c_str()); 
    47914826        if (!result) 
    47924827        { 
  • trunk/src/game/Makefile.am

    r2 r6  
    3131$(POSTGRE_INCLUDES) \ 
    3232-I$(top_srcdir)/dep/include \ 
     33-I$(top_srcdir)/dep/ACE_wrappers \ 
     34-I$(top_builddir)/dep/ACE_wrappers \ 
    3335-I$(top_srcdir)/src/framework \ 
    3436-I$(top_srcdir)/src/shared \ 
  • trunk/src/game/NPCHandler.cpp

    r2 r6  
    130130        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); 
    131131 
    132     // Lazy loading at first access 
    133     unit->LoadTrainerSpells(); 
    134  
    135132    // trainer list loaded at check; 
    136133    if(!unit->isCanTrainingOf(_player,true)) 
     
    145142    } 
    146143 
    147     Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells(); 
    148  
    149     WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells.size()*38 + strTitle.size()+1); 
     144    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); 
     145    if(!trainer_spells) 
     146    { 
     147        sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", guid, unit->GetEntry()); 
     148        return; 
     149    } 
     150 
     151    WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); 
    150152    data << guid; 
    151     data << uint32(unit->GetTrainerType()); 
     153    data << uint32(trainer_spells->trainerType); 
    152154 
    153155    size_t count_pos = data.wpos(); 
    154     data << uint32(trainer_spells.size()); 
     156    data << uint32(trainer_spells->spellList.size()); 
    155157 
    156158    // reputation discount 
     
    158160 
    159161    uint32 count = 0; 
    160     for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr) 
    161     { 
    162         if(!_player->IsSpellFitByClassAndRace(itr->spell->Id)) 
     162    for(TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) 
     163    { 
     164        TrainerSpell const* tSpell = *itr; 
     165 
     166        if(!_player->IsSpellFitByClassAndRace(tSpell->spell)) 
    163167            continue; 
    164168 
    165169        ++count; 
    166170 
    167         bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(itr->spell->Id); 
    168  
    169         SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(itr->spell->Id); 
    170  
    171         data << uint32(itr->spell->Id); 
    172         data << uint8(_player->GetTrainerSpellState(&*itr)); 
    173         data << uint32(floor(itr->spellcost * fDiscountMod)); 
     171        bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell); 
     172 
     173        SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell); 
     174 
     175        data << uint32(tSpell->spell); 
     176        data << uint8(_player->GetTrainerSpellState(tSpell)); 
     177        data << uint32(floor(tSpell->spellcost * fDiscountMod)); 
    174178 
    175179        data << uint32(primary_prof_first_rank ? 1 : 0);    // primary prof. learn confirmation dialog 
    176180        data << uint32(primary_prof_first_rank ? 1 : 0);    // must be equal prev. field to have learn button in enabled state 
    177         data << uint8(itr->reqlevel ? itr->reqlevel : itr->spell->spellLevel); 
    178         data << uint32(itr->reqskill); 
    179         data << uint32(itr->reqskillvalue); 
     181        data << uint8(tSpell->reqlevel); 
     182        data << uint32(tSpell->reqskill); 
     183        data << uint32(tSpell->reqskillvalue); 
    180184        data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0); 
    181185        data << uint32(chain_node && chain_node->prev ? chain_node->req : 0); 
     
    210214        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); 
    211215 
    212     // Lazy loading at first access 
    213     unit->LoadTrainerSpells(); 
    214  
    215216    if(!unit->isCanTrainingOf(_player,true)) 
    216217        return; 
    217218 
    218     TrainerSpell const* trainer_spell = NULL; 
    219  
    220219    // check present spell in trainer spell list 
    221     Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells(); 
    222     for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr) 
    223     { 
    224         if(itr->spell->Id == spellId) 
    225         { 
    226             trainer_spell = &*itr; 
    227             break; 
    228         } 
    229     } 
     220    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); 
     221    if(!trainer_spells) 
     222        return;  
    230223 
    231224    // not found, cheat? 
     225    TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); 
    232226    if(!trainer_spell) 
    233227        return; 
     
    255249 
    256250    // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation 
    257     _player->learnSpell(trainer_spell->spell->Id); 
     251    _player->learnSpell(trainer_spell->spell); 
    258252 
    259253    data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); 
  • trunk/src/game/ObjectMgr.cpp

    r2 r6  
    133133    for(ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr) 
    134134        delete itr->second; 
     135 
     136    for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) 
     137        for (VendorItemList::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) 
     138            delete (*itr2); 
     139 
     140    for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) 
     141        itr->second.Clear(); 
    135142} 
    136143 
     
    255262void ObjectMgr::SendAuctionWonMail( AuctionEntry *auction ) 
    256263{ 
    257     Item *pItem = objmgr.GetAItem(auction->item_guidlow); 
     264    Item *pItem = GetAItem(auction->item_guidlow); 
    258265    if(!pItem) 
    259266        return; 
    260267 
    261268    uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); 
    262     Player *bidder = objmgr.GetPlayer(bidder_guid); 
     269    Player *bidder = GetPlayer(bidder_guid); 
    263270 
    264271    uint32 bidder_accId = 0; 
     
    328335            bidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, bidder_guid, 0, 0, auction->item_template); 
    329336        else 
    330             objmgr.RemoveAItem(pItem->GetGUIDLow());        // we have to remove the item, before we delete it !! 
     337            RemoveAItem(pItem->GetGUIDLow());               // we have to remove the item, before we delete it !! 
    331338 
    332339        // will delete item or place to receiver mail list 
     
    337344    { 
    338345        CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", pItem->GetGUIDLow()); 
    339         objmgr.RemoveAItem(pItem->GetGUIDLow());            // we have to remove the item, before we delete it !! 
     346        RemoveAItem(pItem->GetGUIDLow());                   // we have to remove the item, before we delete it !! 
    340347        delete pItem; 
    341348    } 
     
    345352{ 
    346353    uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); 
    347     Player *owner = objmgr.GetPlayer(owner_guid); 
     354    Player *owner = GetPlayer(owner_guid); 
    348355 
    349356    // owner exist (online or offline) 
     
    376383{ 
    377384    uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); 
    378     Player *owner = objmgr.GetPlayer(owner_guid); 
     385    Player *owner = GetPlayer(owner_guid); 
    379386 
    380387    uint32 owner_accId = 0; 
     
    415422void ObjectMgr::SendAuctionExpiredMail( AuctionEntry * auction ) 
    416423{                                                           //return an item in auction to its owner by mail 
    417     Item *pItem = objmgr.GetAItem(auction->item_guidlow); 
     424    Item *pItem = GetAItem(auction->item_guidlow); 
    418425    if(!pItem) 
    419426    { 
     
    423430 
    424431    uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); 
    425     Player *owner = objmgr.GetPlayer(owner_guid); 
     432    Player *owner = GetPlayer(owner_guid); 
    426433 
    427434    uint32 owner_accId = 0; 
     
    438445            owner->GetSession()->SendAuctionOwnerNotification( auction ); 
    439446        else 
    440             objmgr.RemoveAItem(pItem->GetGUIDLow());        // we have to remove the item, before we delete it !! 
     447            RemoveAItem(pItem->GetGUIDLow());               // we have to remove the item, before we delete it !! 
    441448 
    442449        MailItemsInfo mi; 
     
    451458    { 
    452459        CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'",pItem->GetGUIDLow()); 
    453         objmgr.RemoveAItem(pItem->GetGUIDLow());            // we have to remove the item, before we delete it !! 
     460        RemoveAItem(pItem->GetGUIDLow());                   // we have to remove the item, before we delete it !! 
    454461        delete pItem; 
    455462    } 
     
    17371744        uint32 item_template    = fields[1].GetUInt32(); 
    17381745 
    1739         ItemPrototype const *proto = objmgr.GetItemPrototype(item_template); 
     1746        ItemPrototype const *proto = GetItemPrototype(item_template); 
    17401747 
    17411748        if(!proto) 
     
    36883695            case SCRIPT_COMMAND_QUEST_EXPLORED: 
    36893696            { 
    3690                 Quest const* quest = objmgr.GetQuestTemplate(tmp.datalong); 
     3697                Quest const* quest = GetQuestTemplate(tmp.datalong); 
    36913698                if(!quest) 
    36923699                { 
     
    37683775void ObjectMgr::LoadQuestEndScripts() 
    37693776{ 
    3770     objmgr.LoadScripts(sQuestEndScripts,  "quest_end_scripts"); 
     3777    LoadScripts(sQuestEndScripts,  "quest_end_scripts"); 
    37713778 
    37723779    // check ids 
     
    37803787void ObjectMgr::LoadQuestStartScripts() 
    37813788{ 
    3782     objmgr.LoadScripts(sQuestStartScripts,"quest_start_scripts"); 
     3789    LoadScripts(sQuestStartScripts,"quest_start_scripts"); 
    37833790 
    37843791    // check ids 
     
    37923799void ObjectMgr::LoadSpellScripts() 
    37933800{ 
    3794     objmgr.LoadScripts(sSpellScripts, "spell_scripts"); 
     3801    LoadScripts(sSpellScripts, "spell_scripts"); 
    37953802 
    37963803    // check ids 
     
    38273834void ObjectMgr::LoadEventScripts() 
    38283835{ 
    3829     objmgr.LoadScripts(sEventScripts, "event_scripts"); 
     3836    LoadScripts(sEventScripts, "event_scripts"); 
    38303837 
    38313838    std::set<uint32> evt_scripts; 
     
    42314238        Player *pl = 0; 
    42324239        if (serverUp) 
    4233             pl = objmgr.GetPlayer((uint64)m->receiver); 
     4240            pl = GetPlayer((uint64)m->receiver); 
    42344241        if (pl && pl->m_mailsLoaded) 
    42354242        {                                                   //this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail 
     
    45044511        { 
    45054512            mount_entry = node->alliance_mount_type; 
    4506             CreatureInfo const *ci = objmgr.GetCreatureTemplate(mount_entry); 
     4513            CreatureInfo const *ci = GetCreatureTemplate(mount_entry); 
    45074514            if(ci) 
    45084515                mount_id = ci->DisplayID_A; 
     
    45114518        { 
    45124519            mount_entry = node->horde_mount_type; 
    4513             CreatureInfo const *ci = objmgr.GetCreatureTemplate(mount_entry); 
     4520            CreatureInfo const *ci = GetCreatureTemplate(mount_entry); 
    45144521            if(ci) 
    45154522                mount_id = ci->DisplayID_H; 
     
    45174524    } 
    45184525 
    4519     CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(mount_id); 
     4526    CreatureModelInfo const *minfo = GetCreatureModelInfo(mount_id); 
    45204527    if(!minfo) 
    45214528    { 
     
    48094816        if(at.requiredItem) 
    48104817        { 
    4811             ItemPrototype const *pProto = objmgr.GetItemPrototype(at.requiredItem); 
     4818            ItemPrototype const *pProto = GetItemPrototype(at.requiredItem); 
    48124819            if(!pProto) 
    48134820            { 
     
    48184825        if(at.requiredItem2) 
    48194826        { 
    4820             ItemPrototype const *pProto = objmgr.GetItemPrototype(at.requiredItem2); 
     4827            ItemPrototype const *pProto = GetItemPrototype(at.requiredItem2); 
    48214828            if(!pProto) 
    48224829            { 
     
    48284835        if(at.heroicKey) 
    48294836        { 
    4830             ItemPrototype const *pProto = objmgr.GetItemPrototype(at.heroicKey); 
     4837            ItemPrototype const *pProto = GetItemPrototype(at.heroicKey); 
    48314838            if(!pProto) 
    48324839            { 
     
    48384845        if(at.heroicKey2) 
    48394846        { 
    4840             ItemPrototype const *pProto = objmgr.GetItemPrototype(at.heroicKey2); 
     4847            ItemPrototype const *pProto = GetItemPrototype(at.heroicKey2); 
    48414848            if(!pProto) 
    48424849            { 
     
    54465453    if(list0.empty() || list1.empty()) 
    54475454    { 
    5448         CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(entry); 
     5455        CreatureInfo const *cinfo = GetCreatureTemplate(entry); 
    54495456        char* petname = GetPetName(cinfo->family, sWorld.GetDefaultDbcLocale()); 
    54505457        if(!petname) 
     
    55405547        repOnKill.repfaction2          = fields[2].GetUInt32(); 
    55415548        repOnKill.is_teamaward1        = fields[3].GetBool(); 
    5542         repOnKill.reputration_max_cap1 = fields[4].GetUInt32(); 
     5549        repOnKill.reputation_max_cap1 = fields[4].GetUInt32(); 
    55435550        repOnKill.repvalue1            = fields[5].GetInt32(); 
    55445551        repOnKill.is_teamaward2        = fields[6].GetBool(); 
    5545         repOnKill.reputration_max_cap2 = fields[7].GetUInt32(); 
     5552        repOnKill.reputation_max_cap2 = fields[7].GetUInt32(); 
    55465553        repOnKill.repvalue2            = fields[8].GetInt32(); 
    55475554        repOnKill.team_dependent       = fields[9].GetUInt8(); 
     
    60986105} 
    60996106 
    6100 bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, bool positive_entries) 
     6107bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value) 
    61016108{ 
    61026109    // cleanup affected map part for reloading case 
    61036110    for(MangosStringLocaleMap::iterator itr = mMangosStringLocaleMap.begin(); itr != mMangosStringLocaleMap.end();) 
    61046111    { 
    6105         if(itr->first > 0 && positive_entries || itr->first < 0 && !positive_entries) 
     6112        if(itr->first >= min_value && itr->first <= max_value) 
    61066113        { 
    61076114            MangosStringLocaleMap::iterator itr2 = itr; 
     
    61226129 
    61236130        sLog.outString(""); 
    6124         if(positive_entries)                                // error only in case internal strings 
     6131        if(min_value > 0)                                   // error only in case internal strings 
    61256132            sLog.outErrorDb(">> Loaded 0 mangos strings. DB table `%s` is empty. Cannot continue.",table); 
    61266133        else 
    6127             sLog.outString(">> Loaded 0 mangos strings. DB table `%s` is empty.",table); 
     6134            sLog.outString(">> Loaded 0 string templates. DB table `%s` is empty.",table); 
    61286135        return false; 
    61296136    } 
     6137 
     6138    uint32 count = 0; 
    61306139 
    61316140    barGoLink bar(result->GetRowCount()); 
     
    61436152            continue; 
    61446153        } 
    6145         else if(entry < 0) 
    6146         { 
    6147             if(positive_entries) 
    6148             { 
    6149                 sLog.outString("Table `%s` contain unexpected negative entry %i, ignored.",table,entry); 
    6150                 continue; 
    6151             } 
    6152         } 
    6153         else 
    6154         { 
    6155             if(!positive_entries) 
    6156             { 
    6157                 sLog.outString("Table `%s` contain unexpected positive entry %i, ignored.",table,entry); 
    6158                 continue; 
    6159             } 
     6154        else if(entry < min_value || entry > max_value) 
     6155        { 
     6156            int32 start = min_value > 0 ? min_value : max_value; 
     6157            int32 end   = min_value > 0 ? max_value : min_value; 
     6158            sLog.outString("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,start,end); 
     6159            continue; 
    61606160        } 
    61616161 
    61626162        MangosStringLocale& data = mMangosStringLocaleMap[entry]; 
    61636163 
    6164         if(data.Content.size() < 1) 
    6165             data.Content.resize(1); 
     6164        if(data.Content.size() > 0) 
     6165        { 
     6166            sLog.outString("Table `%s` contain data for already loaded entry  %i (from another table?), ignored.",table,entry); 
     6167            continue; 
     6168        } 
     6169 
     6170        data.Content.resize(1); 
     6171        ++count; 
    61666172 
    61676173        // 0 -> default, idx in to idx+1 
     
    61896195 
    61906196    sLog.outString(); 
    6191     sLog.outString( ">> Loaded %u MaNGOS strings from table %s", mMangosStringLocaleMap.size(),table); 
     6197    if(min_value > 0)                                       // internal mangos strings 
     6198        sLog.outString( ">> Loaded %u MaNGOS strings from table %s", count,table); 
     6199    else 
     6200        sLog.outString( ">> Loaded %u string templates from %s", count,table); 
     6201 
    61926202    return true; 
    61936203} 
     
    65006510} 
    65016511 
     6512void ObjectMgr::LoadGameTele() 
     6513{ 
     6514    m_GameTeleMap.clear();                                  // for relaod case 
     6515 
     6516    uint32 count = 0; 
     6517    QueryResult *result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, map, name FROM game_tele"); 
     6518 
     6519    if( !result ) 
     6520    { 
     6521        barGoLink bar( 1 ); 
     6522 
     6523        bar.step(); 
     6524 
     6525        sLog.outString(); 
     6526        sLog.outErrorDb(">> Loaded `game_tele`, table is empty!"); 
     6527        return; 
     6528    } 
     6529 
     6530    barGoLink bar( result->GetRowCount() ); 
     6531 
     6532    do 
     6533    { 
     6534        bar.step(); 
     6535 
     6536        Field *fields = result->Fetch(); 
     6537 
     6538        uint32 id         = fields[0].GetUInt32(); 
     6539 
     6540        GameTele gt; 
     6541 
     6542        gt.position_x     = fields[1].GetFloat(); 
     6543        gt.position_y     = fields[2].GetFloat(); 
     6544        gt.position_z     = fields[3].GetFloat(); 
     6545        gt.orientation    = fields[4].GetFloat(); 
     6546        gt.mapId          = fields[5].GetUInt32(); 
     6547        gt.name           = fields[6].GetCppString(); 
     6548 
     6549        if(!MapManager::IsValidMapCoord(gt.mapId,gt.position_x,gt.position_y,gt.position_z,gt.orientation)) 
     6550        { 
     6551            sLog.outErrorDb("Wrong position for id %u (name: %s) in `game_tele` table, ignoring.",id,gt.name.c_str()); 
     6552            continue; 
     6553        } 
     6554 
     6555        if(!Utf8toWStr(gt.name,gt.wnameLow)) 
     6556        { 
     6557            sLog.outErrorDb("Wrong UTF8 name for id %u in `game_tele` table, ignoring.",id); 
     6558            continue; 
     6559        } 
     6560 
     6561        wstrToLower( gt.wnameLow ); 
     6562 
     6563        m_GameTeleMap[id] = gt; 
     6564 
     6565        ++count; 
     6566    } 
     6567    while (result->NextRow()); 
     6568 
     6569    delete result; 
     6570 
     6571    sLog.outString(); 
     6572    sLog.outString( ">> Loaded %u game tele's", count ); 
     6573} 
     6574 
     6575GameTele const* ObjectMgr::GetGameTele(std::string name) const 
     6576{ 
     6577    // explicit name case 
     6578    std::wstring wname; 
     6579    if(!Utf8toWStr(name,wname)) 
     6580        return false; 
     6581 
     6582    // converting string that we try to find to lower case 
     6583    wstrToLower( wname ); 
     6584 
     6585    for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) 
     6586        if(itr->second.wnameLow == wname) 
     6587            return &itr->second; 
     6588 
     6589    return NULL; 
     6590} 
     6591 
     6592bool ObjectMgr::AddGameTele(GameTele& tele) 
     6593{ 
     6594    // find max id 
     6595    uint32 new_id = 0; 
     6596    for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) 
     6597        if(itr->first > new_id) 
     6598            new_id = itr->first; 
     6599     
     6600    // use next 
     6601    ++new_id; 
     6602 
     6603    if(!Utf8toWStr(tele.name,tele.wnameLow)) 
     6604        return false; 
     6605 
     6606    wstrToLower( tele.wnameLow ); 
     6607 
     6608    m_GameTeleMap[new_id] = tele; 
     6609 
     6610    return WorldDatabase.PExecuteLog("INSERT INTO game_tele (id,position_x,position_y,position_z,orientation,map,name) VALUES (%u,%f,%f,%f,%f,%d,'%s')", 
     6611        new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str()); 
     6612} 
     6613 
     6614bool ObjectMgr::DeleteGameTele(std::string name) 
     6615{ 
     6616    // explicit name case 
     6617    std::wstring wname; 
     6618    if(!Utf8toWStr(name,wname)) 
     6619        return false; 
     6620 
     6621    // converting string that we try to find to lower case 
     6622    wstrToLower( wname ); 
     6623 
     6624    for(GameTeleMap::iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) 
     6625    { 
     6626        if(itr->second.wnameLow == wname) 
     6627        { 
     6628            WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",itr->second.name.c_str()); 
     6629            m_GameTeleMap.erase(itr); 
     6630            return true; 
     6631        } 
     6632    } 
     6633 
     6634    return false; 
     6635} 
     6636 
     6637void ObjectMgr::LoadTrainerSpell() 
     6638{ 
     6639    // For reload case  
     6640    for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) 
     6641        itr->second.Clear(); 
     6642    m_mCacheTrainerSpellMap.clear(); 
     6643 
     6644    QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); 
     6645 
     6646    if( !result ) 
     6647    { 
     6648        barGoLink bar( 1 ); 
     6649 
     6650        bar.step(); 
     6651 
     6652        sLog.outString(); 
     6653        sLog.outErrorDb(">> Loaded `npc_trainer`, table is empty!"); 
     6654        return; 
     6655    } 
     6656 
     6657    barGoLink bar( result->GetRowCount() ); 
     6658 
     6659    uint32 count = 0,entry,spell; 
     6660    do 
     6661    { 
     6662        bar.step(); 
     6663 
     6664        Field* fields = result->Fetch(); 
     6665 
     6666        entry  = fields[0].GetUInt32(); 
     6667        spell  = fields[1].GetUInt32(); 
     6668 
     6669        if(!GetCreatureTemplate(entry)) 
     6670        { 
     6671            sLog.outErrorDb("Table `npc_trainer` have entry for not existed creature template (Entry: %u), ignore", entry); 
     6672            continue; 
     6673        } 
     6674 
     6675        SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell); 
     6676        if(!spellinfo) 
     6677        { 
     6678            sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u ) has non existing spell %u, ignore", entry,spell); 
     6679            continue; 
     6680        } 
     6681 
     6682        if(!SpellMgr::IsSpellValid(spellinfo)) 
     6683        { 
     6684            sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has broken learning spell %u, ignore", entry, spell); 
     6685            continue; 
     6686        } 
     6687 
     6688        TrainerSpell* pTrainerSpell = new TrainerSpell(); 
     6689        pTrainerSpell->spell         = spell; 
     6690        pTrainerSpell->spellcost     = fields[2].GetUInt32(); 
     6691        pTrainerSpell->reqskill      = fields[3].GetUInt32(); 
     6692        pTrainerSpell->reqskillvalue = fields[4].GetUInt32(); 
     6693        pTrainerSpell->reqlevel      = fields[5].GetUInt32(); 
     6694 
     6695        if(!pTrainerSpell->reqlevel) 
     6696            pTrainerSpell->reqlevel = spellinfo->spellLevel; 
     6697 
     6698 
     6699        TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; 
     6700 
     6701        if(SpellMgr::IsProfessionSpell(spell)) 
     6702            data.trainerType = 2; 
     6703 
     6704        data.spellList.push_back(pTrainerSpell); 
     6705        ++count; 
     6706 
     6707    } while (result->NextRow()); 
     6708    delete result; 
     6709 
     6710    sLog.outString(); 
     6711    sLog.outString( ">> Loaded Trainers %d", count ); 
     6712} 
     6713 
     6714void ObjectMgr::LoadVendors() 
     6715{ 
     6716    // For reload case  
     6717    for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) 
     6718    { 
     6719        for (VendorItemList::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) 
     6720            delete (*itr2); 
     6721    } 
     6722    m_mCacheVendorItemMap.clear(); 
     6723 
     6724    QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor"); 
     6725    if( !result ) 
     6726    { 
     6727        barGoLink bar( 1 ); 
     6728 
     6729        bar.step(); 
     6730 
     6731        sLog.outString(); 
     6732        sLog.outErrorDb(">> Loaded `npc_vendor`, table is empty!"); 
     6733        return; 
     6734    } 
     6735 
     6736    barGoLink bar( result->GetRowCount() ); 
     6737 
     6738    uint32 count = 0; 
     6739    uint32 entry, item_id, ExtendedCost; 
     6740    do 
     6741    { 
     6742        bar.step(); 
     6743        Field* fields = result->Fetch(); 
     6744 
     6745        entry = fields[0].GetUInt32(); 
     6746        if(!GetCreatureTemplate(entry)) 
     6747        { 
     6748            sLog.outErrorDb("Table `npc_vendor` have data for not existed creature template (Entry: %u), ignore", entry); 
     6749            continue; 
     6750        } 
     6751 
     6752        item_id  = fields[1].GetUInt32(); 
     6753        if(!GetItemPrototype(item_id)) 
     6754        { 
     6755            sLog.outErrorDb("Table `npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore",entry,item_id); 
     6756            continue; 
     6757        } 
     6758 
     6759        ExtendedCost = fields[4].GetUInt32(); 
     6760        if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) 
     6761        { 
     6762            sLog.outErrorDb("Table `npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore",item_id,ExtendedCost,entry); 
     6763            continue; 
     6764        } 
     6765 
     6766        VendorItemList& vList = m_mCacheVendorItemMap[entry]; 
     6767 
     6768        if(vList.size() >= MAX_VENDOR_ITEMS) 
     6769        { 
     6770            sLog.outErrorDb( "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", vList.size(), MAX_VENDOR_ITEMS, entry); 
     6771            continue; 
     6772        } 
     6773 
     6774        VendorItem* pVendorItem = new VendorItem(); 
     6775        pVendorItem->item         = item_id; 
     6776        pVendorItem->maxcount     = fields[2].GetUInt32(); 
     6777        pVendorItem->incrtime     = fields[3].GetUInt32(); 
     6778        pVendorItem->ExtendedCost = ExtendedCost; 
     6779 
     6780        vList.push_back(pVendorItem); 
     6781        ++count; 
     6782 
     6783    } while (result->NextRow()); 
     6784    delete result; 
     6785 
     6786    sLog.outString(); 
     6787    sLog.outString( ">> Loaded %d Vendors ", count ); 
     6788} 
     6789 
     6790void ObjectMgr::LoadNpcTextId() 
     6791{ 
     6792 
     6793    m_mCacheNpcTextIdMap.clear(); 
     6794 
     6795    QueryResult* result = WorldDatabase.PQuery("SELECT npc_guid, textid FROM npc_gossip"); 
     6796    if( !result ) 
     6797    { 
     6798        barGoLink bar( 1 ); 
     6799 
     6800        bar.step(); 
     6801 
     6802        sLog.outString(); 
     6803        sLog.outErrorDb(">> Loaded `npc_gossip`, table is empty!"); 
     6804        return; 
     6805    } 
     6806 
     6807    barGoLink bar( result->GetRowCount() ); 
     6808 
     6809    uint32 count = 0; 
     6810    uint32 guid,textid; 
     6811    do 
     6812    { 
     6813        bar.step(); 
     6814 
     6815        Field* fields = result->Fetch(); 
     6816 
     6817        guid   = fields[0].GetUInt32(); 
     6818        textid = fields[1].GetUInt32(); 
     6819 
     6820        if (!GetCreatureData(guid)) 
     6821        { 
     6822            sLog.outErrorDb("Table `npc_gossip` have not existed creature (GUID: %u) entry, ignore. ",guid); 
     6823            continue; 
     6824        } 
     6825        if (!GetGossipText(textid)) 
     6826        { 
     6827            sLog.outErrorDb("Table `npc_gossip` for creature (GUID: %u) have wrong Textid (%u), ignore. ", guid, textid); 
     6828            continue; 
     6829        } 
     6830 
     6831        m_mCacheNpcTextIdMap[guid] = textid ; 
     6832        ++count; 
     6833 
     6834    } while (result->NextRow()); 
     6835    delete result; 
     6836 
     6837    sLog.outString(); 
     6838    sLog.outString( ">> Loaded %d NpcTextId ", count ); 
     6839} 
     6840 
     6841// Functions for scripting access 
    65026842const char* GetAreaTriggerScriptNameById(uint32 id) 
    65036843{ 
     
    65056845} 
    65066846 
    6507  
    6508 bool LoadMangosStrings(DatabaseType& db, char const* table) 
    6509 { 
     6847bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value) 
     6848{ 
     6849    if(start_value >= 0 || start_value <= end_value)        // start/end reversed for negative values 
     6850    { 
     6851        sLog.outError("Table '%s' attempt loaded with invalid range (%d - %d), use (%d - %d) instead.",table,start_value,end_value,-1,std::numeric_limits<int32>::min()); 
     6852        start_value = -1; 
     6853        end_value = std::numeric_limits<int32>::min(); 
     6854    } 
     6855 
    65106856    // for scripting localized strings allowed use _only_ negative entries 
    6511     return objmgr.LoadMangosStrings(db,table,false); 
    6512 } 
     6857    return objmgr.LoadMangosStrings(db,table,end_value,start_value); 
     6858} 
  • trunk/src/game/ObjectMgr.h

    r2 r6  
    4343#include <string> 
    4444#include <map> 
     45#include <limits> 
    4546 
    4647extern SQLStorage sCreatureStorage; 
     
    6061class TransportPath; 
    6162class Item; 
     63 
     64struct GameTele 
     65{ 
     66    float  position_x; 
     67    float  position_y; 
     68    float  position_z; 
     69    float  orientation; 
     70    uint32 mapId; 
     71    std::string name; 
     72    std::wstring wnameLow; 
     73}; 
     74 
     75typedef HM_NAMESPACE::hash_map<uint32, GameTele > GameTeleMap; 
    6276 
    6377struct ScriptInfo 
     
    144158    uint32 repfaction2; 
    145159    bool is_teamaward1; 
    146     uint32 reputration_max_cap1; 
     160    uint32 reputation_max_cap1; 
    147161    int32 repvalue1; 
    148162    bool is_teamaward2; 
    149     uint32 reputration_max_cap2; 
     163    uint32 reputation_max_cap2; 
    150164    int32 repvalue2; 
    151165    bool team_dependent; 
     
    212226}; 
    213227 
     228// NPC gossip text id 
     229typedef HM_NAMESPACE::hash_map<uint32, uint32> CacheNpcTextIdMap; 
     230 
     231// Vendors 
     232struct VendorItem 
     233{ 
     234    uint32 item; 
     235    uint32 maxcount; 
     236    uint32 incrtime; 
     237    uint32 ExtendedCost; 
     238}; 
     239typedef std::vector<VendorItem*> VendorItemList; 
     240 
     241typedef HM_NAMESPACE::hash_map<uint32, VendorItemList> CacheVendorItemMap; 
     242 
     243typedef HM_NAMESPACE::hash_map<uint32, TrainerSpellData> CacheTrainerSpellMap; 
     244 
    214245enum SkillRangeType 
    215246{ 
     
    467498        void LoadSpellScripts(); 
    468499 
    469         bool LoadMangosStrings(DatabaseType& db, char const* table, bool positive_entries); 
    470         bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",true); } 
     500        bool LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value); 
     501        bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",1,std::numeric_limits<int32>::max()); } 
    471502        void LoadPetCreateSpells(); 
    472503        void LoadCreatureLocales(); 
     
    513544 
    514545        void LoadWeatherZoneChances(); 
     546        void LoadGameTele(); 
     547 
     548        void LoadNpcTextId(); 
     549        void LoadVendors(); 
     550        void LoadTrainerSpell(); 
    515551 
    516552        std::string GeneratePetName(uint32 entry); 
     
    664700 
    665701            return mConditions[condition_id].Meets(player); 
     702        } 
     703 
     704        GameTele const* GetGameTele(uint32 id) const 
     705        { 
     706            GameTeleMap::const_iterator itr = m_GameTeleMap.find(id); 
     707            if(itr==m_GameTeleMap.end()) return NULL; 
     708            return &itr->second; 
     709        } 
     710        GameTele const* GetGameTele(std::string name) const; 
     711        GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; } 
     712        bool AddGameTele(GameTele& data); 
     713        bool DeleteGameTele(std::string name); 
     714 
     715        uint32 GetNpcGossip(uint32 entry) const 
     716        { 
     717            CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry); 
     718            if(iter == m_mCacheNpcTextIdMap.end()) 
     719                return 0; 
     720             
     721            return iter->second; 
     722        } 
     723 
     724        TrainerSpellData const* GetNpcTrainerSpells(uint32 entry) const 
     725        { 
     726            CacheTrainerSpellMap::const_iterator  iter = m_mCacheTrainerSpellMap.find(entry); 
     727            if(iter == m_mCacheTrainerSpellMap.end()) 
     728                return NULL; 
     729 
     730            return &iter->second; 
     731        } 
     732 
     733        VendorItemList const* GetNpcVendorItemList(uint32 entry) const 
     734        { 
     735            CacheVendorItemMap::const_iterator  iter = m_mCacheVendorItemMap.find(entry); 
     736            if(iter == m_mCacheVendorItemMap.end()) 
     737                return NULL; 
     738 
     739            return &iter->second; 
    666740        } 
    667741    protected: 
     
    721795 
    722796        GraveYardMap        mGraveYardMap; 
     797 
     798        GameTeleMap         m_GameTeleMap; 
    723799 
    724800        typedef             std::vector<LocaleConstant> LocalForIndex; 
     
    771847        ConditionStore mConditions; 
    772848 
     849        CacheNpcTextIdMap m_mCacheNpcTextIdMap; 
     850        CacheVendorItemMap m_mCacheVendorItemMap; 
     851        CacheTrainerSpellMap m_mCacheTrainerSpellMap; 
    773852}; 
    774853 
    775854#define objmgr MaNGOS::Singleton<ObjectMgr>::Instance() 
     855 
     856// scripting access functions 
     857bool MANGOS_DLL_SPEC LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits<int32>::min()); 
     858MANGOS_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id); 
     859 
    776860#endif 
    777  
    778 // scripting access functions 
    779 bool MANGOS_DLL_SPEC LoadMangosStrings(DatabaseType& db, char const* table); 
    780 MANGOS_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id); 
  • trunk/src/game/Player.cpp

    r2 r6  
    357357    m_ArmorProficiency = 0; 
    358358    m_canParry = false; 
     359    m_canBlock = false; 
    359360    m_canDualWield = false; 
    360361    m_ammoDPS = 0.0f; 
     
    617618            ++action_itr[i]; 
    618619    } 
    619  
    620     UpdateBlockPercentage(); 
    621620 
    622621    for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++) 
     
    22492248        SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1+i, 0.0f); 
    22502249 
    2251     // Base parry percents 
    2252     SetFloatValue(PLAYER_PARRY_PERCENTAGE, 5.0f); 
    2253  
    2254     //Base block percentage 
    2255     SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 5.0f); 
    2256  
     2250    SetFloatValue(PLAYER_PARRY_PERCENTAGE, 0.0f); 
     2251    SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 0.0f); 
    22572252    SetUInt32Value(PLAYER_SHIELD_BLOCK, 0); 
    22582253 
     
    32873282        updateVisualBits.SetBit(i); 
    32883283 
    3289     for(uint16 i = 0; i < INVENTORY_SLOT_BAG_END; i++) 
    3290     { 
    3291         updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + i*2)); 
    3292         updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (i*2) + 1)); 
    3293     } 
    32943284    //Players visible items are not inventory stuff 
    32953285    //431) = 884 (0x374) = main weapon 
     
    34063396 
    34073397    // known spell 
    3408     if(HasSpell(trainer_spell->spell->Id)) 
     3398    if(HasSpell(trainer_spell->spell)) 
    34093399        return TRAINER_SPELL_GRAY; 
    34103400 
    34113401    // check race/class requirement 
    3412     if(!IsSpellFitByClassAndRace(trainer_spell->spell->Id)) 
     3402    if(!IsSpellFitByClassAndRace(trainer_spell->spell)) 
    34133403        return TRAINER_SPELL_RED; 
    34143404 
    34153405    // check level requirement 
    3416     if(getLevel() < ( trainer_spell->reqlevel ? trainer_spell->reqlevel : trainer_spell->spell->spellLevel)) 
     3406    if(getLevel() < trainer_spell->reqlevel) 
    34173407        return TRAINER_SPELL_RED; 
    34183408 
    3419     if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell->Id)) 
     3409    if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell)) 
    34203410    { 
    34213411        // check prev.rank requirement 
     
    34323422        return TRAINER_SPELL_RED; 
    34333423 
     3424    // exist, already checked at loading 
     3425    SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->spell); 
     3426 
    34343427    // secondary prof. or not prof. spell 
    3435     uint32 skill = trainer_spell->spell->EffectMiscValue[1]; 
    3436  
    3437     if(trainer_spell->spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill)) 
     3428    uint32 skill = spell->EffectMiscValue[1]; 
     3429 
     3430    if(spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill)) 
    34383431        return TRAINER_SPELL_GREEN; 
    34393432 
    34403433    // check primary prof. limit 
    3441     if(spellmgr.IsPrimaryProfessionFirstRankSpell(trainer_spell->spell->Id) && GetFreePrimaryProffesionPoints() == 0) 
     3434    if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell->Id) && GetFreePrimaryProffesionPoints() == 0) 
    34423435        return TRAINER_SPELL_RED; 
    34433436 
     
    48774870 
    48784871        if(pskill == SKILL_DEFENSE) 
    4879         { 
    4880             UpdateBlockPercentage(); 
    4881         } 
     4872            UpdateDefenseBonusesMod(); 
    48824873    } 
    48834874} 
     
    57915782        FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(Rep->repfaction1); 
    57925783        uint32 current_reputation_rank1 = GetReputationRank(factionEntry1); 
    5793         if(factionEntry1 && current_reputation_rank1 <= Rep->reputration_max_cap1) 
     5784        if(factionEntry1 && current_reputation_rank1 <= Rep->reputation_max_cap1) 
    57945785            ModifyFactionReputation(factionEntry1, donerep1); 
    57955786 
     
    58095800        FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(Rep->repfaction2); 
    58105801        uint32 current_reputation_rank2 = GetReputationRank(factionEntry2); 
    5811         if(factionEntry2 && current_reputation_rank2 <= Rep->reputration_max_cap2) 
     5802        if(factionEntry2 && current_reputation_rank2 <= Rep->reputation_max_cap2) 
    58125803            ModifyFactionReputation(factionEntry2, donerep2); 
    58135804 
     
    1155311544    } 
    1155411545 
    11555     QuestMenu *qm = PlayerTalkClass->GetQuestMenu(); 
    11556     qm->ClearMenu(); 
     11546    QuestMenu &qm = PlayerTalkClass->GetQuestMenu(); 
     11547    qm.ClearMenu(); 
    1155711548 
    1155811549    for(QuestRelations::const_iterator i = pObjectQIR->lower_bound(pObject->GetEntry()); i != pObjectQIR->upper_bound(pObject->GetEntry()); ++i) 
     
    1156111552        QuestStatus status = GetQuestStatus( quest_id ); 
    1156211553        if ( status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus( quest_id ) ) 
    11563             qm->AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); 
     11554            qm.AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); 
    1156411555        else if ( status == QUEST_STATUS_INCOMPLETE ) 
    11565             qm->AddMenuItem(quest_id, DIALOG_STATUS_INCOMPLETE); 
     11556            qm.AddMenuItem(quest_id, DIALOG_STATUS_INCOMPLETE); 
    1156611557        else if (status == QUEST_STATUS_AVAILABLE ) 
    11567             qm->AddMenuItem(quest_id, DIALOG_STATUS_CHAT); 
     11558            qm.AddMenuItem(quest_id, DIALOG_STATUS_CHAT); 
    1156811559    } 
    1156911560 
     
    1157711568 
    1157811569        if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false)) 
    11579             qm->AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); 
     11570            qm.AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP); 
    1158011571        else if ( status == QUEST_STATUS_NONE && CanTakeQuest( pQuest, false ) ) 
    11581             qm->AddMenuItem(quest_id, DIALOG_STATUS_AVAILABLE); 
     11572            qm.AddMenuItem(quest_id, DIALOG_STATUS_AVAILABLE); 
    1158211573    } 
    1158311574} 
     
    1158511576void Player::SendPreparedQuest( uint64 guid ) 
    1158611577{ 
    11587     QuestMenu* pQuestMenu = PlayerTalkClass->GetQuestMenu(); 
    11588     if( !pQuestMenu || pQuestMenu->MenuItemCount() < 1 ) 
     11578    QuestMenu& questMenu = PlayerTalkClass->GetQuestMenu(); 
     11579    if( questMenu.Empty() ) 
    1158911580        return; 
    1159011581 
    11591     uint32 status = pQuestMenu->GetItem(0).m_qIcon; 
    11592     if ( pQuestMenu->MenuItemCount() == 1 ) 
     11582    QuestMenuItem const& qmi0 = questMenu.GetItem( 0 ); 
     11583 
     11584    uint32 status = qmi0.m_qIcon; 
     11585 
     11586    // single element case 
     11587    if ( questMenu.MenuItemCount() == 1 ) 
    1159311588    { 
    1159411589        // Auto open -- maybe also should verify there is no greeting 
    11595         uint32 quest_id = pQuestMenu->GetItem(0).m_qId; 
     11590        uint32 quest_id = qmi0.m_qId; 
    1159611591        Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); 
    1159711592        if ( pQuest ) 
     
    1160811603        } 
    1160911604    } 
     11605    // multiply entries 
    1161011606    else 
    1161111607    { 
     
    1377213768                break; 
    1377313769        } 
    13774     } 
    13775  
    13776     //Unmount Player from previous mount, so speed bug with mount is no more... 
    13777     if(IsMounted()) 
    13778     { 
    13779         Unmount(); 
    13780         RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); 
    1378113770    } 
    1378213771 
     
    1562715616void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const 
    1562815617{ 
    15629     bool pre = (msgtype==CHAT_MSG_EMOTE); 
    15630  
    1563115618    *data << (uint8)msgtype; 
    1563215619    *data << (uint32)language; 
     
    1563415621    *data << (uint32)language;                               //language 2.1.0 ? 
    1563515622    *data << (uint64)GetGUID(); 
    15636     *data << (uint32)(text.length()+1+(pre?3:0)); 
    15637     if(pre) 
    15638         data->append("%s ",3); 
     15623    *data << (uint32)(text.length()+1); 
    1563915624    *data << text; 
    1564015625    *data << (uint8)chatTag(); 
     
    1715217137    data << (float)0.01666667f;                             // game speed 
    1715317138    GetSession()->SendPacket( &data ); 
     17139 
     17140    // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment 
     17141    if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight()) 
     17142        SetUnitMovementFlags(GetUnitMovementFlags() | MOVEMENTFLAG_FLYING2); 
    1715417143} 
    1715517144 
     
    1716317152    static const AuraType auratypes[] = 
    1716417153    { 
    17165         SPELL_AURA_MOD_FEAR,     SPELL_AURA_TRANSFORM, SPELL_AURA_WATER_WALK, 
    17166         SPELL_AURA_FEATHER_FALL, SPELL_AURA_HOVER,     SPELL_AURA_SAFE_FALL, 
    17167         SPELL_AURA_FLY,          SPELL_AURA_NONE 
     17154        SPELL_AURA_MOD_FEAR,     SPELL_AURA_TRANSFORM,                 SPELL_AURA_WATER_WALK, 
     17155        SPELL_AURA_FEATHER_FALL, SPELL_AURA_HOVER,                     SPELL_AURA_SAFE_FALL, 
     17156        SPELL_AURA_FLY,          SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED, SPELL_AURA_NONE 
    1716817157    }; 
    1716917158    for(AuraType const* itr = &auratypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr) 
     
    1811718106} 
    1811818107 
    18119 bool ItemPosCount::isContainedIn(ItemPosCountVec &vec) 
     18108void Player::SetCanParry( bool value ) 
     18109{ 
     18110    if(m_canParry==value) 
     18111        return;  
     18112 
     18113    m_canParry = value; 
     18114    UpdateParryPercentage(); 
     18115} 
     18116 
     18117void Player::SetCanBlock( bool value ) 
     18118{ 
     18119    if(m_canBlock==value) 
     18120        return;  
     18121 
     18122    m_canBlock = value; 
     18123    UpdateBlockPercentage(); 
     18124} 
     18125 
     18126bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const 
    1812018127{ 
    1812118128    for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr) 
    18122     { 
    18123         if(itr->pos == this->pos/* && itr->count == this.count*/) 
    18124         { 
     18129        if(itr->pos == this->pos) 
    1812518130            return true; 
    18126         } 
    18127     } 
     18131 
    1812818132    return false; 
    1812918133} 
    18130  
  • trunk/src/game/Player.h

    r2 r6  
    671671{ 
    672672    ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {} 
    673     bool isContainedIn(std::vector<ItemPosCount>&); 
     673    bool isContainedIn(std::vector<ItemPosCount> const& vec) const; 
    674674    uint16 pos; 
    675675    uint8 count; 
     
    17421742        uint32 GetShieldBlockValue() const;                 // overwrite Unit version (virtual) 
    17431743        bool CanParry() const { return m_canParry; } 
    1744         void SetCanParry(bool value) { m_canParry = value; } 
     1744        void SetCanParry(bool value); 
     1745        bool CanBlock() const { return m_canBlock; } 
     1746        void SetCanBlock(bool value); 
    17451747        bool CanDualWield() const { return m_canDualWield; } 
    17461748        void SetCanDualWield(bool value) { m_canDualWield = value; } 
     
    22022204        uint32 m_ArmorProficiency; 
    22032205        bool m_canParry; 
     2206        bool m_canBlock; 
    22042207        bool m_canDualWield; 
    22052208        uint8 m_swingErrorMsg; 
  • trunk/src/game/SharedDefines.h

    r2 r6  
    19951995    SUMMON_TYPE_POSESSED2   = 428 
    19961996}; 
     1997 
     1998enum ResponseCodes 
     1999{ 
     2000    RESPONSE_SUCCESS                                       = 0x00, 
     2001    RESPONSE_FAILURE                                       = 0x01, 
     2002    RESPONSE_CANCELLED                                     = 0x02, 
     2003    RESPONSE_DISCONNECTED                                  = 0x03, 
     2004    RESPONSE_FAILED_TO_CONNECT                             = 0x04, 
     2005    RESPONSE_CONNECTED                                     = 0x05, 
     2006    RESPONSE_VERSION_MISMATCH                              = 0x06, 
     2007 
     2008    CSTATUS_CONNECTING                                     = 0x07, 
     2009    CSTATUS_NEGOTIATING_SECURITY                           = 0x08, 
     2010    CSTATUS_NEGOTIATION_COMPLETE                           = 0x09, 
     2011    CSTATUS_NEGOTIATION_FAILED                             = 0x0A, 
     2012    CSTATUS_AUTHENTICATING                                 = 0x0B, 
     2013 
     2014    AUTH_OK                                                = 0x0C, 
     2015    AUTH_FAILED                                            = 0x0D, 
     2016    AUTH_REJECT                                            = 0x0E, 
     2017    AUTH_BAD_SERVER_PROOF                                  = 0x0F, 
     2018    AUTH_UNAVAILABLE                                       = 0x10, 
     2019    AUTH_SYSTEM_ERROR                                      = 0x11, 
     2020    AUTH_BILLING_ERROR                                     = 0x12, 
     2021    AUTH_BILLING_EXPIRED                                   = 0x13, 
     2022    AUTH_VERSION_MISMATCH                                  = 0x14, 
     2023    AUTH_UNKNOWN_ACCOUNT                                   = 0x15, 
     2024    AUTH_INCORRECT_PASSWORD                                = 0x16, 
     2025    AUTH_SESSION_EXPIRED                                   = 0x17, 
     2026    AUTH_SERVER_SHUTTING_DOWN                              = 0x18, 
     2027    AUTH_ALREADY_LOGGING_IN                                = 0x19, 
     2028    AUTH_LOGIN_SERVER_NOT_FOUND                            = 0x1A, 
     2029    AUTH_WAIT_QUEUE                                        = 0x1B, 
     2030    AUTH_BANNED                                            = 0x1C, 
     2031    AUTH_ALREADY_ONLINE                                    = 0x1D, 
     2032    AUTH_NO_TIME                                           = 0x1E, 
     2033    AUTH_DB_BUSY                                           = 0x1F, 
     2034    AUTH_SUSPENDED                                         = 0x20, 
     2035    AUTH_PARENTAL_CONTROL                                  = 0x21, 
     2036    AUTH_LOCKED_ENFORCED                                   = 0x22, 
     2037 
     2038    REALM_LIST_IN_PROGRESS                                 = 0x23, 
     2039    REALM_LIST_SUCCESS                                     = 0x24, 
     2040    REALM_LIST_FAILED                                      = 0x25, 
     2041    REALM_LIST_INVALID                                     = 0x26, 
     2042    REALM_LIST_REALM_NOT_FOUND                             = 0x27, 
     2043 
     2044    ACCOUNT_CREATE_IN_PROGRESS                             = 0x28, 
     2045    ACCOUNT_CREATE_SUCCESS                                 = 0x29, 
     2046    ACCOUNT_CREATE_FAILED                                  = 0x2A, 
     2047 
     2048    CHAR_LIST_RETRIEVING                                   = 0x2B, 
     2049    CHAR_LIST_RETRIEVED                                    = 0x2C, 
     2050    CHAR_LIST_FAILED                                       = 0x2D, 
     2051 
     2052    CHAR_CREATE_IN_PROGRESS                                = 0x2E, 
     2053    CHAR_CREATE_SUCCESS                                    = 0x2F, 
     2054    CHAR_CREATE_ERROR                                      = 0x30, 
     2055    CHAR_CREATE_FAILED                                     = 0x31, 
     2056    CHAR_CREATE_NAME_IN_USE                                = 0x32, 
     2057    CHAR_CREATE_DISABLED                                   = 0x33, 
     2058    CHAR_CREATE_PVP_TEAMS_VIOLATION                        = 0x34, 
     2059    CHAR_CREATE_SERVER_LIMIT                               = 0x35, 
     2060    CHAR_CREATE_ACCOUNT_LIMIT                              = 0x36, 
     2061    CHAR_CREATE_SERVER_QUEUE                               = 0x37, 
     2062    CHAR_CREATE_ONLY_EXISTING                              = 0x38, 
     2063    CHAR_CREATE_EXPANSION                                  = 0x39, 
     2064 
     2065    CHAR_DELETE_IN_PROGRESS                                = 0x3A, 
     2066    CHAR_DELETE_SUCCESS                                    = 0x3B, 
     2067    CHAR_DELETE_FAILED                                     = 0x3C, 
     2068    CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER                 = 0x3D, 
     2069    CHAR_DELETE_FAILED_GUILD_LEADER                        = 0x3E, 
     2070    CHAR_DELETE_FAILED_ARENA_CAPTAIN                       = 0x3F, 
     2071 
     2072    CHAR_LOGIN_IN_PROGRESS                                 = 0x40, 
     2073    CHAR_LOGIN_SUCCESS                                     = 0x41, 
     2074    CHAR_LOGIN_NO_WORLD                                    = 0x42, 
     2075    CHAR_LOGIN_DUPLICATE_CHARACTER                         = 0x43, 
     2076    CHAR_LOGIN_NO_INSTANCES                                = 0x44, 
     2077    CHAR_LOGIN_FAILED                                      = 0x45, 
     2078    CHAR_LOGIN_DISABLED                                    = 0x46, 
     2079    CHAR_LOGIN_NO_CHARACTER                                = 0x47, 
     2080    CHAR_LOGIN_LOCKED_FOR_TRANSFER                         = 0x48, 
     2081    CHAR_LOGIN_LOCKED_BY_BILLING                           = 0x49, 
     2082 
     2083    CHAR_NAME_SUCCESS                                      = 0x4A, 
     2084    CHAR_NAME_FAILURE                                      = 0x4B, 
     2085    CHAR_NAME_NO_NAME                                      = 0x4C, 
     2086    CHAR_NAME_TOO_SHORT                                    = 0x4D, 
     2087    CHAR_NAME_TOO_LONG                                     = 0x4E, 
     2088    CHAR_NAME_INVALID_CHARACTER                            = 0x4F, 
     2089    CHAR_NAME_MIXED_LANGUAGES                              = 0x50, 
     2090    CHAR_NAME_PROFANE                                      = 0x51, 
     2091    CHAR_NAME_RESERVED                                     = 0x52, 
     2092    CHAR_NAME_INVALID_APOSTROPHE                           = 0x53, 
     2093    CHAR_NAME_MULTIPLE_APOSTROPHES                         = 0x54, 
     2094    CHAR_NAME_THREE_CONSECUTIVE                            = 0x55, 
     2095    CHAR_NAME_INVALID_SPACE                                = 0x56, 
     2096    CHAR_NAME_CONSECUTIVE_SPACES                           = 0x57, 
     2097    CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS        = 0x58, 
     2098    CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59, 
     2099    CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME            = 0x5A, 
     2100}; 
    19972101#endif 
  • trunk/src/game/Spell.cpp

    r2 r6  
    524524                case SPELL_EFFECT_RESURRECT: 
    525525                case SPELL_EFFECT_PARRY: 
     526                case SPELL_EFFECT_BLOCK: 
    526527                case SPELL_EFFECT_CREATE_ITEM: 
    527528                case SPELL_EFFECT_TRIGGER_SPELL: 
     
    34773478            case SPELL_EFFECT_DUMMY: 
    34783479            { 
    3479                 // Execute 
    3480                 if(m_spellInfo->SpellIconID == 1648) 
     3480                if(m_spellInfo->SpellIconID == 1648)        // Execute 
    34813481                { 
    34823482                    if(!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2) 
    34833483                        return SPELL_FAILED_BAD_TARGETS; 
    34843484                } 
    3485                 else if (m_spellInfo->Id == 51582) 
     3485                else if (m_spellInfo->Id == 51582)          // Rocket Boots Engaged 
    34863486                { 
    34873487                    if(m_caster->IsInWater()) 
    34883488                        return SPELL_FAILED_ONLY_ABOVEWATER; 
     3489                } 
     3490                else if(m_spellInfo->SpellIconID==156)      // Holy Shock 
     3491                { 
     3492                    // spell different for friends and enemies 
     3493                    // hart version required facing 
     3494                    if(m_targets.getUnitTarget() && !m_caster->IsFriendlyTo(m_targets.getUnitTarget()) && !m_caster->HasInArc( M_PI, target )) 
     3495                        return SPELL_FAILED_UNIT_NOT_INFRONT; 
    34893496                } 
    34903497                break; 
     
    42324239        if(dist < min_range) 
    42334240            return SPELL_FAILED_TOO_CLOSE; 
    4234         if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER && 
    4235             !IsPositiveSpell(m_spellInfo->Id) && !m_caster->HasInArc( M_PI, target ) ) 
    4236         { 
    4237             // Spell-Family Related Checks 
    4238             switch (m_spellInfo->SpellFamilyName) 
    4239             { 
    4240                 case SPELLFAMILY_PRIEST: 
    4241                 { 
    4242                     // Shadow Word: Death, castable without facing 
    4243                     if (m_spellInfo->SpellFamilyFlags & 0x200000000LL) 
    4244                         return 0;                           // this is not TARGET_FLAG_DEST_LOCATION so we can return safely 
    4245                     break; 
    4246                 } 
    4247                 case SPELLFAMILY_PALADIN: 
    4248                 { 
    4249                     // Holy Shock, require facing 
    4250                     if (m_spellInfo->SpellFamilyFlags & 0x200000LL) 
    4251                         return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4252                     break; 
    4253                 } 
    4254                 case SPELLFAMILY_WARRIOR: 
    4255                 { 
    4256                     // Charge, require facing 
    4257                     if (m_spellInfo->SpellFamilyFlags & 1) 
    4258                         return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4259                     break; 
    4260                 } 
    4261             } 
    4262  
    4263             // Ranged Weapon 
    4264             if (IsRangedSpell()) 
    4265                 return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4266  
    4267             // Melee Combat 
    4268             if (m_spellInfo->rangeIndex == 2) 
    4269                 return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4270  
    4271             // Missile Effect 
    4272             if (m_spellInfo->speed > 0) 
    4273                 return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4274  
    4275             // Channeled Spells need facing 
    4276             if (IsChanneledSpell(m_spellInfo)) 
    4277                 return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4278  
    4279             // Direct Damage and charge effects 
    4280             for (uint8 i=0;i<3;++i) 
    4281             { 
    4282                 if (m_spellInfo->Effect[i] == SPELL_EFFECT_SCHOOL_DAMAGE || 
    4283                     m_spellInfo->Effect[i] == SPELL_EFFECT_POWER_BURN || 
    4284                     m_spellInfo->Effect[i] == SPELL_EFFECT_HEALTH_LEECH || 
    4285                     m_spellInfo->Effect[i] == SPELL_EFFECT_CHARGE) 
    4286                     return SPELL_FAILED_UNIT_NOT_INFRONT; 
    4287             } 
    4288         } 
     4241        if( m_caster->GetTypeId() == TYPEID_PLAYER && 
     4242            (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc( M_PI, target ) ) 
     4243            return SPELL_FAILED_UNIT_NOT_INFRONT; 
    42894244    } 
    42904245 
  • trunk/src/game/Spell.h

    r2 r6  
    252252        void EffectResurrect(uint32 i); 
    253253        void EffectParry(uint32 i); 
     254        void EffectBlock(uint32 i); 
    254255        void EffectMomentMove(uint32 i); 
    255256        void EffectTransmitted(uint32 i); 
  • trunk/src/game/SpellEffects.cpp

    r2 r6  
    7979    &Spell::EffectUnused,                                   // 21 SPELL_EFFECT_EVADE                    one spell: Evade (DND) 
    8080    &Spell::EffectParry,                                    // 22 SPELL_EFFECT_PARRY 
    81     &Spell::EffectUnused,                                   // 23 SPELL_EFFECT_BLOCK                    one spell: Block 
     81    &Spell::EffectBlock,                                    // 23 SPELL_EFFECT_BLOCK                    one spell: Block 
    8282    &Spell::EffectCreateItem,                               // 24 SPELL_EFFECT_CREATE_ITEM 
    8383    &Spell::EffectUnused,                                   // 25 SPELL_EFFECT_WEAPON 
     
    53315331} 
    53325332 
     5333void Spell::EffectBlock(uint32 /*i*/) 
     5334{ 
     5335    if (unitTarget->GetTypeId() != TYPEID_PLAYER) 
     5336        return; 
     5337 
     5338    ((Player*)unitTarget)->SetCanBlock(true); 
     5339} 
     5340 
    53335341void Spell::EffectMomentMove(uint32 i) 
    53345342{ 
  • trunk/src/game/StatSystem.cpp

    r2 r6  
    432432void Player::UpdateBlockPercentage() 
    433433{ 
    434     // Base value 
    435     float value = 5.0f; 
    436     // Modify value from defense skill 
    437     value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; 
    438     // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura 
    439     value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT); 
    440     // Increase from rating 
    441     value += GetRatingBonusValue(CR_BLOCK); 
    442     value = value < 0.0f ? 0.0f : value; 
     434    // No block 
     435    float value = 0.0f; 
     436    if(CanBlock()) 
     437    { 
     438        // Base value 
     439        value = 5.0f; 
     440        // Modify value from defense skill 
     441        value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; 
     442        // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura 
     443        value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT); 
     444        // Increase from rating 
     445        value += GetRatingBonusValue(CR_BLOCK); 
     446        value = value < 0.0f ? 0.0f : value; 
     447    } 
    443448    SetStatFloatValue(PLAYER_BLOCK_PERCENTAGE, value); 
    444449} 
     
    492497void Player::UpdateParryPercentage() 
    493498{ 
    494     // Base parry 
    495     float value  = 5.0f; 
    496     // Modify value from defense skill 
    497     value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; 
    498     // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura 
    499     value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT); 
    500     // Parry from rating 
    501     value += GetRatingBonusValue(CR_PARRY); 
    502     value = value < 0.0f ? 0.0f : value; 
     499    // No parry 
     500    float value = 0.0f; 
     501    if (CanParry()) 
     502    { 
     503        // Base parry 
     504        value  = 5.0f; 
     505        // Modify value from defense skill 
     506        value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f; 
     507        // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura 
     508        value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT); 
     509        // Parry from rating 
     510        value += GetRatingBonusValue(CR_PARRY); 
     511        value = value < 0.0f ? 0.0f : value; 
     512    } 
    503513    SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value); 
    504514} 
  • trunk/src/game/Unit.cpp

    r2 r6  
    29912991        if(player->CanParry() ) 
    29922992        { 
    2993             Item *tmpitem = ((Player*)this)->GetWeaponForAttack(BASE_ATTACK,true); 
     2993            Item *tmpitem = player->GetWeaponForAttack(BASE_ATTACK,true); 
    29942994            if(!tmpitem) 
    2995                 tmpitem = ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true); 
     2995                tmpitem = player->GetWeaponForAttack(OFF_ATTACK,true); 
    29962996 
    29972997            if(tmpitem) 
     
    30183018    if(GetTypeId() == TYPEID_PLAYER) 
    30193019    { 
    3020         Item *tmpitem = ((Player const*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); 
    3021         if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block) 
    3022             return GetFloatValue(PLAYER_BLOCK_PERCENTAGE); 
    3023         else 
    3024             return 0.0f; 
     3020        Player const* player = (Player const*)this; 
     3021        if(player->CanBlock() ) 
     3022        { 
     3023            Item *tmpitem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); 
     3024            if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block) 
     3025                return GetFloatValue(PLAYER_BLOCK_PERCENTAGE); 
     3026        } 
     3027        // is player but has no block ability or no not broken shield equiped 
     3028        return 0.0f; 
    30253029    } 
    30263030    else 
     
    34163420        return c->canSwim(); 
    34173421    else 
    3418         return c->canWalk(); 
     3422        return c->canWalk() || c->canFly(); 
    34193423} 
    34203424 
  • trunk/src/game/Unit.h

    r2 r6  
    116116 
    117117#define MAX_SPELLMOD 32 
     118 
     119enum SpellFacingFlags 
     120{ 
     121    SPELL_FACING_FLAG_INFRONT = 0x0001 
     122}; 
    118123 
    119124#define BASE_MINDAMAGE 1.0f 
  • trunk/src/game/WaypointMovementGenerator.cpp

    r2 r6  
    112112            // Now we re-set destination to same node and start travel 
    113113            creature.addUnitState(UNIT_STAT_ROAMING); 
     114            if (creature.canFly()) 
     115                creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2); 
    114116            const WaypointNode &node = i_path->at(i_currentNode); 
    115117            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); 
     
    174176        { 
    175177            creature.addUnitState(UNIT_STAT_ROAMING); 
     178            if (creature.canFly()) 
     179                creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2); 
    176180            const WaypointNode &node = i_path->at(i_currentNode); 
    177181            i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z); 
  • trunk/src/game/World.cpp

    r2 r6  
    2222 
    2323#include "Common.h" 
     24//#include "WorldSocket.h" 
    2425#include "Database/DatabaseEnv.h" 
    2526#include "Config/ConfigEnv.h" 
     
    5152#include "GameEvent.h" 
    5253#include "Database/DatabaseImpl.h" 
    53 #include "WorldSocket.h" 
    5454#include "GridNotifiersImpl.h" 
    5555#include "CellImpl.h" 
     
    124124 
    125125    if(m_resultQueue) delete m_resultQueue; 
     126     
     127    //TODO free addSessQueue 
    126128} 
    127129 
     
    174176} 
    175177 
    176 /// Add a session to the session list 
    177178void World::AddSession(WorldSession* s) 
    178179{ 
    179     ASSERT(s); 
    180  
    181     WorldSession* old = m_sessions[s->GetAccountId()]; 
    182     m_sessions[s->GetAccountId()] = s; 
    183  
    184     // if session already exist, prepare to it deleting at next world update 
    185     if(old) 
    186         m_kicked_sessions.insert(old); 
    187 } 
    188  
    189 int32 World::GetQueuePos(WorldSocket* socket) 
     180  addSessQueue.add(s); 
     181} 
     182 
     183void 
     184World::AddSession_ (WorldSession* s) 
     185{ 
     186  ASSERT (s); 
     187 
     188  //NOTE - Still there is race condition in WorldSession* being used in the Sockets 
     189 
     190  ///- kick already loaded player with same account (if any) and remove session 
     191  ///- if player is in loading and want to load again, return 
     192  if (!RemoveSession (s->GetAccountId ())) 
     193    { 
     194      s->KickPlayer (); 
     195      m_kicked_sessions.insert (s); 
     196      return; 
     197    } 
     198 
     199  WorldSession* old = m_sessions[s->GetAccountId ()]; 
     200  m_sessions[s->GetAccountId ()] = s; 
     201 
     202  // if session already exist, prepare to it deleting at next world update 
     203  // NOTE - KickPlayer() should be called on "old" in RemoveSession() 
     204  if (old) 
     205    m_kicked_sessions.insert (old); 
     206 
     207  uint32 Sessions = GetActiveAndQueuedSessionCount (); 
     208  uint32 pLimit = GetPlayerAmountLimit (); 
     209  uint32 QueueSize = GetQueueSize (); //number of players in the queue 
     210  bool inQueue = false; 
     211  //so we don't count the user trying to  
     212  //login as a session and queue the socket that we are using 
     213  --Sessions; 
     214 
     215  if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER ) 
     216    { 
     217      AddQueuedPlayer (s); 
     218      UpdateMaxSessionCounters (); 
     219      sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize); 
     220      return; 
     221    } 
     222   
     223  WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); 
     224  packet << uint8 (AUTH_OK); 
     225  packet << uint32 (0); // unknown random value... 
     226  packet << uint8 (0); 
     227  packet << uint32 (0); 
     228  packet << uint8 (s->IsTBC () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account 
     229  s->SendPacket (&packet); 
     230 
     231  UpdateMaxSessionCounters (); 
     232 
     233  // Updates the population 
     234  if (pLimit > 0) 
     235    { 
     236      float popu = GetActiveSessionCount (); //updated number of users on the server 
     237      popu /= pLimit; 
     238      popu *= 2; 
     239      loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); 
     240      sLog.outDetail ("Server Population (%f).", popu); 
     241    } 
     242} 
     243 
     244int32 World::GetQueuePos(WorldSession* sess) 
    190245{ 
    191246    uint32 position = 1; 
    192247 
    193248    for(Queue::iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position) 
    194         if((*iter) == socket) 
     249        if((*iter) == sess) 
    195250            return position; 
    196251 
     
    198253} 
    199254 
    200 void World::AddQueuedPlayer(WorldSocket* socket) 
    201 { 
    202     m_QueuedPlayer.push_back(socket); 
    203 } 
    204  
    205 void World::RemoveQueuedPlayer(WorldSocket* socket) 
     255void World::AddQueuedPlayer(WorldSession* sess) 
     256{ 
     257    m_QueuedPlayer.push_back (sess); 
     258     
     259    // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. 
     260    WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); 
     261    packet << uint8 (AUTH_WAIT_QUEUE); 
     262    packet << uint32 (0); // unknown random value... 
     263    packet << uint8 (0); 
     264    packet << uint32 (0); 
     265    packet << uint8 (sess->IsTBC () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account 
     266    packet << uint32(GetQueuePos (sess)); 
     267    sess->SendPacket (&packet); 
     268     
     269    //sess->SendAuthWaitQue (GetQueuePos (sess)); 
     270} 
     271 
     272void World::RemoveQueuedPlayer(WorldSession* sess) 
    206273{ 
    207274    // sessions count including queued to remove (if removed_session set) 
     
    214281    bool decrease_session = true; 
    215282 
    216     // search socket to remove and count skipped positions 
     283    // search to remove and count skipped positions 
    217284    for(;iter != m_QueuedPlayer.end(); ++iter, ++position) 
    218285    { 
    219         if(*iter==socket) 
     286        if(*iter==sess) 
    220287        { 
    221288            Queue::iterator iter2 = iter; 
     
    237304    if( (!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty() ) 
    238305    { 
    239         WorldSocket * socket = m_QueuedPlayer.front(); 
     306        WorldSession * socket = m_QueuedPlayer.front(); 
    240307        socket->SendAuthWaitQue(0); 
    241308        m_QueuedPlayer.pop_front(); 
     
    10161083    objmgr.LoadBattleMastersEntry(); 
    10171084 
     1085    sLog.outString( "Loading GameTeleports..." ); 
     1086    objmgr.LoadGameTele(); 
     1087 
     1088    sLog.outString( "Loading Npc Text Id..." ); 
     1089    objmgr.LoadNpcTextId();                                 // must be after load Creature and NpcText 
     1090 
     1091    sLog.outString( "Loading vendors..." ); 
     1092    objmgr.LoadVendors();                                   // must be after load CreatureTemplate and ItemTemplate 
     1093 
     1094    sLog.outString( "Loading trainers..." ); 
     1095    objmgr.LoadTrainerSpell();                              // must be after load CreatureTemplate 
     1096 
    10181097    sLog.outString( "Loading Waypoints..." ); 
    10191098    WaypointMgr.Load(); 
     
    20692148{ 
    20702149    // session not removed at kick and will removed in next update tick 
    2071     for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr) 
    2072         if(WorldSession* session = (*itr)->GetSession()) 
    2073             session->KickPlayer(); 
     2150  //TODO here 
     2151//    for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr) 
     2152//        if(WorldSession* session = (*itr)->GetSession()) 
     2153//            session->KickPlayer(); 
    20742154 
    20752155    m_QueuedPlayer.empty(); 
     
    23212401void World::UpdateSessions( time_t diff ) 
    23222402{ 
     2403    while(!addSessQueue.empty()) 
     2404    { 
     2405      WorldSession* sess = addSessQueue.next (); 
     2406      AddSession_ (sess); 
     2407    } 
     2408         
    23232409    ///- Delete kicked sessions at add new session 
    23242410    for (std::set<WorldSession*>::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr) 
  • trunk/src/game/World.h

    r2 r6  
    363363 
    364364        //player Queue 
    365         typedef std::list<WorldSocket*> Queue; 
    366         void AddQueuedPlayer(WorldSocket* Socket); 
    367         void RemoveQueuedPlayer(WorldSocket* Socket); 
    368         int32 GetQueuePos(WorldSocket* Socket); 
     365        typedef std::list<WorldSession*> Queue; 
     366        void AddQueuedPlayer(WorldSession*); 
     367        void RemoveQueuedPlayer(WorldSession*); 
     368        int32 GetQueuePos(WorldSession*); 
    369369        uint32 GetQueueSize() const { return m_QueuedPlayer.size(); } 
    370370 
     
    526526        //Player Queue 
    527527        Queue m_QueuedPlayer; 
     528         
     529        //sessions that are added async 
     530        void AddSession_(WorldSession* s); 
     531        ZThread::LockedQueue<WorldSession*, ZThread::FastMutex> addSessQueue; 
    528532}; 
    529533 
  • trunk/src/game/WorldSession.cpp

    r2 r6  
    2121*/ 
    2222 
     23#include "WorldSocket.h" 
    2324#include "Common.h" 
    2425#include "Database/DatabaseEnv.h" 
     
    4344WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, bool tbc, time_t mute_time, LocaleConstant locale) : 
    4445LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time), 
    45 _player(NULL), _socket(sock),_security(sec), _accountId(id), m_isTBC(tbc), 
     46_player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_isTBC(tbc), 
    4647m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)), 
    4748_logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0) 
    4849{ 
     50   if (sock) 
     51     { 
     52       m_Address = sock->GetRemoteAddress (); 
     53       sock->AddReference (); 
     54     } 
    4955} 
    5056 
     
    5763 
    5864    /// - If have unclosed socket, close it 
    59     if(_socket) 
    60         _socket->CloseSocket(); 
    61  
    62     _socket = NULL; 
     65  if (m_Socket) 
     66    { 
     67      m_Socket->CloseSocket ();    
     68      m_Socket->RemoveReference (); 
     69      m_Socket = NULL; 
     70    } 
    6371 
    6472    ///- empty incoming packet queue 
     
    6876        delete packet; 
    6977    } 
     78     
     79    sWorld.RemoveQueuedPlayer(this); 
    7080} 
    7181 
     
    8292} 
    8393 
    84 /// Set the WorldSocket associated with this session 
    85 void WorldSession::SetSocket(WorldSocket *sock) 
    86 { 
    87     _socket = sock; 
    88 } 
    89  
    9094/// Send a packet to the client 
    9195void WorldSession::SendPacket(WorldPacket const* packet) 
    9296{ 
    93     if (!_socket) 
     97    if (!m_Socket) 
    9498        return; 
    9599    #ifdef MANGOS_DEBUG 
     
    125129        sendLastPacketBytes = packet->wpos();               // wpos is real written size 
    126130    } 
    127     #endif                                                  // !MANGOS_DEBUG 
    128  
    129     _socket->SendPacket(packet); 
     131#endif                                                  // !MANGOS_DEBUG 
     132 
     133  if (m_Socket->SendPacket (*packet) == -1) 
     134    { 
     135      m_Socket->CloseSocket (); 
     136    } 
    130137} 
    131138 
    132139/// Add an incoming packet to the queue 
    133 void WorldSession::QueuePacket(WorldPacket& packet) 
    134 { 
    135     WorldPacket *pck = new WorldPacket(packet); 
    136     _recvQueue.add(pck); 
     140void WorldSession::QueuePacket(WorldPacket* new_packet) 
     141{ 
     142    _recvQueue.add(new_packet); 
    137143} 
    138144 
     
    149155bool WorldSession::Update(uint32 /*diff*/) 
    150156{ 
     157  if (m_Socket) 
     158    if (m_Socket->IsClosed ()) 
     159      {  
     160        m_Socket->RemoveReference (); 
     161        m_Socket = NULL; 
     162      } 
     163   
    151164    WorldPacket *packet; 
    152165 
     
    211224    ///- If necessary, log the player out 
    212225    time_t currTime = time(NULL); 
    213     if (!_socket || (ShouldLogOut(currTime) && !m_playerLoading)) 
     226    if (!m_Socket || (ShouldLogOut(currTime) && !m_playerLoading)) 
    214227        LogoutPlayer(true); 
    215228 
    216     if (!_socket) 
     229    if (!m_Socket) 
    217230        return false;                                       //Will remove this session from the world session map 
    218231 
     
    344357        // remove player from the group if he is: 
    345358        // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) 
    346         if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && _socket) 
     359        if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) 
    347360            _player->RemoveFromGroup(); 
    348361 
     
    386399void WorldSession::KickPlayer() 
    387400{ 
    388     if(!_socket) 
    389         return; 
    390  
    391     // player will be logout and session will removed in next update tick 
    392     _socket->CloseSocket(); 
    393     _socket = NULL; 
     401  if (m_Socket) 
     402    { 
     403      m_Socket->CloseSocket (); 
     404    } 
    394405} 
    395406 
     
    462473        recvPacket.GetOpcode()); 
    463474} 
     475 
     476void WorldSession::SendAuthWaitQue(uint32 position) 
     477 { 
     478     if(position == 0) 
     479     { 
     480         WorldPacket packet( SMSG_AUTH_RESPONSE, 1 ); 
     481         packet << uint8( AUTH_OK ); 
     482         SendPacket(&packet); 
     483     } 
     484     else 
     485     { 
     486         WorldPacket packet( SMSG_AUTH_RESPONSE, 5 ); 
     487         packet << uint8( AUTH_WAIT_QUEUE ); 
     488         packet << uint32 (position); 
     489         SendPacket(&packet); 
     490     } 
     491 } 
     492  
     493 
  • trunk/src/game/WorldSession.h

    r2 r6  
    8989        char const* GetPlayerName() const; 
    9090        void SetSecurity(uint32 security) { _security = security; } 
    91         void SetSocket(WorldSocket *sock); 
     91        std::string& GetRemoteAddress() { return m_Address; } 
    9292        void SetPlayer(Player *plr) { _player = plr; } 
    9393        bool IsTBC() const { return m_isTBC; } 
     
    111111        void KickPlayer(); 
    112112 
    113         void QueuePacket(WorldPacket& packet); 
     113        void QueuePacket(WorldPacket* new_packet); 
    114114        bool Update(uint32 diff); 
     115         
     116        /// Handle the authentication waiting queue (to be completed) 
     117        void SendAuthWaitQue(uint32 position); 
    115118 
    116119        //void SendTestCreatureQueryOpcode( uint32 entry, uint64 guid, uint32 testvalue ); 
     
    619622        void logUnexpectedOpcode(WorldPacket *packet, const char * reason); 
    620623        Player *_player; 
    621         WorldSocket *_socket; 
     624        WorldSocket *m_Socket; 
     625        std::string m_Address; 
    622626 
    623627        uint32 _security; 
  • trunk/src/game/WorldSocket.cpp

    r2 r6  
    1 /* 
     1/*  
    22 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> 
    33 * 
     
    1717 */ 
    1818 
    19 /** \file 
    20     \ingroup u2w 
    21 */ 
    22  
    2319#include "Common.h" 
    24 #include "Log.h" 
     20#include "WorldSocket.h"  
     21#include <ace/Message_Block.h> 
     22#include <ace/OS_NS_string.h> 
     23#include <ace/OS_NS_unistd.h> 
     24#include <ace/os_include/arpa/os_inet.h> 
     25#include <ace/os_include/netinet/os_tcp.h> 
     26#include <ace/os_include/sys/os_types.h> 
     27#include <ace/os_include/sys/os_socket.h> 
     28#include <ace/OS_NS_string.h> 
     29#include <ace/Reactor.h> 
     30#include <ace/Auto_Ptr.h> 
     31 
     32#include "Util.h" 
     33#include "World.h" 
     34#include "WorldPacket.h" 
     35#include "SharedDefines.h" 
     36#include "ByteBuffer.h" 
     37#include "AddonHandler.h" 
    2538#include "Opcodes.h" 
    2639#include "Database/DatabaseEnv.h" 
    2740#include "Auth/Sha1.h" 
    28 #include "WorldPacket.h" 
    29 #include "WorldSocket.h" 
    3041#include "WorldSession.h" 
    31 #include "World.h" 
    3242#include "WorldSocketMgr.h" 
    33 #include "Policies/SingletonImp.h" 
     43#include "Log.h" 
    3444#include "WorldLog.h" 
    35 #include "AddonHandler.h" 
    36 #include "sockets/Utility.h" 
    37 #include "Util.h" 
    38  
    39 // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform 
     45 
    4046#if defined( __GNUC__ ) 
    4147#pragma pack(1) 
     
    4450#endif 
    4551 
    46 /// Client Packet Header 
     52struct ServerPktHeader 
     53{ 
     54  ACE_UINT16 size; 
     55  ACE_UINT16 cmd; 
     56}; 
     57 
    4758struct ClientPktHeader 
    4859{ 
    49     uint16 size; 
    50     uint32 cmd; 
     60  ACE_UINT16 size; 
     61  ACE_UINT32 cmd; 
    5162}; 
    5263 
    53 /// Server Packet Header 
    54 struct ServerPktHeader 
    55 { 
    56     uint16 size; 
    57     uint16 cmd; 
    58 }; 
    59  
    60 // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform 
    6164#if defined( __GNUC__ ) 
    6265#pragma pack() 
     
    6568#endif 
    6669 
    67 #define SOCKET_CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S)); 
    68  
    69 /// WorldSocket construction and initialization. 
    70 WorldSocket::WorldSocket(ISocketHandler &sh): TcpSocket(sh), _cmd(0), _remaining(0), _session(NULL) 
    71 { 
    72     _seed = static_cast<uint32>(rand32()); 
    73     m_LastPingMSTime = 0;                                   // first time it will counted as overspeed maybe, but this is not important 
    74     m_OverSpeedPings = 0; 
    75  
    76     if (sWorld.getConfig(CONFIG_TCP_NO_DELAY)) 
    77         SetTcpNodelay(true); 
    78 } 
    79  
    80 /// WorldSocket destructor 
    81 WorldSocket::~WorldSocket() 
    82 { 
    83     if(_session) 
    84         _session->SetSocket(0); 
    85  
    86     WorldPacket *packet; 
    87  
    88     ///- Go through the to-be-sent queue and delete remaining packets 
    89     while(!_sendQueue.empty()) 
    90     { 
    91         packet = _sendQueue.next(); 
    92         delete packet; 
    93     } 
    94 } 
    95  
    96 /// Copy the packet to the to-be-sent queue 
    97 void WorldSocket::SendPacket(WorldPacket const* packet) 
    98 { 
    99     WorldPacket *pck = new WorldPacket(*packet); 
    100     ASSERT(pck); 
    101     _sendQueue.add(pck); 
    102 } 
    103  
    104 /// On client connection 
    105 void WorldSocket::OnAccept() 
    106 { 
    107     ///- Add the current socket to the list of sockets to be managed (WorldSocketMgr) 
    108     sWorldSocketMgr.AddSocket(this); 
    109     Utility::ResolveLocal(); 
    110  
    111     ///- Send a AUTH_CHALLENGE packet 
    112     WorldPacket packet( SMSG_AUTH_CHALLENGE, 4 ); 
    113     packet << _seed; 
    114  
    115     SendPacket(&packet); 
    116 } 
    117  
    118 /// Read the client transmitted data 
    119 void WorldSocket::OnRead() 
    120 { 
    121     TcpSocket::OnRead(); 
    122  
    123     while(1) 
    124     { 
    125         ///- Read the packet header and decipher it (if needed) 
    126         if (!_remaining) 
    127         { 
    128             if (ibuf.GetLength() < 6) 
    129                 break; 
    130  
    131             ClientPktHeader hdr; 
    132  
    133             ibuf.Read((char *)&hdr, 6); 
    134             _crypt.DecryptRecv((uint8 *)&hdr, 6); 
    135  
    136             _remaining = ntohs(hdr.size) - 4; 
    137             _cmd = hdr.cmd; 
    138         } 
    139  
    140         if (ibuf.GetLength() < _remaining) 
    141             break; 
    142  
    143         ///- Read the remaining of the packet 
    144         WorldPacket packet((uint16)_cmd, _remaining); 
    145  
    146         packet.resize(_remaining); 
    147         if(_remaining) ibuf.Read((char*)packet.contents(), _remaining); 
    148         _remaining = 0; 
    149  
    150         ///- If log of world packets is enable, log the incoming packet 
    151         if( sWorldLog.LogWorld() ) 
    152         { 
    153             sWorldLog.Log("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
    154                 (uint32)GetSocket(), 
    155                 packet.size(), 
    156                 LookupOpcodeName(packet.GetOpcode()), 
    157                 packet.GetOpcode()); 
    158  
    159             uint32 p = 0; 
    160             while (p < packet.size()) 
     70// used when testing to alow login without password and encryption 
     71// #define _NETCODE_FAKE_AUTH 
     72 
     73WorldSocket::WorldSocket (void) : 
     74WorldHandler (), 
     75m_Session (0), 
     76m_RecvWPct (0), 
     77m_RecvPct (), 
     78m_Header (sizeof (ClientPktHeader)), 
     79m_OutBuffer (0), 
     80m_OutBufferSize (65536), 
     81m_OutActive (false), 
     82m_Seed (static_cast<uint32> (rand32 ())), 
     83m_OverSpeedPings (0), 
     84m_LastPingTime (ACE_Time_Value::zero) 
     85{ 
     86  this->reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); 
     87} 
     88 
     89WorldSocket::~WorldSocket (void) 
     90{ 
     91  if (m_RecvWPct) 
     92    delete m_RecvWPct; 
     93 
     94  if (m_OutBuffer) 
     95    m_OutBuffer->release (); 
     96 
     97  this->closing_ = true; 
     98 
     99  this->peer ().close (); 
     100 
     101  WorldPacket* pct; 
     102  while (m_PacketQueue.dequeue_head (pct) == 0) 
     103    delete pct; 
     104} 
     105 
     106bool 
     107WorldSocket::IsClosed (void) const 
     108{ 
     109  return this->closing_; 
     110} 
     111 
     112void 
     113WorldSocket::CloseSocket (void) 
     114{ 
     115  { 
     116    ACE_GUARD (LockType, Guard, m_OutBufferLock); 
     117 
     118    if (this->closing_) 
     119      return; 
     120 
     121    this->closing_ = true; 
     122 
     123    this->peer ().close_writer (); 
     124  } 
     125 
     126  { 
     127    ACE_GUARD (LockType, Guard, m_SessionLock); 
     128 
     129    m_Session = NULL; 
     130  } 
     131 
     132} 
     133 
     134const std::string& 
     135WorldSocket::GetRemoteAddress (void) const 
     136{ 
     137  return m_Address; 
     138} 
     139 
     140int 
     141WorldSocket::SendPacket (const WorldPacket& pct) 
     142{ 
     143  ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
     144 
     145  if (this->closing_) 
     146    return -1; 
     147 
     148  // Dump outgoing packet. 
     149  if (sWorldLog.LogWorld ()) 
     150    { 
     151      sWorldLog.Log ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
     152                     (uint32) get_handle (), 
     153                     pct.size (), 
     154                     LookupOpcodeName (pct.GetOpcode ()), 
     155                     pct.GetOpcode ()); 
     156 
     157      uint32 p = 0; 
     158      while (p < pct.size ()) 
     159        { 
     160          for (uint32 j = 0; j < 16 && p < pct.size (); j++) 
     161            sWorldLog.Log ("%.2X ", const_cast<WorldPacket&>(pct)[p++]); 
     162 
     163          sWorldLog.Log ("\n"); 
     164        } 
     165 
     166      sWorldLog.Log ("\n\n"); 
     167    } 
     168 
     169  if (iSendPacket (pct) == -1) 
     170    { 
     171      WorldPacket* npct; 
     172 
     173      ACE_NEW_RETURN (npct, WorldPacket (pct), -1); 
     174 
     175      // NOTE maybe check of the size of the queue can be good ? 
     176      // to make it bounded instead of unbounded 
     177      if (m_PacketQueue.enqueue_tail (npct) == -1) 
     178        { 
     179          delete npct; 
     180          sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed"); 
     181          return -1; 
     182        } 
     183    } 
     184 
     185  return 0; 
     186} 
     187 
     188long 
     189WorldSocket::AddReference (void) 
     190{ 
     191  return static_cast<long> (this->add_reference ()); 
     192} 
     193 
     194long 
     195WorldSocket::RemoveReference (void) 
     196{ 
     197  return static_cast<long> (this->remove_reference ()); 
     198} 
     199 
     200int 
     201WorldSocket::open (void *a) 
     202{ 
     203  ACE_UNUSED_ARG (a); 
     204 
     205  // Prevent double call to this func. 
     206  if (m_OutBuffer) 
     207    return -1; 
     208 
     209  // This will also prevent the socket from being Updated 
     210  // while we are initializing it. 
     211  m_OutActive = true; 
     212 
     213  // Hook for the manager. 
     214  if (sWorldSocketMgr->OnSocketOpen (this) == -1) 
     215    return -1; 
     216 
     217  // Allocate the buffer. 
     218  ACE_NEW_RETURN (m_OutBuffer, ACE_Message_Block (m_OutBufferSize), -1); 
     219 
     220  // Store peer address. 
     221  ACE_INET_Addr remote_addr; 
     222 
     223  if (this->peer ().get_remote_addr (remote_addr) == -1) 
     224    { 
     225      sLog.outError ("WorldSocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno)); 
     226      return -1; 
     227    } 
     228 
     229  m_Address = remote_addr.get_host_addr (); 
     230 
     231  // Send startup packet. 
     232  WorldPacket packet (SMSG_AUTH_CHALLENGE, 4); 
     233  packet << m_Seed; 
     234 
     235  if (SendPacket (packet) == -1) 
     236    return -1; 
     237 
     238  // Register with ACE Reactor 
     239  if (this->reactor ()->register_handler 
     240      (this, 
     241       ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1) 
     242    { 
     243      sLog.outError ("WorldSocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno)); 
     244      return -1; 
     245    } 
     246 
     247  // reactor takes care of the socket from now on 
     248  this->remove_reference (); 
     249 
     250  return 0; 
     251} 
     252 
     253int 
     254WorldSocket::close (int) 
     255{ 
     256  this->shutdown (); 
     257 
     258  this->closing_ = true; 
     259 
     260  this->remove_reference (); 
     261 
     262  return 0; 
     263} 
     264 
     265int 
     266WorldSocket::handle_input (ACE_HANDLE) 
     267{ 
     268  if (this->closing_) 
     269    return -1; 
     270 
     271  switch (this->handle_input_missing_data ()) 
     272    { 
     273    case -1 : 
     274      { 
     275        if ((errno == EWOULDBLOCK) || 
     276            (errno == EAGAIN)) 
     277          { 
     278            //return 0; 
     279            return this->Update (); // interesting line ,isnt it ? 
     280          } 
     281 
     282        DEBUG_LOG ("WorldSocket::handle_input: Peer error closing connection errno = %s", ACE_OS::strerror (errno)); 
     283 
     284        return -1; 
     285      } 
     286    case 0: 
     287      { 
     288        DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection\n"); 
     289 
     290        errno = ECONNRESET; 
     291 
     292        return -1; 
     293      } 
     294    case 1: 
     295      return 1; 
     296    } 
     297 
     298  //return 0; 
     299  return this->Update (); // another interesting line ;) 
     300} 
     301 
     302int 
     303WorldSocket::handle_output (ACE_HANDLE) 
     304{ 
     305  ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
     306 
     307  if (this->closing_) 
     308    return -1; 
     309 
     310  const size_t send_len = m_OutBuffer->length (); 
     311 
     312  if (send_len == 0) 
     313    return this->cancel_wakeup_output (Guard); 
     314   
     315// TODO SO_NOSIGPIPE on platforms that support it 
     316#ifdef MSG_NOSIGNAL 
     317  ssize_t n = this->peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL); 
     318#else 
     319  ssize_t n = this->peer ().send (m_OutBuffer->rd_ptr (), send_len); 
     320#endif // MSG_NOSIGNAL 
     321           
     322  if (n == 0) 
     323    return -1; 
     324  else if (n == -1) 
     325    { 
     326      if (errno == EWOULDBLOCK || errno == EAGAIN) 
     327        return this->schedule_wakeup_output (Guard); 
     328 
     329      return -1; 
     330    } 
     331  else if (n < send_len) //now n > 0 
     332    { 
     333      m_OutBuffer->rd_ptr (static_cast<size_t> (n)); 
     334 
     335      // move the data to the base of the buffer 
     336      m_OutBuffer->crunch (); 
     337 
     338      return this->schedule_wakeup_output (Guard); 
     339    } 
     340  else //now n == send_len 
     341    { 
     342      m_OutBuffer->reset (); 
     343 
     344      if (!iFlushPacketQueue ()) 
     345        return this->cancel_wakeup_output (Guard); 
     346      else 
     347        return this->schedule_wakeup_output (Guard); 
     348    } 
     349 
     350  ACE_NOTREACHED (return 0); 
     351} 
     352 
     353int 
     354WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) 
     355{ 
     356  // Critical section 
     357  { 
     358    ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
     359 
     360    this->closing_ = true; 
     361 
     362    if (h == ACE_INVALID_HANDLE) 
     363      this->peer ().close_writer (); 
     364  } 
     365 
     366  // Critical section 
     367  { 
     368    ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     369 
     370    m_Session = NULL; 
     371  } 
     372 
     373  return 0; 
     374} 
     375 
     376int 
     377WorldSocket::Update (void) 
     378{ 
     379  if (this->closing_) 
     380    return -1; 
     381 
     382  if (m_OutActive || m_OutBuffer->length () == 0) 
     383    return 0; 
     384 
     385  return this->handle_output (this->get_handle ()); 
     386} 
     387 
     388int 
     389WorldSocket::handle_input_header (void) 
     390{ 
     391  ACE_ASSERT (m_RecvWPct == NULL); 
     392 
     393  if (m_Header.length () != sizeof (ClientPktHeader)) 
     394    { 
     395      sLog.outError ("WorldSocket::handle_input_header: internal error: invalid header"); 
     396      errno = EINVAL; 
     397      return -1; 
     398    } 
     399 
     400  m_Crypt.DecryptRecv ((ACE_UINT8*) m_Header.rd_ptr (), sizeof (ClientPktHeader)); 
     401 
     402  ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr ()); 
     403 
     404  header.size = ACE_NTOHS (header.size); 
     405 
     406#if ACE_BYTE_ORDER == ACE_BIG_ENDIAN 
     407  header.cmd = ACE_SWAP_LONG (header.cmd) 
     408#endif // ACE_BIG_ENDIAN 
     409 
     410  if ((header.size < 4) || 
     411      (header.size > 10240) || 
     412      (header.cmd <= 0) || 
     413      (header.cmd > 10240) 
     414      ) 
     415    { 
     416      sLog.outError ("WorldSocket::handle_input_header: client sent mailformed packet size = %d , cmd = %d", 
     417                     header.size, 
     418                     header.cmd); 
     419 
     420      errno = EINVAL; 
     421      return -1; 
     422    } 
     423 
     424  header.size -= 4; 
     425 
     426  ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1); 
     427 
     428  if(header.size > 0) 
     429  { 
     430     m_RecvWPct->resize (header.size);   
     431     m_RecvPct.base ((char*) m_RecvWPct->contents (), m_RecvWPct->size ()); 
     432  } 
     433  else 
     434  { 
     435     ACE_ASSERT(m_RecvPct.space() == 0); 
     436  } 
     437 
     438 
     439  return 0; 
     440} 
     441 
     442int 
     443WorldSocket::handle_input_payload (void) 
     444{ 
     445  // set errno properly here on error !!! 
     446  // now have a header and payload 
     447 
     448  ACE_ASSERT (m_RecvPct.space () == 0); 
     449  ACE_ASSERT (m_Header.space () == 0); 
     450  ACE_ASSERT (m_RecvWPct != NULL); 
     451 
     452  const int ret = this->ProcessIncoming (m_RecvWPct); 
     453 
     454  m_RecvPct.base (NULL, 0); 
     455  m_RecvPct.reset (); 
     456  m_RecvWPct = NULL; 
     457 
     458  m_Header.reset (); 
     459 
     460  if (ret == -1) 
     461    errno = EINVAL; 
     462 
     463  return ret; 
     464} 
     465 
     466int 
     467WorldSocket::handle_input_missing_data (void) 
     468{ 
     469  char buf [1024]; 
     470 
     471  ACE_Data_Block db (sizeof (buf), 
     472                     ACE_Message_Block::MB_DATA, 
     473                     buf, 
     474                     0, 
     475                     0, 
     476                     ACE_Message_Block::DONT_DELETE, 
     477                     0); 
     478 
     479  ACE_Message_Block message_block (&db, 
     480                                   ACE_Message_Block::DONT_DELETE, 
     481                                   0); 
     482 
     483  const size_t recv_size = message_block.space (); 
     484 
     485  const ssize_t n = this->peer ().recv (message_block.wr_ptr (), 
     486                                        recv_size); 
     487 
     488  if (n <= 0) 
     489    return n; 
     490 
     491  message_block.wr_ptr (n); 
     492 
     493  while (message_block.length () > 0) 
     494    { 
     495      if (m_Header.space () > 0) 
     496        { 
     497          //need to recieve the header 
     498          const size_t to_header = (message_block.length () > m_Header.space () ? m_Header.space () : message_block.length ()); 
     499          m_Header.copy (message_block.rd_ptr (), to_header); 
     500          message_block.rd_ptr (to_header); 
     501 
     502          if (m_Header.space () > 0) 
    161503            { 
    162                 for (uint32 j = 0; j < 16 && p < packet.size(); j++) 
    163                     sWorldLog.Log("%.2X ", packet[p++]); 
    164                 sWorldLog.Log("\n"); 
     504              //couldnt recieve the whole header this time 
     505              ACE_ASSERT (message_block.length () == 0); 
     506              errno = EWOULDBLOCK; 
     507              return -1; 
    165508            } 
    166             sWorldLog.Log("\n\n"); 
    167         } 
    168  
    169         ///- If the packet is PING, KEEP_ALIVE or AUTH_SESSION, handle immediately 
    170         switch (_cmd) 
    171         { 
    172             case CMSG_KEEP_ALIVE: 
    173                 break;                                      // just ignore, network connectivity timeout preventing 
    174             case CMSG_PING: 
     509 
     510          //we just recieved nice new header 
     511          if (this->handle_input_header () == -1) 
    175512            { 
    176                 _HandlePing(packet); 
    177                 break; 
     513              ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); 
     514              return -1; 
    178515            } 
    179             case CMSG_AUTH_SESSION: 
     516        } 
     517 
     518      // Its possible on some error situations that this happens 
     519      // for example on closing when epoll recieves more chunked data and stuff 
     520      // hope this is not hack ,as proper m_RecvWPct is asserted around 
     521      if (!m_RecvWPct) 
     522        { 
     523          sLog.outError ("Forsing close on input m_RecvWPct = NULL"); 
     524          errno = EINVAL; 
     525          return -1; 
     526        } 
     527 
     528      // We have full readed header, now check the data payload 
     529      if (m_RecvPct.space () > 0) 
     530        { 
     531          //need more data in the payload 
     532          const size_t to_data = (message_block.length () > m_RecvPct.space () ? m_RecvPct.space () : message_block.length ()); 
     533          m_RecvPct.copy (message_block.rd_ptr (), to_data); 
     534          message_block.rd_ptr (to_data); 
     535 
     536          if (m_RecvPct.space () > 0) 
    180537            { 
    181                 _HandleAuthSession(packet); 
    182                 break; 
     538              //couldnt recieve the whole data this time 
     539              ACE_ASSERT (message_block.length () == 0); 
     540              errno = EWOULDBLOCK; 
     541              return -1; 
    183542            } 
    184             default: 
     543        } 
     544 
     545      //just recieved fresh new payload 
     546      if (this->handle_input_payload () == -1) 
     547        { 
     548          ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); 
     549          return -1; 
     550        } 
     551    } 
     552 
     553  return n == recv_size ? 1 : 2; 
     554} 
     555 
     556int 
     557WorldSocket::cancel_wakeup_output (GuardType& g) 
     558{ 
     559  if (!m_OutActive) 
     560    return 0; 
     561 
     562  m_OutActive = false; 
     563 
     564  g.release (); 
     565 
     566  if (this->reactor ()->cancel_wakeup 
     567      (this, ACE_Event_Handler::WRITE_MASK) == -1) 
     568    { 
     569      // would be good to store errno from reactor with errno guard 
     570      sLog.outError ("WorldSocket::cancel_wakeup_output"); 
     571      return -1; 
     572    } 
     573 
     574  return 0; 
     575} 
     576 
     577int 
     578WorldSocket::schedule_wakeup_output (GuardType& g) 
     579{ 
     580  if (m_OutActive) 
     581    return 0; 
     582 
     583  m_OutActive = true; 
     584 
     585  g.release (); 
     586 
     587  if (this->reactor ()->schedule_wakeup 
     588      (this, ACE_Event_Handler::WRITE_MASK) == -1) 
     589    { 
     590      sLog.outError ("WorldSocket::schedule_wakeup_output"); 
     591      return -1; 
     592    } 
     593 
     594  return 0; 
     595} 
     596 
     597int 
     598WorldSocket::ProcessIncoming (WorldPacket* new_pct) 
     599{ 
     600  ACE_ASSERT (new_pct); 
     601   
     602  // manage memory ;) 
     603  ACE_Auto_Ptr<WorldPacket> aptr (new_pct); 
     604 
     605  const ACE_UINT16 opcode = new_pct->GetOpcode (); 
     606 
     607  if (this->closing_) 
     608    return -1; 
     609 
     610  // dump recieved packet 
     611  if (sWorldLog.LogWorld ()) 
     612    { 
     613      sWorldLog.Log ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
     614                     (uint32) get_handle (), 
     615                     new_pct->size (), 
     616                     LookupOpcodeName (new_pct->GetOpcode ()), 
     617                     new_pct->GetOpcode ()); 
     618 
     619      uint32 p = 0; 
     620      while (p < new_pct->size ()) 
     621        { 
     622          for (uint32 j = 0; j < 16 && p < new_pct->size (); j++) 
     623            sWorldLog.Log ("%.2X ", (*new_pct)[p++]); 
     624          sWorldLog.Log ("\n"); 
     625        } 
     626      sWorldLog.Log ("\n\n"); 
     627    } 
     628 
     629  // like one switch ;) 
     630  if (opcode == CMSG_PING) 
     631    { 
     632      return HandlePing (*new_pct); 
     633    } 
     634  else if (opcode == CMSG_AUTH_SESSION) 
     635    { 
     636      if (m_Session) 
     637        { 
     638          sLog.outError ("WorldSocket::ProcessIncoming: Player send CMSG_AUTH_SESSION again"); 
     639          return -1; 
     640        } 
     641 
     642      return HandleAuthSession (*new_pct); 
     643    } 
     644  else if (opcode == CMSG_KEEP_ALIVE) 
     645    { 
     646      DEBUG_LOG ("CMSG_KEEP_ALIVE ,size: %d", new_pct->size ()); 
     647 
     648      return 0; 
     649    } 
     650  else 
     651    { 
     652      ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     653 
     654      if (m_Session != NULL) 
     655        { 
     656          // OK ,give the packet to WorldSession 
     657          aptr.release (); 
     658          // WARNINIG here we call it with locks held. 
     659          // Its possible to cause deadlock if QueuePacket calls back 
     660          m_Session->QueuePacket (new_pct); 
     661          return 0; 
     662        } 
     663      else 
     664        { 
     665          sLog.outError ("WorldSocket::ProcessIncoming: Client not authed opcode = ", opcode); 
     666          return -1; 
     667        } 
     668    } 
     669 
     670  ACE_NOTREACHED (return 0); 
     671} 
     672 
     673int 
     674WorldSocket::HandleAuthSession (WorldPacket& recvPacket) 
     675{ 
     676  uint8 digest[20]; 
     677  uint32 clientSeed; 
     678  uint32 unk2; 
     679  uint32 BuiltNumberClient; 
     680  uint32 id, security; 
     681  bool tbc = false; 
     682  LocaleConstant locale; 
     683  std::string account; 
     684  Sha1Hash sha1; 
     685  BigNumber v, s, g, N, x, I; 
     686  WorldPacket packet, SendAddonPacked; 
     687 
     688  BigNumber K; 
     689 
     690  if (recvPacket.size () < (4 + 4 + 1 + 4 + 20)) 
     691    { 
     692      sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size"); 
     693      return -1; 
     694    } 
     695 
     696  // Read the content of the packet 
     697  recvPacket >> BuiltNumberClient; // for now no use 
     698  recvPacket >> unk2; 
     699  recvPacket >> account; 
     700 
     701  if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) 
     702    { 
     703      sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check"); 
     704      return -1; 
     705    } 
     706 
     707  recvPacket >> clientSeed; 
     708  recvPacket.read (digest, 20); 
     709 
     710  DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", 
     711             BuiltNumberClient, 
     712             unk2, 
     713             account.c_str (), 
     714             clientSeed); 
     715 
     716#if defined _NETCODE_FAKE_AUTH 
     717  bool dontchechtheacc = false; 
     718  uint8 digest_fake[sizeof (digest)]; 
     719  memset ((void*) digest_fake, '\0', sizeof (digest_fake)); 
     720  if (memcmp ((void*) digest, (void*) digest_fake, sizeof (digest_fake)) == 0) 
     721    { 
     722      dontchechtheacc = true; 
     723    } 
     724#endif //_NETCODE_FAKE_AUTH 
     725 
     726  // Get the account information from the realmd database 
     727  std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below 
     728  loginDatabase.escape_string (safe_account); 
     729  // No SQL injection, username escaped. 
     730 
     731  QueryResult *result = 
     732          loginDatabase.PQuery ("SELECT " 
     733                                "id, " //0 
     734                                "gmlevel, " //1 
     735                                "sessionkey, " //2 
     736                                "last_ip, " //3 
     737                                "locked, " //4 
     738                                "sha_pass_hash, " //5 
     739                                "v, " //6 
     740                                "s, " //7 
     741                                "tbc, " //8 
     742                                "mutetime, " //9 
     743                                "locale " //10 
     744                                "FROM account " 
     745                                "WHERE username = '%s'", 
     746                                safe_account.c_str ()); 
     747 
     748  // Stop if the account is not found 
     749  if (!result) 
     750    { 
     751      packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     752      packet << uint8 (AUTH_UNKNOWN_ACCOUNT); 
     753 
     754      SendPacket (packet); 
     755 
     756      sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); 
     757      return -1; 
     758    } 
     759 
     760  Field* fields = result->Fetch (); 
     761 
     762  tbc = fields[8].GetUInt8 () && sWorld.getConfig (CONFIG_EXPANSION) > 0; 
     763 
     764  N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); 
     765  g.SetDword (7); 
     766  I.SetHexStr (fields[5].GetString ()); 
     767 
     768  //In case of leading zeros in the I hash, restore them 
     769  uint8 mDigest[SHA_DIGEST_LENGTH]; 
     770  memset (mDigest, 0, SHA_DIGEST_LENGTH); 
     771 
     772  if (I.GetNumBytes () <= SHA_DIGEST_LENGTH) 
     773    memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ()); 
     774 
     775  std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH); 
     776 
     777  s.SetHexStr (fields[7].GetString ()); 
     778  sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ()); 
     779  sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH); 
     780  sha1.Finalize (); 
     781  x.SetBinary (sha1.GetDigest (), sha1.GetLength ()); 
     782  v = g.ModExp (x, N); 
     783 
     784  const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free() 
     785  const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free() 
     786  const char* vold = fields[6].GetString (); 
     787 
     788  DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v_old: %s v_new: %s", 
     789             sStr, 
     790             vold, 
     791             vStr); 
     792 
     793  loginDatabase.PExecute ("UPDATE account " 
     794                          "SET " 
     795                          "v = '0', " 
     796                          "s = '0' " 
     797                          "WHERE username = '%s'", 
     798                          safe_account.c_str ()); 
     799 
     800#if defined _NETCODE_FAKE_AUTH 
     801  if (!dontchechtheacc) 
     802    { 
     803#endif 
     804      if (!vold || strcmp (vStr, vold)) 
     805        { 
     806          packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     807          packet << uint8 (AUTH_UNKNOWN_ACCOUNT); 
     808          SendPacket (packet); 
     809          delete result; 
     810          OPENSSL_free ((void*) sStr); 
     811          OPENSSL_free ((void*) vStr); 
     812 
     813          sLog.outError ("WorldSocket::HandleAuthSession: User not logged."); 
     814          return -1; 
     815        } 
     816#if defined _NETCODE_FAKE_AUTH 
     817    } 
     818#endif 
     819 
     820  OPENSSL_free ((void*) sStr); 
     821  OPENSSL_free ((void*) vStr); 
     822 
     823  ///- Re-check ip locking (same check as in realmd). 
     824  if (fields[4].GetUInt8 () == 1) // if ip is locked 
     825    { 
     826      if (strcmp (fields[3].GetString (), GetRemoteAddress ().c_str ())) 
     827        { 
     828          packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     829          packet << uint8 (AUTH_FAILED); 
     830          SendPacket (packet); 
     831 
     832          delete result; 
     833          sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); 
     834          return -1; 
     835        } 
     836    } 
     837 
     838  id = fields[0].GetUInt32 (); 
     839  security = fields[1].GetUInt16 (); 
     840  K.SetHexStr (fields[2].GetString ()); 
     841 
     842  time_t mutetime = time_t (fields[9].GetUInt64 ()); 
     843 
     844  locale = LocaleConstant (fields[10].GetUInt8 ()); 
     845  if (locale >= MAX_LOCALE) 
     846    locale = LOCALE_enUS; 
     847 
     848  delete result; 
     849 
     850#if defined _NETCODE_FAKE_AUTH 
     851  if (!dontchechtheacc) 
     852    { 
     853#endif 
     854      // Re-check account ban (same check as in realmd)  
     855      QueryResult *banresult = 
     856              loginDatabase.PQuery ("SELECT " 
     857                                    "bandate, " 
     858                                    "unbandate " 
     859                                    "FROM account_banned " 
     860                                    "WHERE id = '%u' " 
     861                                    "AND active = 1", 
     862                                    id); 
     863 
     864      if (banresult) // if account banned 
     865        { 
     866          packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     867          packet << uint8 (AUTH_BANNED); 
     868          SendPacket (packet); 
     869 
     870          delete banresult; 
     871 
     872          sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); 
     873          return -1; 
     874        } 
     875 
     876      // Check locked state for server 
     877      AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit (); 
     878 
     879      if (allowedAccountType > SEC_PLAYER && security < allowedAccountType) 
     880        { 
     881          WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); 
     882          Packet << uint8 (AUTH_UNAVAILABLE); 
     883 
     884          SendPacket (packet); 
     885 
     886          sLog.outBasic ("WorldSocket::HandleAuthSession: User tryes to login but his security level is not enough"); 
     887          return -1; 
     888        } 
     889 
     890      // Check that Key and account name are the same on client and server 
     891      Sha1Hash sha; 
     892 
     893      uint32 t = 0; 
     894      uint32 seed = m_Seed; 
     895 
     896      sha.UpdateData (account); 
     897      sha.UpdateData ((uint8 *) & t, 4); 
     898      sha.UpdateData ((uint8 *) & clientSeed, 4); 
     899      sha.UpdateData ((uint8 *) & seed, 4); 
     900      sha.UpdateBigNumbers (&K, NULL); 
     901      sha.Finalize (); 
     902 
     903      if (memcmp (sha.GetDigest (), digest, 20)) 
     904        { 
     905          packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     906          packet << uint8 (AUTH_FAILED); 
     907 
     908          SendPacket (packet); 
     909 
     910          sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); 
     911          return -1; 
     912        } 
     913#if defined _NETCODE_FAKE_AUTH 
     914    } 
     915#endif 
     916 
     917  std::string address = this->GetRemoteAddress (); 
     918 
     919  DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", 
     920             account.c_str (), 
     921             address.c_str ()); 
     922 
     923  // Update the last_ip in the database 
     924  // No SQL injection, username escaped. 
     925  loginDatabase.escape_string (address); 
     926 
     927  loginDatabase.PExecute ("UPDATE account " 
     928                          "SET last_ip = '%s' " 
     929                          "WHERE username = '%s'", 
     930                          address.c_str (), 
     931                          safe_account.c_str ()); 
     932 
     933  // TODO protect here probably ? 
     934  // Althought atm the socket is singlethreaded 
     935  ACE_NEW_RETURN (m_Session, WorldSession (id, this, security, tbc, mutetime, locale), -1); 
     936 
     937#if defined _NETCODE_FAKE_AUTH 
     938  if (!dontchechtheacc) 
     939    { 
     940#endif 
     941      this->m_Crypt.SetKey (&K); 
     942      this->m_Crypt.Init (); 
     943#if defined _NETCODE_FAKE_AUTH 
     944    } 
     945#endif 
     946 
     947  // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec 
     948  ACE_OS::sleep (ACE_Time_Value (0, 10000)); 
     949 
     950  // TODO error handling 
     951  sWorld.AddSession (this->m_Session); 
     952 
     953  // Create and send the Addon packet 
     954  if (sAddOnHandler.BuildAddonPacket (&recvPacket, &SendAddonPacked)) 
     955    SendPacket (SendAddonPacked); 
     956 
     957  return 0; 
     958} 
     959 
     960int 
     961WorldSocket::HandlePing (WorldPacket& recvPacket) 
     962{ 
     963  uint32 ping; 
     964  uint32 latency; 
     965 
     966  if (recvPacket.size () < 8) 
     967    { 
     968      sLog.outError ("WorldSocket::_HandlePing wrong packet size"); 
     969      return -1; 
     970    } 
     971 
     972  // Get the ping packet content 
     973  recvPacket >> ping; 
     974  recvPacket >> latency; 
     975 
     976  if (m_LastPingTime == ACE_Time_Value::zero) 
     977    m_LastPingTime = ACE_OS::gettimeofday (); // for 1st ping 
     978  else 
     979    { 
     980      ACE_Time_Value cur_time = ACE_OS::gettimeofday (); 
     981      ACE_Time_Value diff_time (cur_time); 
     982      diff_time -= m_LastPingTime; 
     983      m_LastPingTime = cur_time; 
     984 
     985      if (diff_time < ACE_Time_Value (27)) 
     986        { 
     987          ++m_OverSpeedPings; 
     988 
     989          uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS); 
     990 
     991          if (max_count && m_OverSpeedPings > max_count) 
    185992            { 
    186                 ///- Else, put it in the world session queue for this user (need to be already authenticated) 
    187                 if (_session) 
    188                     _session->QueuePacket(packet); 
    189                 else 
    190                     sLog.outDetail("Received out of place packet with cmdid 0x%.4X", _cmd); 
    191                 break; 
     993              ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     994 
     995              if (m_Session && m_Session->GetSecurity () == SEC_PLAYER) 
     996                { 
     997                  sLog.outError ("WorldSocket::HandlePing: Player kicked for " 
     998                                 "overspeeded pings adress = %s", 
     999                                 GetRemoteAddress ().c_str ()); 
     1000 
     1001                  return -1; 
     1002                } 
    1921003            } 
    1931004        } 
    194     } 
    195 } 
    196  
    197 /// On socket closing 
    198 void WorldSocket::CloseSocket() 
    199 { 
    200     ///- Set CloseAndDelete flag for TcpSocket class 
    201     SetCloseAndDelete(true); 
    202  
    203     ///- Set _session to NULL. Prevent crashes 
    204     _session = NULL; 
    205 } 
    206  
    207 /// On socket deleting 
    208 void WorldSocket::OnDelete() 
    209 { 
    210     ///- Stop sending remaining data through this socket 
    211     if (_session) 
    212     { 
    213         _session->SetSocket(NULL); 
    214         // Session deleted from World session list at socket==0, This is only back reference from socket to session. 
    215         _session = NULL; 
    216     } 
    217  
    218     ///- Remove the socket from the WorldSocketMgr list 
    219     sWorldSocketMgr.RemoveSocket(this); 
    220  
    221     ///- Removes socket from player queue 
    222     sWorld.RemoveQueuedPlayer(this); 
    223 } 
    224  
    225 /// Handle the client authentication packet 
    226 void WorldSocket::_HandleAuthSession(WorldPacket& recvPacket) 
    227 { 
    228     uint8 digest[20]; 
    229     uint32 clientSeed; 
    230     uint32 unk2; 
    231     uint32 BuiltNumberClient; 
    232     uint32 id, security; 
    233     bool tbc = false; 
    234     std::string account; 
    235     Sha1Hash sha1; 
    236     BigNumber v, s, g, N, x, I; 
    237     WorldPacket packet, SendAddonPacked; 
    238  
    239     BigNumber K; 
    240  
    241     SOCKET_CHECK_PACKET_SIZE(recvPacket,4+4+1+4+20); 
    242  
    243     ///- Read the content of the packet 
    244     recvPacket >> BuiltNumberClient;                        // for now no use 
    245     recvPacket >> unk2; 
    246     recvPacket >> account; 
    247  
    248     // recheck size 
    249     SOCKET_CHECK_PACKET_SIZE(recvPacket,4+4+(account.size()+1)+4+20); 
    250  
    251     recvPacket >> clientSeed; 
    252     recvPacket.read(digest, 20); 
    253  
    254     sLog.outDebug("Auth: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str(), clientSeed); 
    255  
    256     ///- Normalize account name 
    257     //utf8ToUpperOnlyLatin(account); -- client already send account in expected form 
    258  
    259     ///- Get the account information from the realmd database 
    260     std::string safe_account = account;                     // Duplicate, else will screw the SHA hash verification below 
    261     loginDatabase.escape_string(safe_account); 
    262     //No SQL injection, username escaped. 
    263     //                                                 0   1        2           3        4       5              6  7  8    9         10 
    264     QueryResult *result = loginDatabase.PQuery("SELECT id, gmlevel, sessionkey, last_ip, locked, sha_pass_hash, v, s, tbc, mutetime, locale FROM account WHERE username = '%s'", safe_account.c_str()); 
    265  
    266     ///- Stop if the account is not found 
    267     if ( !result ) 
    268     { 
    269         packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); 
    270         packet << uint8( AUTH_UNKNOWN_ACCOUNT ); 
    271         SendPacket( &packet ); 
    272         sLog.outDetail( "SOCKET: Sent Auth Response (unknown account)." ); 
    273         return; 
    274     } 
    275  
    276     Field* fields = result->Fetch(); 
    277  
    278     tbc = fields[8].GetUInt8() && sWorld.getConfig(CONFIG_EXPANSION) > 0; 
    279  
    280     N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); 
    281     g.SetDword(7); 
    282     I.SetHexStr(fields[5].GetString()); 
    283  
    284     //In case of leading zeros in the I hash, restore them 
    285     uint8 mDigest[SHA_DIGEST_LENGTH]; 
    286     memset(mDigest,0,SHA_DIGEST_LENGTH); 
    287     if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) 
    288         memcpy(mDigest,I.AsByteArray(),I.GetNumBytes()); 
    289  
    290     std::reverse(mDigest,mDigest+SHA_DIGEST_LENGTH); 
    291  
    292     s.SetHexStr(fields[7].GetString()); 
    293     sha1.UpdateData(s.AsByteArray(), s.GetNumBytes()); 
    294     sha1.UpdateData(mDigest, SHA_DIGEST_LENGTH); 
    295     sha1.Finalize(); 
    296     x.SetBinary(sha1.GetDigest(), sha1.GetLength()); 
    297     v = g.ModExp(x, N); 
    298  
    299     const char* sStr = s.AsHexStr();                        //Must be freed by OPENSSL_free() 
    300     const char* vStr = v.AsHexStr();                        //Must be freed by OPENSSL_free() 
    301     const char* vold = fields[6].GetString(); 
    302     sLog.outDebug("SOCKET: (s,v) check s: %s v_old: %s v_new: %s", sStr, vold, vStr ); 
    303     loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE username = '%s'", safe_account.c_str()); 
    304     if ( !vold || strcmp( vStr, vold ) ) 
    305     { 
    306         packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); 
    307         packet << uint8( AUTH_UNKNOWN_ACCOUNT ); 
    308         SendPacket( &packet ); 
    309         sLog.outDetail( "SOCKET: User not logged."); 
    310         delete result; 
    311         OPENSSL_free((void*)sStr); 
    312         OPENSSL_free((void*)vStr); 
    313         return; 
    314     } 
    315     OPENSSL_free((void*)sStr); 
    316     OPENSSL_free((void*)vStr); 
    317  
    318     ///- Re-check ip locking (same check as in realmd). 
    319     if(fields[4].GetUInt8() == 1)                           // if ip is locked 
    320     { 
    321         if ( strcmp(fields[3].GetString(),GetRemoteAddress().c_str()) ) 
    322         { 
    323             packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); 
    324             packet << uint8( AUTH_FAILED ); 
    325             SendPacket( &packet ); 
    326  
    327             sLog.outDetail( "SOCKET: Sent Auth Response (Account IP differs)." ); 
    328             delete result; 
    329             return; 
    330         } 
    331     } 
    332  
    333     id = fields[0].GetUInt32(); 
    334     security = fields[1].GetUInt16(); 
    335     K.SetHexStr(fields[2].GetString()); 
    336     time_t mutetime = time_t(fields[9].GetUInt64()); 
    337  
    338     LocaleConstant locale = LocaleConstant(fields[10].GetUInt8()); 
    339     if (locale>=MAX_LOCALE) 
    340         locale=LOCALE_enUS; 
    341  
    342     delete result; 
    343  
    344     ///- Re-check account ban (same check as in realmd) /// TO DO: why on earth do 2 checks for same thing? 
    345     QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = '%u' AND active = 1", id); 
    346     if(banresult)                                           // if account banned 
    347     { 
    348         packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); 
    349         packet << uint8( AUTH_BANNED ); 
    350         SendPacket( &packet ); 
    351  
    352         sLog.outDetail( "SOCKET: Sent Auth Response (Account banned)." ); 
    353         delete banresult; 
    354         return; 
    355     } 
    356  
    357     ///- Check locked state for server 
    358     AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); 
    359     if( allowedAccountType > SEC_PLAYER && security < allowedAccountType) 
    360     { 
    361         WorldPacket Packet(SMSG_AUTH_RESPONSE, 1); 
    362         Packet << uint8(AUTH_UNAVAILABLE); 
    363         SendPacket(&Packet); 
    364         return; 
    365     } 
    366  
    367     ///- kick already loaded player with same account (if any) and remove session 
    368     ///- if player is in loading and want to load again, return 
    369     if(!sWorld.RemoveSession(id)) 
    370     { 
    371         return; 
    372     } 
    373  
    374     ///- Check that Key and account name are the same on client and server 
    375     Sha1Hash sha; 
    376  
    377     uint32 t = 0; 
    378     uint32 seed = _seed; 
    379  
    380     sha.UpdateData(account); 
    381     sha.UpdateData((uint8 *)&t, 4); 
    382     sha.UpdateData((uint8 *)&clientSeed, 4); 
    383     sha.UpdateData((uint8 *)&seed, 4); 
    384     sha.UpdateBigNumbers(&K, NULL); 
    385     sha.Finalize(); 
    386  
    387     if (memcmp(sha.GetDigest(), digest, 20)) 
    388     { 
    389         packet.Initialize( SMSG_AUTH_RESPONSE, 1 ); 
    390         packet << uint8( AUTH_FAILED ); 
    391         SendPacket( &packet ); 
    392  
    393         sLog.outDetail( "SOCKET: Sent Auth Response (authentication failed)." ); 
    394         return; 
    395     } 
    396  
    397     ///- Initialize the encryption with the Key 
    398     _crypt.SetKey(&K); 
    399     _crypt.Init(); 
    400  
    401     ///- Send 'Auth is ok' 
    402     packet.Initialize( SMSG_AUTH_RESPONSE, 1+4+1+4+1 ); 
    403     packet << uint8( AUTH_OK ); 
    404     packet << uint32(0);                                    // unknown random value... 
    405     packet << uint8(0);                                     // can be 0 and 2 
    406     packet << uint32(0);                                    // const 0 
    407     packet << uint8(tbc ? 1 : 0);                           // 0 - normal, 1 - TBC, must be set in database manually for each account 
    408     SendPacket(&packet); 
    409  
    410     ///- Create a new WorldSession for the player and add it to the World 
    411     _session = new WorldSession(id, this,security,tbc,mutetime,locale); 
    412     sWorld.AddSession(_session); 
    413  
    414     if(sLog.IsOutDebug())                                   // optimize disabled debug output 
    415     { 
    416         sLog.outDebug( "SOCKET: Client '%s' authenticated successfully.", account.c_str() ); 
    417         sLog.outDebug( "Account: '%s' Logged in from IP %s.", account.c_str(), GetRemoteAddress().c_str()); 
    418     } 
    419  
    420     ///- Update the last_ip in the database 
    421     //No SQL injection, username escaped. 
    422     std::string address = GetRemoteAddress(); 
    423     loginDatabase.escape_string(address); 
    424     loginDatabase.PExecute("UPDATE account SET last_ip = '%s' WHERE username = '%s'",address.c_str(), safe_account.c_str()); 
    425  
    426     // do small delay (10ms) at accepting successful authed connection to prevent dropping packets by client 
    427     // don't must harm anyone (let login ~100 accounts in 1 sec ;) ) 
    428     #ifdef WIN32 
    429     Sleep(10); 
    430     #else 
    431     ZThread::Thread::sleep(10); 
    432     #endif 
    433  
    434     ///- Check that we do not exceed the maximum number of online players in the realm 
    435     uint32 Sessions  = sWorld.GetActiveAndQueuedSessionCount(); 
    436     uint32 pLimit    = sWorld.GetPlayerAmountLimit(); 
    437     uint32 QueueSize = sWorld.GetQueueSize();               //number of players in the queue 
    438     bool   inQueue   = false; 
    439     --Sessions;                                             //so we don't count the user trying to login as a session and queue the socket that we are using 
    440  
    441     if( pLimit >  0 && Sessions >= pLimit && security == SEC_PLAYER ) 
    442     { 
    443         sWorld.AddQueuedPlayer(this); 
    444         SendAuthWaitQue(sWorld.GetQueuePos(this)); 
    445         sWorld.UpdateMaxSessionCounters(); 
    446         sLog.outDetail( "PlayerQueue: %s is in Queue Position (%u).",safe_account.c_str(),++QueueSize); 
    447         inQueue = true; 
    448     } 
    449  
    450     ///- Create and send the Addon packet 
    451     if(sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked)) 
    452         SendPacket(&SendAddonPacked); 
    453  
    454     if(inQueue) 
    455         return; 
    456  
    457     sWorld.UpdateMaxSessionCounters(); 
    458  
    459     // Updates the population 
    460     if (pLimit > 0) 
    461     { 
    462         float popu = sWorld.GetActiveSessionCount();        //updated number of users on the server 
    463         popu /= pLimit; 
    464         popu *= 2; 
    465         loginDatabase.PExecute("UPDATE realmlist SET population = '%f' WHERE id = '%d'",popu,realmID); 
    466         sLog.outDetail( "Server Population (%f).",popu); 
    467     } 
    468  
    469     return; 
    470 } 
    471  
    472 /// Handle the Ping packet 
    473 void WorldSocket::_HandlePing(WorldPacket& recvPacket) 
    474 { 
    475     uint32 ping; 
    476     uint32 latency; 
    477  
    478     CHECK_PACKET_SIZE(recvPacket,8); 
    479  
    480     ///- Get the ping packet content 
    481     recvPacket >> ping; 
    482     recvPacket >> latency; 
    483  
    484     if (_session ) 
    485         _session->SetLatency(latency); 
    486  
    487     ///- check ping speed for players 
    488     if(_session && _session->GetSecurity() == SEC_PLAYER) 
    489     { 
    490         uint32 cur_mstime = getMSTime(); 
    491  
    492         // can overflow and start from 0 
    493         uint32 diff_mstime = getMSTimeDiff(m_LastPingMSTime,cur_mstime); 
    494         m_LastPingMSTime = cur_mstime; 
    495         if(diff_mstime < 27000)                             // should be 30000 (=30 secs), add little tolerance 
    496         { 
    497             ++m_OverSpeedPings; 
    498  
    499             uint32 max_count = sWorld.getConfig(CONFIG_MAX_OVERSPEED_PINGS); 
    500             if(max_count && m_OverSpeedPings > max_count) 
     1005      else 
     1006        m_OverSpeedPings = 0; 
     1007    } 
     1008 
     1009  // critical section 
     1010  { 
     1011    ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     1012 
     1013    if (m_Session) 
     1014      m_Session->SetLatency (latency); 
     1015    else 
     1016      { 
     1017        sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, " 
     1018                       "but is not authenticated or got recently kicked," 
     1019                       " adress = %s", 
     1020                       this->GetRemoteAddress ().c_str ()); 
     1021        return -1; 
     1022      } 
     1023  } 
     1024 
     1025  WorldPacket packet (SMSG_PONG, 4); 
     1026  packet << ping; 
     1027  return this->SendPacket (packet); 
     1028} 
     1029 
     1030int 
     1031WorldSocket::iSendPacket (const WorldPacket& pct) 
     1032{ 
     1033  if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader)) 
     1034    { 
     1035      errno = ENOBUFS; 
     1036      return -1; 
     1037    } 
     1038 
     1039  ServerPktHeader header; 
     1040 
     1041  header.cmd = pct.GetOpcode (); 
     1042 
     1043#if ACE_BYTE_ORDER == ACE_BIG_ENDIAN 
     1044  header.cmd = ACE_SWAP_WORD (header.cmd) 
     1045#endif 
     1046           
     1047  header.size = (uint16) pct.size () + 2; 
     1048  header.size = ACE_HTONS (header.size); 
     1049 
     1050  m_Crypt.EncryptSend ((uint8*) & header, sizeof (header)); 
     1051 
     1052  if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1) 
     1053    ACE_ASSERT (false); 
     1054 
     1055  if (!pct.empty ()) 
     1056    if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1) 
     1057      ACE_ASSERT (false); 
     1058 
     1059  return 0; 
     1060} 
     1061 
     1062bool 
     1063WorldSocket::iFlushPacketQueue () 
     1064{ 
     1065  WorldPacket *pct; 
     1066  bool haveone = false; 
     1067 
     1068  while (m_PacketQueue.dequeue_head (pct) == 0) 
     1069    { 
     1070      if (iSendPacket (*pct) == -1) 
     1071        { 
     1072          if (m_PacketQueue.enqueue_head (pct) == -1) 
    5011073            { 
    502                 sLog.outBasic("Player %s from account id %u kicked for overspeed ping packets from client (non-playable connection lags or cheating) ",_session->GetPlayerName(),_session->GetAccountId()); 
    503                 _session->KickPlayer(); 
    504                 return; 
     1074              delete pct; 
     1075              sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head"); 
     1076              return false; 
    5051077            } 
    506         } 
    507         else 
    508             m_OverSpeedPings = 0; 
    509  
    510     } 
    511  
    512     ///- And put the pong answer in the to-be-sent queue 
    513     WorldPacket packet( SMSG_PONG, 4 ); 
    514     packet << ping; 
    515     SendPacket(&packet); 
    516  
    517     return; 
    518 } 
    519  
    520 /// Handle the update order for the socket 
    521 void WorldSocket::SendSinglePacket() 
    522 { 
    523     WorldPacket *packet; 
    524     ServerPktHeader hdr; 
    525  
    526     ///- If we have packet to send 
    527     if (!_sendQueue.empty()) 
    528     { 
    529         packet = _sendQueue.next(); 
    530  
    531         hdr.size = ntohs((uint16)packet->size() + 2); 
    532         hdr.cmd = packet->GetOpcode(); 
    533  
    534         if( sWorldLog.LogWorld() ) 
    535         { 
    536             sWorldLog.Log("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
    537                 (uint32)GetSocket(), 
    538                 packet->size(), 
    539                 LookupOpcodeName(packet->GetOpcode()), 
    540                 packet->GetOpcode()); 
    541  
    542             uint32 p = 0; 
    543             while (p < packet->size()) 
    544             { 
    545                 for (uint32 j = 0; j < 16 && p < packet->size(); j++) 
    546                     sWorldLog.Log("%.2X ", (*packet)[p++]); 
    547  
    548                 sWorldLog.Log("\n"); 
    549             } 
    550  
    551             sWorldLog.Log("\n\n"); 
    552         } 
    553  
    554         ///- Encrypt (if needed) the header 
    555         _crypt.EncryptSend((uint8*)&hdr, 4); 
    556  
    557         ///- Send the header and body to the client 
    558         TcpSocket::SendBuf((char*)&hdr, 4); 
    559         if(!packet->empty()) TcpSocket::SendBuf((char*)packet->contents(), packet->size()); 
    560  
    561         delete packet; 
    562     } 
    563 } 
    564  
    565 void WorldSocket::Update(time_t diff) 
    566 { 
    567     const uint32 SEND_PACKETS_MAX = 100; 
    568     const uint32 SEND_BUFFER_SIZE = 1024; 
    569  
    570     uint8 sendBuffer[SEND_BUFFER_SIZE]; 
    571  
    572     while (!_sendQueue.empty()) 
    573     { 
    574         bool haveBigPacket = false; 
    575         uint32 bufferSize = 0; 
    576  
    577         ///- While we have packets to send 
    578         for (uint32 packetCount = 0; (packetCount < SEND_PACKETS_MAX) && !_sendQueue.empty(); packetCount++) 
    579         { 
    580             ServerPktHeader *hdr = (ServerPktHeader*)&sendBuffer[bufferSize]; 
    581  
    582             // check merge possibility. 
    583             WorldPacket *front = _sendQueue.front(); 
    584             uint32 packetSize = front->size(); 
    585  
    586             if ((sizeof(*hdr) + packetSize) > SEND_BUFFER_SIZE) 
    587             { 
    588                 haveBigPacket = true; 
    589                 break; 
    590             } 
    591  
    592             if ((bufferSize + sizeof(*hdr) + packetSize) > sizeof(sendBuffer)) 
    593                 break; 
    594  
    595             // can be merged 
    596             WorldPacket *packet = _sendQueue.next(); 
    597  
    598             hdr->size = ntohs((uint16)packetSize + 2); 
    599             hdr->cmd = packet->GetOpcode(); 
    600  
    601             if( sWorldLog.LogWorld() ) 
    602             { 
    603                 sWorldLog.Log("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
    604                     (uint32)GetSocket(), 
    605                     packetSize, 
    606                     LookupOpcodeName(packet->GetOpcode()), 
    607                     packet->GetOpcode()); 
    608  
    609                 uint32 p = 0; 
    610                 while (p < packetSize) 
    611                 { 
    612                     for (uint32 j = 0; j < 16 && p < packetSize; j++) 
    613                         sWorldLog.Log("%.2X ", (*packet)[p++]); 
    614  
    615                     sWorldLog.Log("\n"); 
    616                 } 
    617  
    618                 sWorldLog.Log("\n\n"); 
    619             } 
    620  
    621             ///- Encrypt (if needed) the header 
    622             _crypt.EncryptSend((uint8*)hdr, sizeof(*hdr)); 
    623             bufferSize += sizeof(*hdr); 
    624  
    625             if (packetSize) 
    626             { 
    627                 memcpy(&sendBuffer[bufferSize], packet->contents(), packetSize); 
    628                 bufferSize += packetSize; 
    629             } 
    630  
    631             ///- Send the header and body to the client 
    632             delete packet; 
    633         } 
    634  
    635         // send merged packets 
    636         if (bufferSize) TcpSocket::SendBuf((char*)sendBuffer, bufferSize); 
    637         // send too big non-merged packet 
    638         if (haveBigPacket) SendSinglePacket(); 
    639     } 
    640 } 
    641  
    642 /// Handle the authentication waiting queue (to be completed) 
    643 void WorldSocket::SendAuthWaitQue(uint32 position) 
    644 { 
    645     if(position == 0) 
    646     { 
    647         WorldPacket packet( SMSG_AUTH_RESPONSE, 1 ); 
    648         packet << uint8( AUTH_OK ); 
    649         SendPacket(&packet); 
    650     } 
    651     else 
    652     { 
    653         WorldPacket packet( SMSG_AUTH_RESPONSE, 5 ); 
    654         packet << uint8( AUTH_WAIT_QUEUE ); 
    655         packet << uint32 (position);                        //amount of players in queue 
    656         SendPacket(&packet); 
    657     } 
    658 } 
    659  
    660 void WorldSocket::SizeError(WorldPacket const& packet, uint32 size) const 
    661 { 
    662     sLog.outError("Client send packet %s (%u) with size %u but expected %u (attempt crash server?), skipped", 
    663         LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size); 
    664 } 
     1078 
     1079          break; 
     1080        } 
     1081      else 
     1082        { 
     1083          haveone = true; 
     1084          delete pct; 
     1085        } 
     1086    } 
     1087 
     1088  return haveone; 
     1089} 
  • trunk/src/game/WorldSocket.h

    r2 r6  
    1 /* 
     1/*  
    22 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> 
    33 * 
     
    1717 */ 
    1818 
    19 /// \addtogroup u2w 
    20 /// @{ 
    21 /// \file 
    22  
    23 #ifndef __WORLDSOCKET_H 
    24 #define __WORLDSOCKET_H 
    25  
    26 #include "sockets/TcpSocket.h" 
    27 #include "Auth/AuthCrypt.h" 
    28  
    29 enum ResponseCodes 
     19/** \addtogroup u2w User to World Communication 
     20 * @{ 
     21 * \file WorldSocket.h 
     22 * \author Derex <derex101@gmail.com> 
     23 */ 
     24 
     25#ifndef _WORLDSOCKET_H 
     26#define _WORLDSOCKET_H 
     27 
     28#include <ace/Basic_Types.h> 
     29#include <ace/Synch_Traits.h> 
     30#include <ace/Svc_Handler.h> 
     31#include <ace/SOCK_Stream.h> 
     32#include <ace/SOCK_Acceptor.h> 
     33#include <ace/Acceptor.h> 
     34#include <ace/Thread_Mutex.h> 
     35#include <ace/Guard_T.h> 
     36#include <ace/Unbounded_Queue.h> 
     37#include <ace/Message_Block.h> 
     38 
     39#if !defined (ACE_LACKS_PRAGMA_ONCE) 
     40#pragma once 
     41#endif /* ACE_LACKS_PRAGMA_ONCE */ 
     42 
     43#include "Common.h" 
     44#include "Auth/AuthCrypt.h"  
     45 
     46class ACE_Message_Block; 
     47class WorldPacket; 
     48class WorldSession; 
     49 
     50/// Handler that can communicate over stream sockets. 
     51typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> WorldHandler; 
     52 
     53/** 
     54 * WorldSocket. 
     55 *  
     56 * This class is responsible for the comunication with  
     57 * remote clients. 
     58 * Most methods return -1 on failure.  
     59 * The class uses refferece counting. 
     60 * 
     61 * For output the class uses one buffer (64K usually) and  
     62 * a queue where it stores packet if there is no place on  
     63 * the queue. The reason this is done, is because the server  
     64 * does realy a lot of small-size writes to it, and it doesn't  
     65 * scale well to allocate memory for every. When something is  
     66 * writen to the output buffer the socket is not immideately  
     67 * activated for output (again for the same reason), there  
     68 * is 10ms celling (thats why there is Update() method).  
     69 * This concept is simmilar to TCP_CORK, but TCP_CORK  
     70 * usses 200ms celling. As result overhead generated by  
     71 * sending packets from "producer" threads is minimal,  
     72 * and doing a lot of writes with small size is tollerated. 
     73 *  
     74 * The calls to Upate () method are managed by WorldSocketMgr 
     75 * and ReactorRunnable. 
     76 *  
     77 * For input ,the class uses one 1024 bytes buffer on stack  
     78 * to which it does recv() calls. And then recieved data is  
     79 * distributed where its needed. 1024 matches pritey well the  
     80 * traffic generated by client for now. 
     81 *   
     82 * The input/output do speculative reads/writes (AKA it tryes  
     83 * to read all data avaible in the kernel buffer or tryes to  
     84 * write everything avaible in userspace buffer),  
     85 * which is ok for using with Level and Edge Trigered IO  
     86 * notification. 
     87 *  
     88 */ 
     89class WorldSocket : protected WorldHandler 
    3090{ 
    31     RESPONSE_SUCCESS                                       = 0x00, 
    32     RESPONSE_FAILURE                                       = 0x01, 
    33     RESPONSE_CANCELLED                                     = 0x02, 
    34     RESPONSE_DISCONNECTED                                  = 0x03, 
    35     RESPONSE_FAILED_TO_CONNECT                             = 0x04, 
    36     RESPONSE_CONNECTED                                     = 0x05, 
    37     RESPONSE_VERSION_MISMATCH                              = 0x06, 
    38  
    39     CSTATUS_CONNECTING                                     = 0x07, 
    40     CSTATUS_NEGOTIATING_SECURITY                           = 0x08, 
    41     CSTATUS_NEGOTIATION_COMPLETE                           = 0x09, 
    42     CSTATUS_NEGOTIATION_FAILED                             = 0x0A, 
    43     CSTATUS_AUTHENTICATING                                 = 0x0B, 
    44  
    45     AUTH_OK                                                = 0x0C, 
    46     AUTH_FAILED                                            = 0x0D, 
    47     AUTH_REJECT                                            = 0x0E, 
    48     AUTH_BAD_SERVER_PROOF                                  = 0x0F, 
    49     AUTH_UNAVAILABLE                                       = 0x10, 
    50     AUTH_SYSTEM_ERROR                                      = 0x11, 
    51     AUTH_BILLING_ERROR                                     = 0x12, 
    52     AUTH_BILLING_EXPIRED                                   = 0x13, 
    53     AUTH_VERSION_MISMATCH                                  = 0x14, 
    54     AUTH_UNKNOWN_ACCOUNT                                   = 0x15, 
    55     AUTH_INCORRECT_PASSWORD                                = 0x16, 
    56     AUTH_SESSION_EXPIRED                                   = 0x17, 
    57     AUTH_SERVER_SHUTTING_DOWN                              = 0x18, 
    58     AUTH_ALREADY_LOGGING_IN                                = 0x19, 
    59     AUTH_LOGIN_SERVER_NOT_FOUND                            = 0x1A, 
    60     AUTH_WAIT_QUEUE                                        = 0x1B, 
    61     AUTH_BANNED                                            = 0x1C, 
    62     AUTH_ALREADY_ONLINE                                    = 0x1D, 
    63     AUTH_NO_TIME                                           = 0x1E, 
    64     AUTH_DB_BUSY                                           = 0x1F, 
    65     AUTH_SUSPENDED                                         = 0x20, 
    66     AUTH_PARENTAL_CONTROL                                  = 0x21, 
    67     AUTH_LOCKED_ENFORCED                                   = 0x22, 
    68  
    69     REALM_LIST_IN_PROGRESS                                 = 0x23, 
    70     REALM_LIST_SUCCESS                                     = 0x24, 
    71     REALM_LIST_FAILED                                      = 0x25, 
    72     REALM_LIST_INVALID                                     = 0x26, 
    73     REALM_LIST_REALM_NOT_FOUND                             = 0x27, 
    74  
    75     ACCOUNT_CREATE_IN_PROGRESS                             = 0x28, 
    76     ACCOUNT_CREATE_SUCCESS                                 = 0x29, 
    77     ACCOUNT_CREATE_FAILED                                  = 0x2A, 
    78  
    79     CHAR_LIST_RETRIEVING                                   = 0x2B, 
    80     CHAR_LIST_RETRIEVED                                    = 0x2C, 
    81     CHAR_LIST_FAILED                                       = 0x2D, 
    82  
    83     CHAR_CREATE_IN_PROGRESS                                = 0x2E, 
    84     CHAR_CREATE_SUCCESS                                    = 0x2F, 
    85     CHAR_CREATE_ERROR                                      = 0x30, 
    86     CHAR_CREATE_FAILED                                     = 0x31, 
    87     CHAR_CREATE_NAME_IN_USE                                = 0x32, 
    88     CHAR_CREATE_DISABLED                                   = 0x33, 
    89     CHAR_CREATE_PVP_TEAMS_VIOLATION                        = 0x34, 
    90     CHAR_CREATE_SERVER_LIMIT                               = 0x35, 
    91     CHAR_CREATE_ACCOUNT_LIMIT                              = 0x36, 
    92     CHAR_CREATE_SERVER_QUEUE                               = 0x37, 
    93     CHAR_CREATE_ONLY_EXISTING                              = 0x38, 
    94     CHAR_CREATE_EXPANSION                                  = 0x39, 
    95  
    96     CHAR_DELETE_IN_PROGRESS                                = 0x3A, 
    97     CHAR_DELETE_SUCCESS                                    = 0x3B, 
    98     CHAR_DELETE_FAILED                                     = 0x3C, 
    99     CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER                 = 0x3D, 
    100     CHAR_DELETE_FAILED_GUILD_LEADER                        = 0x3E, 
    101     CHAR_DELETE_FAILED_ARENA_CAPTAIN                       = 0x3F, 
    102  
    103     CHAR_LOGIN_IN_PROGRESS                                 = 0x40, 
    104     CHAR_LOGIN_SUCCESS                                     = 0x41, 
    105     CHAR_LOGIN_NO_WORLD                                    = 0x42, 
    106     CHAR_LOGIN_DUPLICATE_CHARACTER                         = 0x43, 
    107     CHAR_LOGIN_NO_INSTANCES                                = 0x44, 
    108     CHAR_LOGIN_FAILED                                      = 0x45, 
    109     CHAR_LOGIN_DISABLED                                    = 0x46, 
    110     CHAR_LOGIN_NO_CHARACTER                                = 0x47, 
    111     CHAR_LOGIN_LOCKED_FOR_TRANSFER                         = 0x48, 
    112     CHAR_LOGIN_LOCKED_BY_BILLING                           = 0x49, 
    113  
    114     CHAR_NAME_SUCCESS                                      = 0x4A, 
    115     CHAR_NAME_FAILURE                                      = 0x4B, 
    116     CHAR_NAME_NO_NAME                                      = 0x4C, 
    117     CHAR_NAME_TOO_SHORT                                    = 0x4D, 
    118     CHAR_NAME_TOO_LONG                                     = 0x4E, 
    119     CHAR_NAME_INVALID_CHARACTER                            = 0x4F, 
    120     CHAR_NAME_MIXED_LANGUAGES                              = 0x50, 
    121     CHAR_NAME_PROFANE                                      = 0x51, 
    122     CHAR_NAME_RESERVED                                     = 0x52, 
    123     CHAR_NAME_INVALID_APOSTROPHE                           = 0x53, 
    124     CHAR_NAME_MULTIPLE_APOSTROPHES                         = 0x54, 
    125     CHAR_NAME_THREE_CONSECUTIVE                            = 0x55, 
    126     CHAR_NAME_INVALID_SPACE                                = 0x56, 
    127     CHAR_NAME_CONSECUTIVE_SPACES                           = 0x57, 
    128     CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS        = 0x58, 
    129     CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59, 
    130     CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME            = 0x5A, 
     91public: 
     92  /// Declare some friends 
     93  friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >; 
     94  friend class WorldSocketMgr; 
     95  friend class ReactorRunnable; 
     96 
     97  /// Declare the acceptor for this class 
     98  typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor; 
     99 
     100  /// Mutex type used for various syncronizations. 
     101  typedef ACE_Thread_Mutex LockType; 
     102  typedef ACE_Guard<LockType> GuardType; 
     103 
     104  /// Queue for storing packets for which there is no space. 
     105  typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT; 
     106 
     107  /// Check if socket is closed. 
     108  bool IsClosed (void) const; 
     109 
     110  /// Close the socket. 
     111  void CloseSocket (void); 
     112 
     113  /// Get address of connected peer. 
     114  const std::string& GetRemoteAddress (void) const; 
     115 
     116  /// Send A packet on the socket, this function is reentrant. 
     117  /// @param pct packet to send 
     118  /// @return -1 of failure 
     119  int SendPacket (const WorldPacket& pct); 
     120 
     121  /// Add refference to this object. 
     122  long AddReference (void); 
     123 
     124  /// Remove refference to this object. 
     125  long RemoveReference (void); 
     126 
     127protected: 
     128  /// things called by ACE framework. 
     129  WorldSocket (void); 
     130  virtual ~WorldSocket (void); 
     131 
     132  /// Called on open ,the void* is the acceptor. 
     133  virtual int open (void *); 
     134 
     135  /// Called on failures inside of the acceptor, don't call from your code. 
     136  virtual int close (int); 
     137 
     138  /// Called when we can read from the socket. 
     139  virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); 
     140 
     141  /// Called when the socket can write. 
     142  virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE); 
     143 
     144  /// Called when connection is closed or error happens. 
     145  virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, 
     146                            ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); 
     147 
     148  /// Called by WorldSocketMgr/ReactorRunnable. 
     149  int Update (void); 
     150 
     151private: 
     152  /// Helper functions for processing incoming data. 
     153  int handle_input_header (void); 
     154  int handle_input_payload (void); 
     155  int handle_input_missing_data (void); 
     156 
     157  /// Help functions to mark/unmark the socket for output. 
     158  /// @param g the guard is for m_OutBufferLock, the function will release it 
     159  int cancel_wakeup_output (GuardType& g); 
     160  int schedule_wakeup_output (GuardType& g); 
     161 
     162  /// process one incoming packet. 
     163  /// @param new_pct received packet ,note that you need to delete it.  
     164  int ProcessIncoming (WorldPacket* new_pct); 
     165 
     166  /// Called by ProcessIncoming() on CMSG_AUTH_SESSION. 
     167  int HandleAuthSession (WorldPacket& recvPacket); 
     168 
     169  /// Called by ProcessIncoming() on CMSG_PING. 
     170  int HandlePing (WorldPacket& recvPacket); 
     171 
     172  /// Try to write WorldPacket to m_OutBuffer ,return -1 if no space 
     173  /// Need to be called with m_OutBufferLock lock held 
     174  int iSendPacket (const WorldPacket& pct); 
     175 
     176  /// Flush m_PacketQueue if there are packets in it 
     177  /// Need to be called with m_OutBufferLock lock held 
     178  /// @return true if it wrote to the buffer ( AKA you need  
     179  /// to mark the socket for output ). 
     180  bool iFlushPacketQueue (); 
     181 
     182private: 
     183  /// Time in which the last ping was received 
     184  ACE_Time_Value m_LastPingTime; 
     185   
     186  /// Keep track of overspeed pings ,to prevent ping flood. 
     187  uint32 m_OverSpeedPings; 
     188 
     189  /// Address of the remote peer 
     190  std::string m_Address; 
     191 
     192  /// Class used for managing encryption of the headers 
     193  AuthCrypt m_Crypt; 
     194 
     195  /// Mutex lock to protect m_Session 
     196  LockType m_SessionLock; 
     197 
     198  /// Session to which recieved packets are routed 
     199  WorldSession* m_Session; 
     200 
     201  /// here are stored the fragmens of the recieved data 
     202  WorldPacket* m_RecvWPct; 
     203 
     204  /// This block actually refers to m_RecvWPct contents, 
     205  /// which alows easy and safe writing to it.  
     206  /// It wont free memory when its deleted. m_RecvWPct takes care of freeing. 
     207  ACE_Message_Block m_RecvPct; 
     208 
     209  /// Fragment of the recieved header. 
     210  ACE_Message_Block m_Header; 
     211 
     212  /// Mutex for protecting otuput related data. 
     213  LockType m_OutBufferLock; 
     214 
     215  /// Buffer used for writing output. 
     216  ACE_Message_Block *m_OutBuffer; 
     217 
     218  /// Size of the m_OutBuffer. 
     219  size_t m_OutBufferSize; 
     220 
     221  /// Here are stored packets for which there was no space on m_OutBuffer, 
     222  /// this alows not-to kick player if its buffer is overflowed. 
     223  PacketQueueT m_PacketQueue; 
     224 
     225  /// True if the socket is registered with the reactor for output 
     226  bool m_OutActive; 
     227 
     228  uint32 m_Seed; 
    131229}; 
    132230 
    133 class WorldPacket; 
    134 class SocketHandler; 
    135 class WorldSession; 
    136  
    137 /// Handle connection with the client software 
    138 class WorldSocket : public TcpSocket 
    139 { 
    140     public: 
    141         WorldSocket(ISocketHandler&); 
    142         ~WorldSocket(); 
    143  
    144         void SendPacket(WorldPacket const* packet); 
    145         void CloseSocket(); 
    146  
    147         void OnAccept(); 
    148         void OnRead(); 
    149         void OnDelete(); 
    150  
    151         void Update(time_t diff); 
    152         // Player Queue 
    153         void SendAuthWaitQue(uint32 position); 
    154  
    155         WorldSession* GetSession() const { return _session; } 
    156     protected: 
    157         void SendSinglePacket(); 
    158  
    159     protected: 
    160         void _HandleAuthSession(WorldPacket& recvPacket); 
    161         void _HandlePing(WorldPacket& recvPacket); 
    162  
    163     private: 
    164         AuthCrypt _crypt; 
    165         uint32 _seed; 
    166         uint32 _cmd; 
    167         uint16 _remaining; 
    168         WorldSession* _session; 
    169  
    170         ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> _sendQueue; 
    171  
    172         uint32 m_LastPingMSTime; 
    173         uint32 m_OverSpeedPings; 
    174  
    175         // internal checks 
    176         void SizeError(WorldPacket const& packet, uint32 size) const; 
    177 }; 
    178 #endif 
     231#endif  /* _WORLDSOCKET_H */ 
     232 
    179233/// @} 
  • trunk/src/game/WorldSocketMgr.cpp

    r2 r6  
    1717 */ 
    1818 
    19 /** \file 
    20     \ingroup u2w 
    21 */ 
    22  
     19/** \file WorldSocketMgr.cpp 
     20 *  \ingroup u2w 
     21 *  \author Derex <derex101@gmail.com> 
     22 */ 
     23 
     24#include "WorldSocketMgr.h" 
     25 
     26#include <ace/ACE.h> 
     27#include <ace/Log_Msg.h> 
     28#include <ace/Reactor.h> 
     29#include <ace/Reactor_Impl.h> 
     30#include <ace/TP_Reactor.h> 
     31#include <ace/Dev_Poll_Reactor.h> 
     32#include <ace/Guard_T.h> 
     33#include <ace/Atomic_Op.h> 
     34#include <ace/os_include/arpa/os_inet.h> 
     35#include <ace/os_include/netinet/os_tcp.h> 
     36#include <ace/os_include/sys/os_types.h> 
     37#include <ace/os_include/sys/os_socket.h> 
     38 
     39#include <set> 
     40 
     41#include "Log.h" 
    2342#include "Common.h" 
     43#include "Config/ConfigEnv.h" 
     44#include "Database/DatabaseEnv.h" 
    2445#include "WorldSocket.h" 
    25 #include "WorldSocketMgr.h" 
    26 #include "Policies/SingletonImp.h" 
    27  
    28 INSTANTIATE_SINGLETON_1( WorldSocketMgr ); 
    29  
    30 /// WorldSocketMgr constructor 
    31 WorldSocketMgr::WorldSocketMgr() 
    32 { 
    33 } 
    34  
    35 /// Add a WorldSocket to the set 
    36 void WorldSocketMgr::AddSocket(WorldSocket *s) 
    37 { 
    38     m_sockets.insert(s); 
    39 } 
    40  
    41 /// Remove a WorldSocket to the set 
    42 void WorldSocketMgr::RemoveSocket(WorldSocket *s) 
    43 { 
    44     m_sockets.erase(s); 
    45 } 
    46  
    47 /// Triggers an 'update' to all sockets in the set 
    48 void WorldSocketMgr::Update(time_t diff) 
    49 { 
    50     SocketSet::iterator i; 
    51     for(i = m_sockets.begin(); i != m_sockets.end(); i++) 
    52     { 
    53         (*i)->Update(diff); 
    54     } 
    55 } 
     46 
     47/**  
     48 * This is a helper class to WorldSocketMgr ,that manages  
     49 * network threads, and assigning connections from acceptor thread 
     50 * to other network threads 
     51 */ 
     52class ReactorRunnable : protected ACE_Task_Base 
     53{ 
     54public: 
     55 
     56  ReactorRunnable () : 
     57  m_ThreadId (-1), 
     58  m_Connections (0), 
     59  m_Reactor (0) 
     60  { 
     61    ACE_Reactor_Impl* imp = 0; 
     62 
     63#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL) 
     64    imp = new ACE_Dev_Poll_Reactor (); 
     65 
     66    imp->max_notify_iterations (128); 
     67    imp->restart (1); 
     68#else 
     69    imp = new ACE_TP_Reactor (); 
     70    imp->max_notify_iterations (128); 
     71#endif 
     72 
     73    m_Reactor = new ACE_Reactor (imp, 1); 
     74  } 
     75 
     76  virtual 
     77  ~ReactorRunnable () 
     78  { 
     79    this->Stop (); 
     80    this->Wait (); 
     81 
     82    if (m_Reactor) 
     83      delete m_Reactor; 
     84  } 
     85 
     86  void 
     87  Stop () 
     88  { 
     89    m_Reactor->end_reactor_event_loop (); 
     90  } 
     91 
     92  int 
     93  Start () 
     94  { 
     95    if (m_ThreadId != -1) 
     96      return -1; 
     97 
     98    return (m_ThreadId = this->activate ()); 
     99  } 
     100 
     101  void 
     102  Wait () 
     103  { 
     104    ACE_Task_Base::wait (); 
     105  } 
     106 
     107  long 
     108  Connections () 
     109  { 
     110    return static_cast<long> (m_Connections.value ()); 
     111  } 
     112 
     113  int 
     114  AddSocket (WorldSocket* sock) 
     115  { 
     116    ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, m_NewSockets_Lock, -1); 
     117 
     118    ++m_Connections; 
     119    sock->AddReference(); 
     120    sock->reactor (m_Reactor); 
     121    m_NewSockets.insert (sock); 
     122 
     123    return 0; 
     124  } 
     125   
     126  ACE_Reactor* GetReactor () 
     127  { 
     128    return m_Reactor; 
     129  } 
     130   
     131protected: 
     132   
     133  void 
     134  AddNewSockets () 
     135  { 
     136    ACE_GUARD (ACE_Thread_Mutex, Guard, m_NewSockets_Lock); 
     137 
     138    if (m_NewSockets.empty ()) 
     139      return; 
     140 
     141    for (SocketSet::iterator i = m_NewSockets.begin (); i != m_NewSockets.end (); ++i) 
     142      { 
     143        WorldSocket* sock = (*i); 
     144 
     145        if (sock->IsClosed ()) 
     146          { 
     147            sock->RemoveReference (); 
     148            --m_Connections; 
     149          } 
     150        else 
     151          m_Sockets.insert (sock); 
     152      } 
     153 
     154    m_NewSockets.clear (); 
     155  } 
     156 
     157  virtual int 
     158  svc (void) 
     159  { 
     160    DEBUG_LOG ("Network Thread Starting"); 
     161 
     162    WorldDatabase.ThreadStart (); 
     163 
     164    ACE_ASSERT (m_Reactor); 
     165 
     166    SocketSet::iterator i, t; 
     167 
     168    while (!m_Reactor->reactor_event_loop_done ()) 
     169      { 
     170        // dont be too smart to move this outside the loop  
     171        // the run_reactor_event_loop will modify interval 
     172        ACE_Time_Value interval (0, 10000); 
     173 
     174        if (m_Reactor->run_reactor_event_loop (interval) == -1) 
     175          break; 
     176 
     177        AddNewSockets (); 
     178 
     179        for (i = m_Sockets.begin (); i != m_Sockets.end ();) 
     180          { 
     181            if ((*i)->Update () == -1) 
     182              { 
     183                t = i; 
     184                i++; 
     185                (*t)->CloseSocket (); 
     186                (*t)->RemoveReference (); 
     187                --m_Connections; 
     188                m_Sockets.erase (t); 
     189              } 
     190            else 
     191              i++; 
     192          } 
     193      } 
     194 
     195    WorldDatabase.ThreadEnd (); 
     196 
     197    DEBUG_LOG ("Network Thread Exitting"); 
     198 
     199    return 0; 
     200  } 
     201 
     202private: 
     203  typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> AtomicInt; 
     204  typedef std::set<WorldSocket*> SocketSet; 
     205 
     206  ACE_Reactor* m_Reactor; 
     207  AtomicInt m_Connections; 
     208  int m_ThreadId; 
     209 
     210  SocketSet m_Sockets; 
     211 
     212  SocketSet m_NewSockets; 
     213  ACE_Thread_Mutex m_NewSockets_Lock; 
     214}; 
     215 
     216 
     217 
     218WorldSocketMgr::WorldSocketMgr () : 
     219m_NetThreadsCount (0), 
     220m_NetThreads (0), 
     221m_SockOutKBuff (-1), 
     222m_SockOutUBuff (65536), 
     223m_UseNoDelay (true), 
     224m_Acceptor (0) {} 
     225 
     226WorldSocketMgr::~WorldSocketMgr () 
     227{ 
     228  if (m_NetThreads) 
     229    delete [] m_NetThreads; 
     230   
     231  if(m_Acceptor) 
     232    delete m_Acceptor; 
     233} 
     234 
     235int 
     236WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) 
     237{ 
     238  m_UseNoDelay = sConfig.GetBoolDefault ("Network.TcpNodelay", true); 
     239 
     240  int num_threads = sConfig.GetIntDefault ("Network.Threads", 1); 
     241 
     242  if (num_threads <= 0) 
     243    { 
     244      sLog.outError ("Network.Threads is wrong in your config file"); 
     245      return -1; 
     246    } 
     247 
     248  m_NetThreadsCount = static_cast<size_t> (num_threads + 1); 
     249 
     250  m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; 
     251 
     252  sLog.outBasic ("Max alowed socket connections %d",ACE::max_handles ()); 
     253 
     254  m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); // -1 means use default 
     255 
     256  m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536); 
     257 
     258  if ( m_SockOutUBuff <= 0 ) 
     259    { 
     260      sLog.outError ("Network.OutUBuff is wrong in your config file"); 
     261      return -1; 
     262    } 
     263 
     264  WorldSocket::Acceptor *acc = new WorldSocket::Acceptor; 
     265  m_Acceptor = acc; 
     266 
     267  ACE_INET_Addr listen_addr (port, address); 
     268 
     269  if (acc->open (listen_addr, m_NetThreads[0].GetReactor (), ACE_NONBLOCK) == -1) 
     270    { 
     271      sLog.outError ("Failed to open acceptor ,check if the port is free"); 
     272      return -1; 
     273    } 
     274 
     275  for (size_t i = 0; i < m_NetThreadsCount; ++i) 
     276    m_NetThreads[i].Start (); 
     277 
     278  return 0; 
     279} 
     280 
     281int 
     282WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address) 
     283{ 
     284  if (!sLog.IsOutDebug ()) 
     285    ACE_Log_Msg::instance ()->priority_mask (LM_ERROR, ACE_Log_Msg::PROCESS); 
     286 
     287  if (this->StartReactiveIO (port, address) == -1) 
     288    return -1; 
     289 
     290  return 0; 
     291} 
     292 
     293void 
     294WorldSocketMgr::StopNetwork () 
     295{ 
     296  if (m_Acceptor) 
     297    { 
     298      WorldSocket::Acceptor* acc = dynamic_cast<WorldSocket::Acceptor*> (m_Acceptor); 
     299 
     300      if (acc) 
     301        acc->close (); 
     302    } 
     303 
     304  if (m_NetThreadsCount != 0) 
     305    { 
     306      for (size_t i = 0; i < m_NetThreadsCount; ++i) 
     307        m_NetThreads[i].Stop (); 
     308    } 
     309   
     310  this->Wait (); 
     311} 
     312 
     313void  
     314WorldSocketMgr::Wait () 
     315{ 
     316  if (m_NetThreadsCount != 0) 
     317    { 
     318      for (size_t i = 0; i < m_NetThreadsCount; ++i) 
     319        m_NetThreads[i].Wait (); 
     320    } 
     321} 
     322 
     323int 
     324WorldSocketMgr::OnSocketOpen (WorldSocket* sock) 
     325{ 
     326  // set some options here 
     327  if (m_SockOutKBuff >= 0) 
     328    if (sock->peer ().set_option (SOL_SOCKET, 
     329                                  SO_SNDBUF, 
     330                                  (void*) & m_SockOutKBuff, 
     331                                  sizeof (int)) == -1 && errno != ENOTSUP) 
     332      { 
     333        sLog.outError ("WorldSocketMgr::OnSocketOpen set_option SO_SNDBUF"); 
     334        return -1; 
     335      } 
     336 
     337  static const int ndoption = 1; 
     338 
     339  // Set TCP_NODELAY. 
     340  if (m_UseNoDelay) 
     341    if (sock->peer ().set_option (ACE_IPPROTO_TCP, 
     342                                  TCP_NODELAY, 
     343                                  (void*) & ndoption, 
     344                                  sizeof (int)) == -1) 
     345      { 
     346        sLog.outError ("WorldSocketMgr::OnSocketOpen: peer ().set_option TCP_NODELAY errno = %s", ACE_OS::strerror (errno)); 
     347        return -1; 
     348      } 
     349   
     350  sock->m_OutBufferSize = static_cast<size_t> (m_SockOutUBuff); 
     351 
     352  // we skip the Acceptor Thread 
     353  size_t min = 1; 
     354 
     355  ACE_ASSERT (m_NetThreadsCount >= 1); 
     356 
     357  for (size_t i = 1; i < m_NetThreadsCount; ++i) 
     358    if (m_NetThreads[i].Connections () < m_NetThreads[min].Connections ()) 
     359      min = i; 
     360 
     361  return m_NetThreads[min].AddSocket (sock); 
     362 
     363  return 0; 
     364} 
     365 
     366WorldSocketMgr* 
     367WorldSocketMgr::Instance () 
     368{ 
     369  return ACE_Singleton<WorldSocketMgr,ACE_Thread_Mutex>::instance(); 
     370} 
  • trunk/src/game/WorldSocketMgr.h

    r2 r6  
    1717 */ 
    1818 
    19 /// \addtogroup u2w User to World Communication 
    20 /// @{ 
    21 /// \file 
     19/** \addtogroup u2w User to World Communication 
     20 *  @{ 
     21 *  \file WorldSocketMgr.h 
     22 *  \author Derex <derex101@gmail.com> 
     23 */ 
    2224 
    2325#ifndef __WORLDSOCKETMGR_H 
    2426#define __WORLDSOCKETMGR_H 
    2527 
    26 #include "Policies/Singleton.h" 
     28#include <ace/Basic_Types.h> 
     29#include <ace/Singleton.h> 
     30#include <ace/Thread_Mutex.h> 
    2731 
    2832class WorldSocket; 
     33class ReactorRunnable; 
     34class ACE_Event_Handler; 
    2935 
    30 /// Manages the list of connected WorldSockets 
    31 class WorldSocketMgr 
     36/// Manages all sockets connected to peers and network threads 
     37class WorldSocketMgr  
    3238{ 
    33     public: 
    34         WorldSocketMgr(); 
     39public: 
     40  friend class WorldSocket; 
     41  friend class ACE_Singleton<WorldSocketMgr,ACE_Thread_Mutex>; 
    3542 
    36         void AddSocket(WorldSocket *s); 
    37         void RemoveSocket(WorldSocket *s); 
    38         void Update(time_t diff); 
    39  
    40     private: 
    41         typedef std::set<WorldSocket*> SocketSet; 
    42         SocketSet m_sockets; 
     43  /// Start network, listen at address:port . 
     44  int StartNetwork (ACE_UINT16 port, const char* address); 
     45   
     46  /// Stops all network threads, It will wait for all running threads . 
     47  void StopNetwork (); 
     48   
     49  /// Wait untill all network threads have "joined" . 
     50  void Wait (); 
     51   
     52  /// Make this class singleton . 
     53  static WorldSocketMgr* Instance (); 
     54   
     55private: 
     56  int OnSocketOpen(WorldSocket* sock); 
     57   
     58  int StartReactiveIO(ACE_UINT16 port, const char* address); 
     59   
     60private:   
     61  WorldSocketMgr (); 
     62  virtual ~WorldSocketMgr (); 
     63   
     64  ReactorRunnable* m_NetThreads; 
     65  size_t m_NetThreadsCount; 
     66   
     67  int m_SockOutKBuff; 
     68  int m_SockOutUBuff; 
     69  bool m_UseNoDelay; 
     70   
     71  ACE_Event_Handler* m_Acceptor; 
    4372}; 
    4473 
    45 #define sWorldSocketMgr MaNGOS::Singleton<WorldSocketMgr>::Instance() 
     74#define sWorldSocketMgr WorldSocketMgr::Instance () 
     75 
    4676#endif 
    4777/// @}