Index: trunk/src/game/Guild.cpp
===================================================================
--- trunk/src/game/Guild.cpp (revision 2)
+++ trunk/src/game/Guild.cpp (revision 6)
@@ -1806,6 +1806,11 @@
         need_space = count;
 
-    dest.push_back(GuildItemPosCount(slot,need_space));
-    count -= need_space;
+    GuildItemPosCount newPosition = GuildItemPosCount(slot,need_space);
+    if(!newPosition.isContainedIn(dest))
+    {
+        dest.push_back(newPosition);
+        count -= need_space;
+    }
+
     return EQUIP_ERR_OK;
 }
@@ -1837,5 +1842,25 @@
                     need_space = count;
 
-                dest.push_back(GuildItemPosCount(j,need_space));
+                GuildItemPosCount newPosition = GuildItemPosCount(j,need_space);
+                if(!newPosition.isContainedIn(dest))
+                {
+                    dest.push_back(newPosition);
+                    count -= need_space;
+
+                    if(count==0)
+                        return EQUIP_ERR_OK;
+                }
+            }
+        }
+        else
+        {
+            uint32 need_space = pSrcItem->GetMaxStackCount();
+            if(need_space > count)
+                need_space = count;
+
+            GuildItemPosCount newPosition = GuildItemPosCount(j,need_space);
+            if(!newPosition.isContainedIn(dest))
+            {
+                dest.push_back(newPosition);
                 count -= need_space;
 
@@ -1843,16 +1868,4 @@
                     return EQUIP_ERR_OK;
             }
-        }
-        else
-        {
-            uint32 need_space = pSrcItem->GetMaxStackCount();
-            if(need_space > count)
-                need_space = count;
-
-            dest.push_back(GuildItemPosCount(j,need_space));
-            count -= need_space;
-
-            if(count==0)
-                return EQUIP_ERR_OK;
         }
     }
@@ -1939,2 +1952,12 @@
     session->SendPacket(&data);
 }
+
+bool GuildItemPosCount::isContainedIn(GuildItemPosCountVec const &vec) const
+{
+    for(GuildItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr)
+        if(itr->slot == this->slot)
+            return true;
+
+    return false;
+}
+
Index: trunk/src/game/WorldSocket.h
===================================================================
--- trunk/src/game/WorldSocket.h (revision 2)
+++ trunk/src/game/WorldSocket.h (revision 6)
@@ -1,3 +1,3 @@
-/*
+/* 
  * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
  *
@@ -17,163 +17,217 @@
  */
 
-/// \addtogroup u2w
-/// @{
-/// \file
-
-#ifndef __WORLDSOCKET_H
-#define __WORLDSOCKET_H
-
-#include "sockets/TcpSocket.h"
-#include "Auth/AuthCrypt.h"
-
-enum ResponseCodes
+/** \addtogroup u2w User to World Communication
+ * @{
+ * \file WorldSocket.h
+ * \author Derex <derex101@gmail.com>
+ */
+
+#ifndef _WORLDSOCKET_H
+#define	_WORLDSOCKET_H
+
+#include <ace/Basic_Types.h>
+#include <ace/Synch_Traits.h>
+#include <ace/Svc_Handler.h>
+#include <ace/SOCK_Stream.h>
+#include <ace/SOCK_Acceptor.h>
+#include <ace/Acceptor.h>
+#include <ace/Thread_Mutex.h>
+#include <ace/Guard_T.h>
+#include <ace/Unbounded_Queue.h>
+#include <ace/Message_Block.h>
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "Common.h"
+#include "Auth/AuthCrypt.h" 
+
+class ACE_Message_Block;
+class WorldPacket;
+class WorldSession;
+
+/// Handler that can communicate over stream sockets.
+typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> WorldHandler;
+
+/**
+ * WorldSocket.
+ * 
+ * This class is responsible for the comunication with 
+ * remote clients.
+ * Most methods return -1 on failure. 
+ * The class uses refferece counting.
+ *
+ * For output the class uses one buffer (64K usually) and 
+ * a queue where it stores packet if there is no place on 
+ * the queue. The reason this is done, is because the server 
+ * does realy a lot of small-size writes to it, and it doesn't 
+ * scale well to allocate memory for every. When something is 
+ * writen to the output buffer the socket is not immideately 
+ * activated for output (again for the same reason), there 
+ * is 10ms celling (thats why there is Update() method). 
+ * This concept is simmilar to TCP_CORK, but TCP_CORK 
+ * usses 200ms celling. As result overhead generated by 
+ * sending packets from "producer" threads is minimal, 
+ * and doing a lot of writes with small size is tollerated.
+ * 
+ * The calls to Upate () method are managed by WorldSocketMgr
+ * and ReactorRunnable.
+ * 
+ * For input ,the class uses one 1024 bytes buffer on stack 
+ * to which it does recv() calls. And then recieved data is 
+ * distributed where its needed. 1024 matches pritey well the 
+ * traffic generated by client for now.
+ *  
+ * The input/output do speculative reads/writes (AKA it tryes 
+ * to read all data avaible in the kernel buffer or tryes to 
+ * write everything avaible in userspace buffer), 
+ * which is ok for using with Level and Edge Trigered IO 
+ * notification.
+ * 
+ */
+class WorldSocket : protected WorldHandler
 {
-    RESPONSE_SUCCESS                                       = 0x00,
-    RESPONSE_FAILURE                                       = 0x01,
-    RESPONSE_CANCELLED                                     = 0x02,
-    RESPONSE_DISCONNECTED                                  = 0x03,
-    RESPONSE_FAILED_TO_CONNECT                             = 0x04,
-    RESPONSE_CONNECTED                                     = 0x05,
-    RESPONSE_VERSION_MISMATCH                              = 0x06,
-
-    CSTATUS_CONNECTING                                     = 0x07,
-    CSTATUS_NEGOTIATING_SECURITY                           = 0x08,
-    CSTATUS_NEGOTIATION_COMPLETE                           = 0x09,
-    CSTATUS_NEGOTIATION_FAILED                             = 0x0A,
-    CSTATUS_AUTHENTICATING                                 = 0x0B,
-
-    AUTH_OK                                                = 0x0C,
-    AUTH_FAILED                                            = 0x0D,
-    AUTH_REJECT                                            = 0x0E,
-    AUTH_BAD_SERVER_PROOF                                  = 0x0F,
-    AUTH_UNAVAILABLE                                       = 0x10,
-    AUTH_SYSTEM_ERROR                                      = 0x11,
-    AUTH_BILLING_ERROR                                     = 0x12,
-    AUTH_BILLING_EXPIRED                                   = 0x13,
-    AUTH_VERSION_MISMATCH                                  = 0x14,
-    AUTH_UNKNOWN_ACCOUNT                                   = 0x15,
-    AUTH_INCORRECT_PASSWORD                                = 0x16,
-    AUTH_SESSION_EXPIRED                                   = 0x17,
-    AUTH_SERVER_SHUTTING_DOWN                              = 0x18,
-    AUTH_ALREADY_LOGGING_IN                                = 0x19,
-    AUTH_LOGIN_SERVER_NOT_FOUND                            = 0x1A,
-    AUTH_WAIT_QUEUE                                        = 0x1B,
-    AUTH_BANNED                                            = 0x1C,
-    AUTH_ALREADY_ONLINE                                    = 0x1D,
-    AUTH_NO_TIME                                           = 0x1E,
-    AUTH_DB_BUSY                                           = 0x1F,
-    AUTH_SUSPENDED                                         = 0x20,
-    AUTH_PARENTAL_CONTROL                                  = 0x21,
-    AUTH_LOCKED_ENFORCED                                   = 0x22,
-
-    REALM_LIST_IN_PROGRESS                                 = 0x23,
-    REALM_LIST_SUCCESS                                     = 0x24,
-    REALM_LIST_FAILED                                      = 0x25,
-    REALM_LIST_INVALID                                     = 0x26,
-    REALM_LIST_REALM_NOT_FOUND                             = 0x27,
-
-    ACCOUNT_CREATE_IN_PROGRESS                             = 0x28,
-    ACCOUNT_CREATE_SUCCESS                                 = 0x29,
-    ACCOUNT_CREATE_FAILED                                  = 0x2A,
-
-    CHAR_LIST_RETRIEVING                                   = 0x2B,
-    CHAR_LIST_RETRIEVED                                    = 0x2C,
-    CHAR_LIST_FAILED                                       = 0x2D,
-
-    CHAR_CREATE_IN_PROGRESS                                = 0x2E,
-    CHAR_CREATE_SUCCESS                                    = 0x2F,
-    CHAR_CREATE_ERROR                                      = 0x30,
-    CHAR_CREATE_FAILED                                     = 0x31,
-    CHAR_CREATE_NAME_IN_USE                                = 0x32,
-    CHAR_CREATE_DISABLED                                   = 0x33,
-    CHAR_CREATE_PVP_TEAMS_VIOLATION                        = 0x34,
-    CHAR_CREATE_SERVER_LIMIT                               = 0x35,
-    CHAR_CREATE_ACCOUNT_LIMIT                              = 0x36,
-    CHAR_CREATE_SERVER_QUEUE                               = 0x37,
-    CHAR_CREATE_ONLY_EXISTING                              = 0x38,
-    CHAR_CREATE_EXPANSION                                  = 0x39,
-
-    CHAR_DELETE_IN_PROGRESS                                = 0x3A,
-    CHAR_DELETE_SUCCESS                                    = 0x3B,
-    CHAR_DELETE_FAILED                                     = 0x3C,
-    CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER                 = 0x3D,
-    CHAR_DELETE_FAILED_GUILD_LEADER                        = 0x3E,
-    CHAR_DELETE_FAILED_ARENA_CAPTAIN                       = 0x3F,
-
-    CHAR_LOGIN_IN_PROGRESS                                 = 0x40,
-    CHAR_LOGIN_SUCCESS                                     = 0x41,
-    CHAR_LOGIN_NO_WORLD                                    = 0x42,
-    CHAR_LOGIN_DUPLICATE_CHARACTER                         = 0x43,
-    CHAR_LOGIN_NO_INSTANCES                                = 0x44,
-    CHAR_LOGIN_FAILED                                      = 0x45,
-    CHAR_LOGIN_DISABLED                                    = 0x46,
-    CHAR_LOGIN_NO_CHARACTER                                = 0x47,
-    CHAR_LOGIN_LOCKED_FOR_TRANSFER                         = 0x48,
-    CHAR_LOGIN_LOCKED_BY_BILLING                           = 0x49,
-
-    CHAR_NAME_SUCCESS                                      = 0x4A,
-    CHAR_NAME_FAILURE                                      = 0x4B,
-    CHAR_NAME_NO_NAME                                      = 0x4C,
-    CHAR_NAME_TOO_SHORT                                    = 0x4D,
-    CHAR_NAME_TOO_LONG                                     = 0x4E,
-    CHAR_NAME_INVALID_CHARACTER                            = 0x4F,
-    CHAR_NAME_MIXED_LANGUAGES                              = 0x50,
-    CHAR_NAME_PROFANE                                      = 0x51,
-    CHAR_NAME_RESERVED                                     = 0x52,
-    CHAR_NAME_INVALID_APOSTROPHE                           = 0x53,
-    CHAR_NAME_MULTIPLE_APOSTROPHES                         = 0x54,
-    CHAR_NAME_THREE_CONSECUTIVE                            = 0x55,
-    CHAR_NAME_INVALID_SPACE                                = 0x56,
-    CHAR_NAME_CONSECUTIVE_SPACES                           = 0x57,
-    CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS        = 0x58,
-    CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59,
-    CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME            = 0x5A,
+public:
+  /// Declare some friends
+  friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >;
+  friend class WorldSocketMgr;
+  friend class ReactorRunnable;
+
+  /// Declare the acceptor for this class
+  typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor;
+
+  /// Mutex type used for various syncronizations.
+  typedef ACE_Thread_Mutex LockType;
+  typedef ACE_Guard<LockType> GuardType;
+
+  /// Queue for storing packets for which there is no space.
+  typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT;
+
+  /// Check if socket is closed.
+  bool IsClosed (void) const;
+
+  /// Close the socket.
+  void CloseSocket (void);
+
+  /// Get address of connected peer.
+  const std::string& GetRemoteAddress (void) const;
+
+  /// Send A packet on the socket, this function is reentrant.
+  /// @param pct packet to send
+  /// @return -1 of failure
+  int SendPacket (const WorldPacket& pct);
+
+  /// Add refference to this object.
+  long AddReference (void);
+
+  /// Remove refference to this object.
+  long RemoveReference (void);
+
+protected:
+  /// things called by ACE framework.
+  WorldSocket (void);
+  virtual ~WorldSocket (void);
+
+  /// Called on open ,the void* is the acceptor.
+  virtual int open (void *);
+
+  /// Called on failures inside of the acceptor, don't call from your code.
+  virtual int close (int);
+
+  /// Called when we can read from the socket.
+  virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
+
+  /// Called when the socket can write.
+  virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE);
+
+  /// Called when connection is closed or error happens.
+  virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+                            ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+  /// Called by WorldSocketMgr/ReactorRunnable.
+  int Update (void);
+
+private:
+  /// Helper functions for processing incoming data.
+  int handle_input_header (void);
+  int handle_input_payload (void);
+  int handle_input_missing_data (void);
+
+  /// Help functions to mark/unmark the socket for output.
+  /// @param g the guard is for m_OutBufferLock, the function will release it
+  int cancel_wakeup_output (GuardType& g);
+  int schedule_wakeup_output (GuardType& g);
+
+  /// process one incoming packet.
+  /// @param new_pct received packet ,note that you need to delete it. 
+  int ProcessIncoming (WorldPacket* new_pct);
+
+  /// Called by ProcessIncoming() on CMSG_AUTH_SESSION.
+  int HandleAuthSession (WorldPacket& recvPacket);
+
+  /// Called by ProcessIncoming() on CMSG_PING.
+  int HandlePing (WorldPacket& recvPacket);
+
+  /// Try to write WorldPacket to m_OutBuffer ,return -1 if no space
+  /// Need to be called with m_OutBufferLock lock held
+  int iSendPacket (const WorldPacket& pct);
+
+  /// Flush m_PacketQueue if there are packets in it
+  /// Need to be called with m_OutBufferLock lock held
+  /// @return true if it wrote to the buffer ( AKA you need 
+  /// to mark the socket for output ).
+  bool iFlushPacketQueue ();
+
+private:
+  /// Time in which the last ping was received
+  ACE_Time_Value m_LastPingTime;
+  
+  /// Keep track of overspeed pings ,to prevent ping flood.
+  uint32 m_OverSpeedPings;
+
+  /// Address of the remote peer
+  std::string m_Address;
+
+  /// Class used for managing encryption of the headers
+  AuthCrypt m_Crypt;
+
+  /// Mutex lock to protect m_Session
+  LockType m_SessionLock;
+
+  /// Session to which recieved packets are routed
+  WorldSession* m_Session;
+
+  /// here are stored the fragmens of the recieved data
+  WorldPacket* m_RecvWPct;
+
+  /// This block actually refers to m_RecvWPct contents,
+  /// which alows easy and safe writing to it. 
+  /// It wont free memory when its deleted. m_RecvWPct takes care of freeing.
+  ACE_Message_Block m_RecvPct;
+
+  /// Fragment of the recieved header.
+  ACE_Message_Block m_Header;
+
+  /// Mutex for protecting otuput related data.
+  LockType m_OutBufferLock;
+
+  /// Buffer used for writing output.
+  ACE_Message_Block *m_OutBuffer;
+
+  /// Size of the m_OutBuffer.
+  size_t m_OutBufferSize;
+
+  /// Here are stored packets for which there was no space on m_OutBuffer,
+  /// this alows not-to kick player if its buffer is overflowed.
+  PacketQueueT m_PacketQueue;
+
+  /// True if the socket is registered with the reactor for output
+  bool m_OutActive;
+
+  uint32 m_Seed;
 };
 
-class WorldPacket;
-class SocketHandler;
-class WorldSession;
-
-/// Handle connection with the client software
-class WorldSocket : public TcpSocket
-{
-    public:
-        WorldSocket(ISocketHandler&);
-        ~WorldSocket();
-
-        void SendPacket(WorldPacket const* packet);
-        void CloseSocket();
-
-        void OnAccept();
-        void OnRead();
-        void OnDelete();
-
-        void Update(time_t diff);
-        // Player Queue
-        void SendAuthWaitQue(uint32 position);
-
-        WorldSession* GetSession() const { return _session; }
-    protected:
-        void SendSinglePacket();
-
-    protected:
-        void _HandleAuthSession(WorldPacket& recvPacket);
-        void _HandlePing(WorldPacket& recvPacket);
-
-    private:
-        AuthCrypt _crypt;
-        uint32 _seed;
-        uint32 _cmd;
-        uint16 _remaining;
-        WorldSession* _session;
-
-        ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> _sendQueue;
-
-        uint32 m_LastPingMSTime;
-        uint32 m_OverSpeedPings;
-
-        // internal checks
-        void SizeError(WorldPacket const& packet, uint32 size) const;
-};
-#endif
+#endif	/* _WORLDSOCKET_H */
+
 /// @}
Index: trunk/src/game/WorldSocketMgr.cpp
===================================================================
--- trunk/src/game/WorldSocketMgr.cpp (revision 2)
+++ trunk/src/game/WorldSocketMgr.cpp (revision 6)
@@ -17,39 +17,354 @@
  */
 
-/** \file
-    \ingroup u2w
-*/
-
+/** \file WorldSocketMgr.cpp
+ *  \ingroup u2w
+ *  \author Derex <derex101@gmail.com>
+ */
+
+#include "WorldSocketMgr.h"
+
+#include <ace/ACE.h>
+#include <ace/Log_Msg.h>
+#include <ace/Reactor.h>
+#include <ace/Reactor_Impl.h>
+#include <ace/TP_Reactor.h>
+#include <ace/Dev_Poll_Reactor.h>
+#include <ace/Guard_T.h>
+#include <ace/Atomic_Op.h>
+#include <ace/os_include/arpa/os_inet.h>
+#include <ace/os_include/netinet/os_tcp.h>
+#include <ace/os_include/sys/os_types.h>
+#include <ace/os_include/sys/os_socket.h>
+
+#include <set>
+
+#include "Log.h"
 #include "Common.h"
+#include "Config/ConfigEnv.h"
+#include "Database/DatabaseEnv.h"
 #include "WorldSocket.h"
-#include "WorldSocketMgr.h"
-#include "Policies/SingletonImp.h"
-
-INSTANTIATE_SINGLETON_1( WorldSocketMgr );
-
-/// WorldSocketMgr constructor
-WorldSocketMgr::WorldSocketMgr()
-{
-}
-
-/// Add a WorldSocket to the set
-void WorldSocketMgr::AddSocket(WorldSocket *s)
-{
-    m_sockets.insert(s);
-}
-
-/// Remove a WorldSocket to the set
-void WorldSocketMgr::RemoveSocket(WorldSocket *s)
-{
-    m_sockets.erase(s);
-}
-
-/// Triggers an 'update' to all sockets in the set
-void WorldSocketMgr::Update(time_t diff)
-{
-    SocketSet::iterator i;
-    for(i = m_sockets.begin(); i != m_sockets.end(); i++)
-    {
-        (*i)->Update(diff);
-    }
-}
+
+/** 
+ * This is a helper class to WorldSocketMgr ,that manages 
+ * network threads, and assigning connections from acceptor thread
+ * to other network threads
+ */
+class ReactorRunnable : protected ACE_Task_Base
+{
+public:
+
+  ReactorRunnable () :
+  m_ThreadId (-1),
+  m_Connections (0),
+  m_Reactor (0)
+  {
+    ACE_Reactor_Impl* imp = 0;
+
+#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL)
+    imp = new ACE_Dev_Poll_Reactor ();
+
+    imp->max_notify_iterations (128);
+    imp->restart (1);
+#else
+    imp = new ACE_TP_Reactor ();
+    imp->max_notify_iterations (128);
+#endif
+
+    m_Reactor = new ACE_Reactor (imp, 1);
+  }
+
+  virtual
+  ~ReactorRunnable ()
+  {
+    this->Stop ();
+    this->Wait ();
+
+    if (m_Reactor)
+      delete m_Reactor;
+  }
+
+  void
+  Stop ()
+  {
+    m_Reactor->end_reactor_event_loop ();
+  }
+
+  int
+  Start ()
+  {
+    if (m_ThreadId != -1)
+      return -1;
+
+    return (m_ThreadId = this->activate ());
+  }
+
+  void
+  Wait ()
+  {
+    ACE_Task_Base::wait ();
+  }
+
+  long
+  Connections ()
+  {
+    return static_cast<long> (m_Connections.value ());
+  }
+
+  int
+  AddSocket (WorldSocket* sock)
+  {
+    ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, m_NewSockets_Lock, -1);
+
+    ++m_Connections;
+    sock->AddReference();
+    sock->reactor (m_Reactor);
+    m_NewSockets.insert (sock);
+
+    return 0;
+  }
+  
+  ACE_Reactor* GetReactor ()
+  {
+    return m_Reactor;
+  }
+  
+protected:
+  
+  void
+  AddNewSockets ()
+  {
+    ACE_GUARD (ACE_Thread_Mutex, Guard, m_NewSockets_Lock);
+
+    if (m_NewSockets.empty ())
+      return;
+
+    for (SocketSet::iterator i = m_NewSockets.begin (); i != m_NewSockets.end (); ++i)
+      {
+        WorldSocket* sock = (*i);
+
+        if (sock->IsClosed ())
+          {
+            sock->RemoveReference ();
+            --m_Connections;
+          }
+        else
+          m_Sockets.insert (sock);
+      }
+
+    m_NewSockets.clear ();
+  }
+
+  virtual int
+  svc (void)
+  {
+    DEBUG_LOG ("Network Thread Starting");
+
+    WorldDatabase.ThreadStart ();
+
+    ACE_ASSERT (m_Reactor);
+
+    SocketSet::iterator i, t;
+
+    while (!m_Reactor->reactor_event_loop_done ())
+      {
+        // dont be too smart to move this outside the loop 
+        // the run_reactor_event_loop will modify interval
+        ACE_Time_Value interval (0, 10000);
+
+        if (m_Reactor->run_reactor_event_loop (interval) == -1)
+          break;
+
+        AddNewSockets ();
+
+        for (i = m_Sockets.begin (); i != m_Sockets.end ();)
+          {
+            if ((*i)->Update () == -1)
+              {
+                t = i;
+                i++;
+                (*t)->CloseSocket ();
+                (*t)->RemoveReference ();
+                --m_Connections;
+                m_Sockets.erase (t);
+              }
+            else
+              i++;
+          }
+      }
+
+    WorldDatabase.ThreadEnd ();
+
+    DEBUG_LOG ("Network Thread Exitting");
+
+    return 0;
+  }
+
+private:
+  typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> AtomicInt;
+  typedef std::set<WorldSocket*> SocketSet;
+
+  ACE_Reactor* m_Reactor;
+  AtomicInt m_Connections;
+  int m_ThreadId;
+
+  SocketSet m_Sockets;
+
+  SocketSet m_NewSockets;
+  ACE_Thread_Mutex m_NewSockets_Lock;
+};
+
+
+
+WorldSocketMgr::WorldSocketMgr () :
+m_NetThreadsCount (0),
+m_NetThreads (0),
+m_SockOutKBuff (-1),
+m_SockOutUBuff (65536),
+m_UseNoDelay (true),
+m_Acceptor (0) {}
+
+WorldSocketMgr::~WorldSocketMgr ()
+{
+  if (m_NetThreads)
+    delete [] m_NetThreads;
+  
+  if(m_Acceptor)
+    delete m_Acceptor;
+}
+
+int
+WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address)
+{
+  m_UseNoDelay = sConfig.GetBoolDefault ("Network.TcpNodelay", true);
+
+  int num_threads = sConfig.GetIntDefault ("Network.Threads", 1);
+
+  if (num_threads <= 0)
+    {
+      sLog.outError ("Network.Threads is wrong in your config file");
+      return -1;
+    }
+
+  m_NetThreadsCount = static_cast<size_t> (num_threads + 1);
+
+  m_NetThreads = new ReactorRunnable[m_NetThreadsCount];
+
+  sLog.outBasic ("Max alowed socket connections %d",ACE::max_handles ());
+
+  m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); // -1 means use default
+
+  m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536);
+
+  if ( m_SockOutUBuff <= 0 )
+    {
+      sLog.outError ("Network.OutUBuff is wrong in your config file");
+      return -1;
+    }
+
+  WorldSocket::Acceptor *acc = new WorldSocket::Acceptor;
+  m_Acceptor = acc;
+
+  ACE_INET_Addr listen_addr (port, address);
+
+  if (acc->open (listen_addr, m_NetThreads[0].GetReactor (), ACE_NONBLOCK) == -1)
+    {
+      sLog.outError ("Failed to open acceptor ,check if the port is free");
+      return -1;
+    }
+
+  for (size_t i = 0; i < m_NetThreadsCount; ++i)
+    m_NetThreads[i].Start ();
+
+  return 0;
+}
+
+int
+WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address)
+{
+  if (!sLog.IsOutDebug ())
+    ACE_Log_Msg::instance ()->priority_mask (LM_ERROR, ACE_Log_Msg::PROCESS);
+
+  if (this->StartReactiveIO (port, address) == -1)
+    return -1;
+
+  return 0;
+}
+
+void
+WorldSocketMgr::StopNetwork ()
+{
+  if (m_Acceptor)
+    {
+      WorldSocket::Acceptor* acc = dynamic_cast<WorldSocket::Acceptor*> (m_Acceptor);
+
+      if (acc)
+        acc->close ();
+    }
+
+  if (m_NetThreadsCount != 0)
+    {
+      for (size_t i = 0; i < m_NetThreadsCount; ++i)
+        m_NetThreads[i].Stop ();
+    }
+  
+  this->Wait ();
+}
+
+void 
+WorldSocketMgr::Wait ()
+{
+  if (m_NetThreadsCount != 0)
+    {
+      for (size_t i = 0; i < m_NetThreadsCount; ++i)
+        m_NetThreads[i].Wait ();
+    }
+}
+
+int
+WorldSocketMgr::OnSocketOpen (WorldSocket* sock)
+{
+  // set some options here
+  if (m_SockOutKBuff >= 0)
+    if (sock->peer ().set_option (SOL_SOCKET,
+                                  SO_SNDBUF,
+                                  (void*) & m_SockOutKBuff,
+                                  sizeof (int)) == -1 && errno != ENOTSUP)
+      {
+        sLog.outError ("WorldSocketMgr::OnSocketOpen set_option SO_SNDBUF");
+        return -1;
+      }
+
+  static const int ndoption = 1;
+
+  // Set TCP_NODELAY.
+  if (m_UseNoDelay)
+    if (sock->peer ().set_option (ACE_IPPROTO_TCP,
+                                  TCP_NODELAY,
+                                  (void*) & ndoption,
+                                  sizeof (int)) == -1)
+      {
+        sLog.outError ("WorldSocketMgr::OnSocketOpen: peer ().set_option TCP_NODELAY errno = %s", ACE_OS::strerror (errno));
+        return -1;
+      }
+  
+  sock->m_OutBufferSize = static_cast<size_t> (m_SockOutUBuff);
+
+  // we skip the Acceptor Thread
+  size_t min = 1;
+
+  ACE_ASSERT (m_NetThreadsCount >= 1);
+
+  for (size_t i = 1; i < m_NetThreadsCount; ++i)
+    if (m_NetThreads[i].Connections () < m_NetThreads[min].Connections ())
+      min = i;
+
+  return m_NetThreads[min].AddSocket (sock);
+
+  return 0;
+}
+
+WorldSocketMgr*
+WorldSocketMgr::Instance ()
+{
+  return ACE_Singleton<WorldSocketMgr,ACE_Thread_Mutex>::instance();
+}
Index: trunk/src/game/Creature.h
===================================================================
--- trunk/src/game/Creature.h (revision 2)
+++ trunk/src/game/Creature.h (revision 6)
@@ -124,13 +124,4 @@
     uint32 lastincr;
     uint32 ExtendedCost;
-};
-
-struct TrainerSpell
-{
-    SpellEntry const* spell;
-    uint32 spellcost;
-    uint32 reqskill;
-    uint32 reqskillvalue;
-    uint32 reqlevel;
 };
 
@@ -301,4 +292,27 @@
 #endif
 
+struct TrainerSpell
+{
+    uint32 spell;
+    uint32 spellcost;
+    uint32 reqskill;
+    uint32 reqskillvalue;
+    uint32 reqlevel;
+};
+
+typedef std::vector<TrainerSpell*> TrainerSpellList;
+
+struct TrainerSpellData
+{
+    TrainerSpellData() : trainerType(0) {}
+
+    TrainerSpellList spellList;
+    uint32 trainerType;                                     // trainer type based at trainer spells, can be different from creature_template value.
+                                                            // req. for correct show non-prof. trainers like weaponmaster, allowed values 0 and 2.
+
+    void Clear();
+    TrainerSpell const* Find(uint32 spell_id) const;
+};
+
 typedef std::list<GossipOption> GossipOptionList;
 
@@ -441,12 +455,5 @@
         }
 
-        /*********************************************************/
-        /***                    TRAINER SYSTEM                 ***/
-        /*********************************************************/
-        typedef std::list<TrainerSpell> SpellsList;
-        void LoadTrainerSpells();                           // must be called before access to trainer spells, lazy loading at first call
-        void ReloadTrainerSpells() { m_trainerSpellsLoaded = false; LoadTrainerSpells(); }
-        SpellsList const& GetTrainerSpells() const { return m_trainer_spells; }
-        uint32 GetTrainerType() const { return m_trainer_type; }
+        TrainerSpellData const* GetTrainerSpells() const;
 
         CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; }
@@ -559,9 +566,4 @@
         bool m_itemsLoaded;                                 // vendor items loading state
 
-        // trainer spells
-        bool m_trainerSpellsLoaded;                         // trainer spells loading state
-        SpellsList m_trainer_spells;
-        uint32 m_trainer_type;                              // trainer type based at trainer spells, can be different from creature_template value.
-                                                            // req. for correct show non-prof. trainers like weaponmaster.
         void _RealtimeSetCreatureInfo();
 
@@ -581,5 +583,4 @@
         bool m_gossipOptionLoaded;
         GossipOptionList m_goptions;
-        uint32 m_NPCTextId;                                 // cached value
 
         uint8 m_emoteState;
Index: trunk/src/game/SpellEffects.cpp
===================================================================
--- trunk/src/game/SpellEffects.cpp (revision 2)
+++ trunk/src/game/SpellEffects.cpp (revision 6)
@@ -79,5 +79,5 @@
     &Spell::EffectUnused,                                   // 21 SPELL_EFFECT_EVADE                    one spell: Evade (DND)
     &Spell::EffectParry,                                    // 22 SPELL_EFFECT_PARRY
-    &Spell::EffectUnused,                                   // 23 SPELL_EFFECT_BLOCK                    one spell: Block
+    &Spell::EffectBlock,                                    // 23 SPELL_EFFECT_BLOCK                    one spell: Block
     &Spell::EffectCreateItem,                               // 24 SPELL_EFFECT_CREATE_ITEM
     &Spell::EffectUnused,                                   // 25 SPELL_EFFECT_WEAPON
@@ -5331,4 +5331,12 @@
 }
 
+void Spell::EffectBlock(uint32 /*i*/)
+{
+    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
+        return;
+
+    ((Player*)unitTarget)->SetCanBlock(true);
+}
+
 void Spell::EffectMomentMove(uint32 i)
 {
Index: trunk/src/game/Chat.h
===================================================================
--- trunk/src/game/Chat.h (revision 2)
+++ trunk/src/game/Chat.h (revision 6)
@@ -27,4 +27,5 @@
 class Player;
 class Unit;
+struct GameTele;
 
 struct LanguageDesc
@@ -151,4 +152,5 @@
         bool HandleReloadAllItemCommand(const char* args);
         bool HandleReloadAllLootCommand(const char* args);
+        bool HandleReloadAllNpcCommand(const char* args);
         bool HandleReloadAllQuestCommand(const char* args);
         bool HandleReloadAllScriptsCommand(const char* args);
@@ -165,4 +167,5 @@
         bool HandleReloadGameGraveyardZoneCommand(const char* args);
         bool HandleReloadGameObjectScriptsCommand(const char* args);
+        bool HandleReloadGameTeleCommand(const char* args);
         bool HandleReloadGOQuestRelationsCommand(const char* args);
         bool HandleReloadGOQuestInvRelationsCommand(const char* args);
@@ -178,4 +181,7 @@
         bool HandleReloadLootTemplatesSkinningCommand(const char* args);
         bool HandleReloadMangosStringCommand(const char* args);
+        bool HandleReloadNpcGossipCommand(const char* args);
+        bool HandleReloadNpcTrainerCommand(const char* args);
+        bool HandleReloadNpcVendorCommand(const char* args);
         bool HandleReloadQuestAreaTriggersCommand(const char* args);
         bool HandleReloadQuestEndScriptsCommand(const char* args);
@@ -265,4 +271,5 @@
         bool HandleAllowMovementCommand(const char* args);
         bool HandleGoCommand(const char* args);
+
         bool HandleLearnCommand(const char* args);
         bool HandleLearnAllCommand(const char* args);
@@ -275,4 +282,20 @@
         bool HandleLearnAllMySpellsCommand(const char* args);
         bool HandleLearnAllMyTalentsCommand(const char* args);
+
+        bool HandleLookupAreaCommand(const char* args);
+        bool HandleLookupCreatureCommand(const char* args);
+        bool HandleLookupEventCommand(const char* args);
+        bool HandleLookupFactionCommand(const char * args);
+        bool HandleLookupItemCommand(const char * args);
+        bool HandleLookupItemSetCommand(const char * args);
+        bool HandleLookupObjectCommand(const char* args);
+        bool HandleLookupPlayerIpCommand(const char* args);
+        bool HandleLookupPlayerAccountCommand(const char* args);
+        bool HandleLookupPlayerEmailCommand(const char* args);
+        bool HandleLookupQuestCommand(const char* args);
+        bool HandleLookupSkillCommand(const char* args);
+        bool HandleLookupSpellCommand(const char* args);
+        bool HandleLookupTeleCommand(const char * args);
+
         bool HandleCooldownCommand(const char* args);
         bool HandleUnLearnCommand(const char* args);
@@ -300,6 +323,5 @@
         bool HandleAddItemCommand(const char* args);
         bool HandleAddItemSetCommand(const char* args);
-        bool HandleLookupItemCommand(const char * args);
-        bool HandleLookupItemSetCommand(const char * args);
+
         bool HandleGuildCreateCommand(const char* args);
         bool HandleGuildInviteCommand(const char* args);
@@ -315,5 +337,4 @@
         bool HandleDelTeleCommand(const char * args);
         bool HandleListAurasCommand(const char * args);
-        bool HandleLookupTeleCommand(const char * args);
 
         bool HandleResetHonorCommand(const char * args);
@@ -333,12 +354,4 @@
         bool HandleListObjectCommand(const char* args);
         bool HandleNearObjectCommand(const char* args);
-        bool HandleLookupAreaCommand(const char* args);
-        bool HandleLookupCreatureCommand(const char* args);
-        bool HandleLookupEventCommand(const char* args);
-        bool HandleLookupFactionCommand(const char * args);
-        bool HandleLookupObjectCommand(const char* args);
-        bool HandleLookupQuestCommand(const char* args);
-        bool HandleLookupSkillCommand(const char* args);
-        bool HandleLookupSpellCommand(const char* args);
         bool HandlePasswordCommand(const char* args);
         bool HandleLockAccountCommand(const char* args);
@@ -387,4 +400,5 @@
         char*     extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL);
         uint32    extractSpellIdFromLink(char* text);
+        GameTele const* extractGameTeleFromLink(char* text);
 
         GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry);
@@ -395,4 +409,5 @@
         void ShowTicket(uint64 guid, char const* text, char const* time);
         uint32 GetTicketIDByNum(uint32 num);
+        bool LookupPlayerSearchCommand(QueryResult* result, int32 limit);
 
         void SetSentErrorMessage(bool val){ sentErrorMessage = val;};
Index: trunk/src/game/Level1.cpp
===================================================================
--- trunk/src/game/Level1.cpp (revision 2)
+++ trunk/src/game/Level1.cpp (revision 6)
@@ -1555,5 +1555,4 @@
 }
 
-//Teleport by game_tele entry
 bool ChatHandler::HandleModifyHonorCommand (const char* args)
 {
@@ -1585,29 +1584,10 @@
     Player* _player = m_session->GetPlayer();
 
-    char* cId = extractKeyFromLink((char*)args,"Htele");    // string or [name] Shift-click form |color|Htele:name|h[name]|h|r
-    if(!cId)
-        return false;
-
-    std::string name = cId;
-    WorldDatabase.escape_string(name);
-
-    QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",name.c_str());
-    if (!result)
+    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
+    GameTele const* tele = extractGameTeleFromLink((char*)args);
+
+    if (!tele)
     {
         SendSysMessage(LANG_COMMAND_TELE_NOTFOUND);
-        SetSentErrorMessage(true);
-        return false;
-    }
-    Field *fields = result->Fetch();
-    float x = fields[0].GetFloat();
-    float y = fields[1].GetFloat();
-    float z = fields[2].GetFloat();
-    float ort = fields[3].GetFloat();
-    int mapid = fields[4].GetUInt16();
-    delete result;
-
-    if(!MapManager::IsValidMapCoord(mapid,x,y,x,ort))
-    {
-        PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
         SetSentErrorMessage(true);
         return false;
@@ -1624,5 +1604,5 @@
         _player->SaveRecallPosition();
 
-    _player->TeleportTo(mapid, x, y, z, ort);
+    _player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation);
     return true;
 }
@@ -1703,32 +1683,34 @@
 
     std::string namepart = str;
-    WorldDatabase.escape_string(namepart);
-    QueryResult *result = WorldDatabase.PQuery("SELECT name FROM game_tele WHERE name "_LIKE_" '""%%%s%%""'",namepart.c_str());
-    if (!result)
-    {
-        SendSysMessage(LANG_COMMAND_TELE_NOREQUEST);
-        SetSentErrorMessage(true);
-        return false;
-    }
-    std::string reply;
-    for (uint64 i=0; i < result->GetRowCount(); i++)
-    {
-        Field *fields = result->Fetch();
-        reply += "  |cffffffff|Htele:";
-        reply += fields[0].GetCppString();
-        reply += "|h[";
-        reply += fields[0].GetCppString();
-        reply += "]|h|r\n";
-        result->NextRow();
-    }
-    delete result;
-
-    if(reply.empty())
+    std::wstring wnamepart;
+
+    if(!Utf8toWStr(namepart,wnamepart))
+        return false;
+
+    // converting string that we try to find to lower case
+    wstrToLower( wnamepart );
+
+    GameTeleMap const & teleMap = objmgr.GetGameTeleMap();
+
+    std::ostringstream reply;
+    for(GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr)
+    {
+        GameTele const* tele = &itr->second;
+
+        if(tele->wnameLow.find(wnamepart) == std::wstring::npos)
+            continue;
+
+        reply << "  |cffffffff|Htele:";
+        reply << itr->first;
+        reply << "|h[";
+        reply << tele->name;
+        reply << "]|h|r\n";
+    }
+
+    if(reply.str().empty())
         SendSysMessage(LANG_COMMAND_TELE_NOLOCATION);
     else
-    {
-        reply = GetMangosString(LANG_COMMAND_TELE_LOCATION) + reply;
-        SendSysMessage(reply.c_str());
-    }
+        PSendSysMessage(LANG_COMMAND_TELE_LOCATION,reply.str().c_str());
+
     return true;
 }
@@ -1862,43 +1844,22 @@
         return false;
 
+    std::string name = pName;
+
+    if(!normalizePlayerName(name))
+    {
+        SendSysMessage(LANG_PLAYER_NOT_FOUND);
+        SetSentErrorMessage(true);
+        return false;
+    }
+
     char* tail = strtok(NULL, "");
     if(!tail)
         return false;
 
-    char* cId = extractKeyFromLink((char*)tail,"Htele");    // string or [name] Shift-click form |color|Htele:name|h[name]|h|r
-    if(!cId)
-        return false;
-
-    std::string location = cId;
-
-    std::string name = pName;
-
-    if(!normalizePlayerName(name))
-    {
-        SendSysMessage(LANG_PLAYER_NOT_FOUND);
-        SetSentErrorMessage(true);
-        return false;
-    }
-
-    WorldDatabase.escape_string(location);
-    QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str());
-    if (!result)
+    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
+    GameTele const* tele = extractGameTeleFromLink(tail);
+    if(!tele)
     {
         SendSysMessage(LANG_COMMAND_TELE_NOTFOUND);
-        SetSentErrorMessage(true);
-        return false;
-    }
-
-    Field *fields = result->Fetch();
-    float x = fields[0].GetFloat();
-    float y = fields[1].GetFloat();
-    float z = fields[2].GetFloat();
-    float ort = fields[3].GetFloat();
-    int mapid = fields[4].GetUInt16();
-    delete result;
-
-    if(!MapManager::IsValidMapCoord(mapid,x,y,x,ort))
-    {
-        PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
         SetSentErrorMessage(true);
         return false;
@@ -1916,5 +1877,5 @@
         }
 
-        PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", location.c_str());
+        PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", tele->name.c_str());
 
         if (m_session->GetPlayer()->IsVisibleGloballyFor(chr))
@@ -1931,10 +1892,10 @@
             chr->SaveRecallPosition();
 
-        chr->TeleportTo(mapid,x,y,z,chr->GetOrientation());
+        chr->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation);
     }
     else if (uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()))
     {
-        PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetMangosString(LANG_OFFLINE), location.c_str());
-        Player::SavePositionInDB(mapid,x,y,z,ort,MapManager::Instance().GetZoneId(mapid,x,y),guid);
+        PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str());
+        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);
     }
     else
@@ -1958,13 +1919,7 @@
     }
 
-    char* cId = extractKeyFromLink((char*)args,"Htele");    // string or [name] Shift-click form |color|Htele:name|h[name]|h|r
-    if(!cId)
-        return false;
-
-    std::string location = cId;
-
-    WorldDatabase.escape_string(location);
-    QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM game_tele WHERE name = '%s'",location.c_str());
-    if (!result)
+    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
+    GameTele const* tele = extractGameTeleFromLink((char*)args);
+    if(!tele)
     {
         SendSysMessage(LANG_COMMAND_TELE_NOTFOUND);
@@ -1972,21 +1927,6 @@
         return false;
     }
-    Field *fields = result->Fetch();
-    float x = fields[0].GetFloat();
-    float y = fields[1].GetFloat();
-    float z = fields[2].GetFloat();
-    float ort = fields[3].GetFloat();
-    int mapid = fields[4].GetUInt16();
-    delete result;
-
-    if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
-    {
-        PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
-        SetSentErrorMessage(true);
-        return false;
-    }
 
     Group *grp = player->GetGroup();
-
     if(!grp)
     {
@@ -2009,5 +1949,5 @@
         }
 
-        PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", location.c_str());
+        PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", tele->name.c_str());
 
         if (m_session->GetPlayer() != pl && m_session->GetPlayer()->IsVisibleGloballyFor(pl))
@@ -2024,5 +1964,5 @@
             pl->SaveRecallPosition();
 
-        pl->TeleportTo(mapid, x, y, z, ort);
+        pl->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation);
     }
 
Index: trunk/src/game/Level3.cpp
===================================================================
--- trunk/src/game/Level3.cpp (revision 2)
+++ trunk/src/game/Level3.cpp (revision 6)
@@ -62,9 +62,9 @@
 {
     HandleReloadAreaTriggerTeleportCommand("");
-    //HandleReloadAreaTriggerTavernCommand(""); -- reloaded in HandleReloadAreaTriggerTavernCommand
-    //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand
     HandleReloadSkillFishingBaseLevelCommand("");
 
+    HandleReloadAllAreaCommand("");
     HandleReloadAllLootCommand("");
+    HandleReloadAllNpcCommand("");
     HandleReloadAllQuestCommand("");
     HandleReloadAllSpellCommand("");
@@ -74,4 +74,5 @@
     HandleReloadReservedNameCommand("");
     HandleReloadMangosStringCommand("");
+    HandleReloadGameTeleCommand("");
     return true;
 }
@@ -79,6 +80,24 @@
 bool ChatHandler::HandleReloadAllAreaCommand(const char*)
 {
+    //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand
     HandleReloadAreaTriggerTeleportCommand("");
-    //HandleReloadAreaTriggerTavernCommand(""); -- reloaded in HandleReloadAreaTriggerTavernCommand
+    HandleReloadAreaTriggerTavernCommand("");
+    HandleReloadGameGraveyardZoneCommand("");
+    return true;
+}
+
+bool ChatHandler::HandleReloadAllLootCommand(const char*)
+{
+    sLog.outString( "Re-Loading Loot Tables..." );
+    LoadLootTables();
+    SendGlobalSysMessage("DB tables `*_loot_template` reloaded.");
+    return true;
+}
+
+bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/)
+{
+    HandleReloadNpcGossipCommand("a");
+    HandleReloadNpcTrainerCommand("a");
+    HandleReloadNpcVendorCommand("a");
     return true;
 }
@@ -92,12 +111,4 @@
     objmgr.LoadQuestRelations();
     SendGlobalSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded.");
-    return true;
-}
-
-bool ChatHandler::HandleReloadAllLootCommand(const char*)
-{
-    sLog.outString( "Re-Loading Loot Tables..." );
-    LoadLootTables();
-    SendGlobalSysMessage("DB tables `*_loot_template` reloaded.");
     return true;
 }
@@ -321,4 +332,28 @@
 }
 
+bool ChatHandler::HandleReloadNpcGossipCommand(const char*)
+{
+    sLog.outString( "Re-Loading `npc_gossip` Table!" );
+    objmgr.LoadNpcTextId();
+    SendGlobalSysMessage("DB table `npc_gossip` reloaded.");
+    return true;
+}
+
+bool ChatHandler::HandleReloadNpcTrainerCommand(const char*)
+{
+    sLog.outString( "Re-Loading `npc_trainer` Table!" );
+    objmgr.LoadTrainerSpell();
+    SendGlobalSysMessage("DB table `npc_trainer` reloaded.");
+    return true;
+}
+
+bool ChatHandler::HandleReloadNpcVendorCommand(const char*)
+{
+    sLog.outString( "Re-Loading `npc_vendor` Table!" );
+    objmgr.LoadVendors();
+    SendGlobalSysMessage("DB table `npc_vendor` reloaded.");
+    return true;
+}
+
 bool ChatHandler::HandleReloadReservedNameCommand(const char*)
 {
@@ -548,4 +583,15 @@
 
     SendGlobalSysMessage("DB table `game_graveyard_zone` reloaded.");
+
+    return true;
+}
+
+bool ChatHandler::HandleReloadGameTeleCommand(const char* /*arg*/)
+{
+    sLog.outString( "Re-Loading Game Tele coordinates...");
+
+    objmgr.LoadGameTele();
+
+    SendGlobalSysMessage("DB table `game_tele` reloaded.");
 
     return true;
@@ -3870,26 +3916,27 @@
     if(!*args)
         return false;
-    QueryResult *result;
+
     Player *player=m_session->GetPlayer();
-    if (!player) return false;
+    if (!player)
+        return false;
 
     std::string name = args;
-    WorldDatabase.escape_string(name);
-    result = WorldDatabase.PQuery("SELECT id FROM game_tele WHERE name = '%s'",name.c_str());
-    if (result)
+
+    if(objmgr.GetGameTele(name))
     {
         SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST);
-        delete result;
-        SetSentErrorMessage(true);
-        return false;
-    }
-
-    float x = player->GetPositionX();
-    float y = player->GetPositionY();
-    float z = player->GetPositionZ();
-    float ort = player->GetOrientation();
-    int mapid = player->GetMapId();
-
-    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()))
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    GameTele tele;
+    tele.position_x  = player->GetPositionX();
+    tele.position_y  = player->GetPositionY();
+    tele.position_z  = player->GetPositionZ();
+    tele.orientation = player->GetOrientation();
+    tele.mapId       = player->GetMapId();
+    tele.name        = name;
+
+    if(objmgr.AddGameTele(tele))
     {
         SendSysMessage(LANG_COMMAND_TP_ADDED);
@@ -3911,8 +3958,6 @@
 
     std::string name = args;
-    WorldDatabase.escape_string(name);
-
-    QueryResult *result=WorldDatabase.PQuery("SELECT id FROM game_tele WHERE name = '%s'",name.c_str());
-    if (!result)
+
+    if(!objmgr.DeleteGameTele(name))
     {
         SendSysMessage(LANG_COMMAND_TELE_NOTFOUND);
@@ -3920,16 +3965,6 @@
         return false;
     }
-    delete result;
-
-    if(WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",name.c_str()))
-    {
-        SendSysMessage(LANG_COMMAND_TP_DELETED);
-    }
-    else
-    {
-        SendSysMessage(LANG_COMMAND_TP_DELETEERR);
-        SetSentErrorMessage(true);
-        return false;
-    }
+
+    SendSysMessage(LANG_COMMAND_TP_DELETED);
     return true;
 }
@@ -4759,5 +4794,5 @@
     if(Type == "ip")
     {
-        result = loginDatabase.PQuery("SELECT ip FROM ip_banned WHERE ip "_LIKE_" '""%%%s%%""'",Filter.c_str());
+        result = loginDatabase.PQuery("SELECT ip FROM ip_banned WHERE ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),Filter.c_str());
         if(!result)
         {
@@ -4778,5 +4813,5 @@
     if(Type == "account")
     {
-        result = loginDatabase.PQuery("SELECT id FROM account WHERE username "_LIKE_" '""%%%s%%""' ",Filter.c_str());
+        result = loginDatabase.PQuery("SELECT id FROM account WHERE username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),Filter.c_str());
         if (!result)
         {
@@ -4788,5 +4823,5 @@
     else if(Type == "characters")
     {
-        result = CharacterDatabase.PQuery("SELECT account FROM characters, WHERE name "_LIKE_" '""%%%s%%""' ",Filter.c_str());
+        result = CharacterDatabase.PQuery("SELECT account FROM characters, WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),Filter.c_str());
         if (!result)
         {
Index: trunk/src/game/WaypointMovementGenerator.cpp
===================================================================
--- trunk/src/game/WaypointMovementGenerator.cpp (revision 2)
+++ trunk/src/game/WaypointMovementGenerator.cpp (revision 6)
@@ -112,4 +112,6 @@
             // Now we re-set destination to same node and start travel
             creature.addUnitState(UNIT_STAT_ROAMING);
+            if (creature.canFly())
+                creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
             const WaypointNode &node = i_path->at(i_currentNode);
             i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
@@ -174,4 +176,6 @@
         {
             creature.addUnitState(UNIT_STAT_ROAMING);
+            if (creature.canFly())
+                creature.SetUnitMovementFlags(MOVEMENTFLAG_FLYING2);
             const WaypointNode &node = i_path->at(i_currentNode);
             i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
Index: trunk/src/game/WorldSocketMgr.h
===================================================================
--- trunk/src/game/WorldSocketMgr.h (revision 2)
+++ trunk/src/game/WorldSocketMgr.h (revision 6)
@@ -17,31 +17,61 @@
  */
 
-/// \addtogroup u2w User to World Communication
-/// @{
-/// \file
+/** \addtogroup u2w User to World Communication
+ *  @{
+ *  \file WorldSocketMgr.h
+ *  \author Derex <derex101@gmail.com>
+ */
 
 #ifndef __WORLDSOCKETMGR_H
 #define __WORLDSOCKETMGR_H
 
-#include "Policies/Singleton.h"
+#include <ace/Basic_Types.h>
+#include <ace/Singleton.h>
+#include <ace/Thread_Mutex.h>
 
 class WorldSocket;
+class ReactorRunnable;
+class ACE_Event_Handler;
 
-/// Manages the list of connected WorldSockets
-class WorldSocketMgr
+/// Manages all sockets connected to peers and network threads
+class WorldSocketMgr 
 {
-    public:
-        WorldSocketMgr();
+public:
+  friend class WorldSocket;
+  friend class ACE_Singleton<WorldSocketMgr,ACE_Thread_Mutex>;
 
-        void AddSocket(WorldSocket *s);
-        void RemoveSocket(WorldSocket *s);
-        void Update(time_t diff);
-
-    private:
-        typedef std::set<WorldSocket*> SocketSet;
-        SocketSet m_sockets;
+  /// Start network, listen at address:port .
+  int StartNetwork (ACE_UINT16 port, const char* address);
+  
+  /// Stops all network threads, It will wait for all running threads .
+  void StopNetwork ();
+  
+  /// Wait untill all network threads have "joined" .
+  void Wait ();
+  
+  /// Make this class singleton .
+  static WorldSocketMgr* Instance ();
+  
+private:
+  int OnSocketOpen(WorldSocket* sock);
+  
+  int StartReactiveIO(ACE_UINT16 port, const char* address);
+  
+private:  
+  WorldSocketMgr ();
+  virtual ~WorldSocketMgr ();
+  
+  ReactorRunnable* m_NetThreads;
+  size_t m_NetThreadsCount;
+  
+  int m_SockOutKBuff;
+  int m_SockOutUBuff;
+  bool m_UseNoDelay;
+  
+  ACE_Event_Handler* m_Acceptor;
 };
 
-#define sWorldSocketMgr MaNGOS::Singleton<WorldSocketMgr>::Instance()
+#define sWorldSocketMgr WorldSocketMgr::Instance ()
+
 #endif
 /// @}
Index: trunk/src/game/GuardAI.cpp
===================================================================
--- trunk/src/game/GuardAI.cpp (revision 2)
+++ trunk/src/game/GuardAI.cpp (revision 6)
@@ -38,4 +38,8 @@
 void GuardAI::MoveInLineOfSight(Unit *u)
 {
+    // Ignore Z for flying creatures
+    if ( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
+        return;
+
     if( !i_creature.getVictim() && u->isTargetableForAttack() &&
         ( u->IsHostileToPlayers() || i_creature.IsHostileTo(u) /*|| u->getVictim() && i_creature.IsFriendlyTo(u->getVictim())*/ ) &&
@@ -43,5 +47,5 @@
     {
         float attackRadius = i_creature.GetAttackDistance(u);
-        if(i_creature.IsWithinDistInMap(u,attackRadius) && i_creature.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
+        if(i_creature.IsWithinDistInMap(u,attackRadius))
         {
             //Need add code to let guard support player
Index: trunk/src/game/Chat.cpp
===================================================================
--- trunk/src/game/Chat.cpp (revision 2)
+++ trunk/src/game/Chat.cpp (revision 6)
@@ -194,6 +194,7 @@
     {
         { "all",            SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllCommand,           "", NULL },
+        { "all_loot",       SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllLootCommand,       "", NULL },
+        { "all_npc",        SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllNpcCommand,        "", NULL },
         { "all_quest",      SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllQuestCommand,      "", NULL },
-        { "all_loot",       SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllLootCommand,       "", NULL },
         { "all_scripts",    SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllScriptsCommand,    "", NULL },
         { "all_spell",      SEC_ADMINISTRATOR,  &ChatHandler::HandleReloadAllSpellCommand,      "", NULL },
@@ -213,4 +214,5 @@
         { "fishing_loot_template",       SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesFishingCommand,    "", NULL },
         { "game_graveyard_zone",         SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGameGraveyardZoneCommand,       "", NULL },
+        { "game_tele",                   SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGameTeleCommand,                "", NULL },
         { "gameobject_involvedrelation", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadGOQuestInvRelationsCommand,     "", NULL },
         { "gameobject_loot_template",    SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL },
@@ -220,4 +222,7 @@
         { "item_loot_template",          SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesItemCommand,       "", NULL },
         { "mangos_string",               SEC_ADMINISTRATOR, &ChatHandler::HandleReloadMangosStringCommand,            "", NULL },
+        { "npc_gossip",                  SEC_ADMINISTRATOR, &ChatHandler::HandleReloadNpcGossipCommand,               "", NULL },
+        { "npc_trainer",                 SEC_ADMINISTRATOR, &ChatHandler::HandleReloadNpcTrainerCommand,              "", NULL },
+        { "npc_vendor",                  SEC_ADMINISTRATOR, &ChatHandler::HandleReloadNpcVendorCommand,               "", NULL },
         { "page_text",                   SEC_ADMINISTRATOR, &ChatHandler::HandleReloadPageTextsCommand,               "", NULL },
         { "pickpocketing_loot_template", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL},
@@ -265,4 +270,12 @@
     };
 
+    static ChatCommand lookupPlayerCommandTable[] =
+    {
+        { "ip",            SEC_GAMEMASTER,     &ChatHandler::HandleLookupPlayerIpCommand,       "", NULL },
+        { "account",       SEC_GAMEMASTER,     &ChatHandler::HandleLookupPlayerAccountCommand,  "", NULL },
+        { "email",         SEC_GAMEMASTER,     &ChatHandler::HandleLookupPlayerEmailCommand,    "", NULL },
+        { NULL,            0,                  NULL,                                            "", NULL }
+    };
+
     static ChatCommand lookupCommandTable[] =
     {
@@ -275,4 +288,5 @@
         { "object",         SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupObjectCommand,        "", NULL },
         { "quest",          SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupQuestCommand,         "", NULL },
+        { "player",         SEC_GAMEMASTER,     NULL,                                           "", lookupPlayerCommandTable },
         { "skill",          SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupSkillCommand,         "", NULL },
         { "spell",          SEC_ADMINISTRATOR,  &ChatHandler::HandleLookupSpellCommand,         "", NULL },
@@ -1102,2 +1116,16 @@
 }
 
+GameTele const* ChatHandler::extractGameTeleFromLink(char* text)
+{
+    // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
+    char* cId = extractKeyFromLink(text,"Htele");
+    if(!cId)
+        return false;
+
+    // id case (explicit or from shift link)
+    if(cId[0] >= '0' || cId[0] >= '9')
+        if(uint32 id = atoi(cId))
+            return objmgr.GetGameTele(id);
+
+    return objmgr.GetGameTele(cId);
+}
Index: trunk/src/game/GossipDef.h
===================================================================
--- trunk/src/game/GossipDef.h (revision 2)
+++ trunk/src/game/GossipDef.h (revision 6)
@@ -109,7 +109,12 @@
         void AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded = false);
 
-        unsigned int MenuItemCount()
+        unsigned int MenuItemCount() const
         {
             return m_gItems.size();
+        }
+
+        bool Empty() const
+        {
+            return m_gItems.empty();
         }
 
@@ -138,8 +143,14 @@
         void ClearMenu();
 
-        uint8 MenuItemCount()
+        uint8 MenuItemCount() const
         {
             return m_qItems.size();
         }
+
+        bool Empty() const
+        {
+            return m_qItems.empty();
+        }
+
         bool HasItem( uint32 questid );
 
@@ -156,6 +167,6 @@
 {
     private:
-        GossipMenu* pGossipMenu;
-        QuestMenu* pQuestMenu;
+        GossipMenu mGossipMenu;
+        QuestMenu  mQuestMenu;
         WorldSession* pSession;
 
@@ -164,6 +175,8 @@
         ~PlayerMenu();
 
-        GossipMenu* GetGossipMenu() { return pGossipMenu; }
-        QuestMenu* GetQuestMenu() { return pQuestMenu; }
+        GossipMenu& GetGossipMenu() { return mGossipMenu; }
+        QuestMenu& GetQuestMenu() { return mQuestMenu; }
+
+        bool Empty() const { return mGossipMenu.Empty() && mQuestMenu.Empty(); }
 
         void ClearMenus();
Index: trunk/src/game/Player.h
===================================================================
--- trunk/src/game/Player.h (revision 2)
+++ trunk/src/game/Player.h (revision 6)
@@ -671,5 +671,5 @@
 {
     ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {}
-    bool isContainedIn(std::vector<ItemPosCount>&);
+    bool isContainedIn(std::vector<ItemPosCount> const& vec) const;
     uint16 pos;
     uint8 count;
@@ -1742,5 +1742,7 @@
         uint32 GetShieldBlockValue() const;                 // overwrite Unit version (virtual)
         bool CanParry() const { return m_canParry; }
-        void SetCanParry(bool value) { m_canParry = value; }
+        void SetCanParry(bool value);
+        bool CanBlock() const { return m_canBlock; }
+        void SetCanBlock(bool value);
         bool CanDualWield() const { return m_canDualWield; }
         void SetCanDualWield(bool value) { m_canDualWield = value; }
@@ -2202,4 +2204,5 @@
         uint32 m_ArmorProficiency;
         bool m_canParry;
+        bool m_canBlock;
         bool m_canDualWield;
         uint8 m_swingErrorMsg;
Index: trunk/src/game/GossipDef.cpp
===================================================================
--- trunk/src/game/GossipDef.cpp (revision 2)
+++ trunk/src/game/GossipDef.cpp (revision 6)
@@ -92,36 +92,32 @@
 }
 
-PlayerMenu::PlayerMenu( WorldSession *Session )
-{
-    pGossipMenu = new GossipMenu();
-    pQuestMenu  = new QuestMenu();
-    pSession    = Session;
+PlayerMenu::PlayerMenu( WorldSession *session ) : pSession(session)
+{
 }
 
 PlayerMenu::~PlayerMenu()
 {
-    delete pGossipMenu;
-    delete pQuestMenu;
+    ClearMenus();
 }
 
 void PlayerMenu::ClearMenus()
 {
-    pGossipMenu->ClearMenu();
-    pQuestMenu->ClearMenu();
+    mGossipMenu.ClearMenu();
+    mQuestMenu.ClearMenu();
 }
 
 uint32 PlayerMenu::GossipOptionSender( unsigned int Selection )
 {
-    return pGossipMenu->MenuItemSender( Selection );
+    return mGossipMenu.MenuItemSender( Selection );
 }
 
 uint32 PlayerMenu::GossipOptionAction( unsigned int Selection )
 {
-    return pGossipMenu->MenuItemAction( Selection );
+    return mGossipMenu.MenuItemAction( Selection );
 }
 
 bool PlayerMenu::GossipOptionCoded( unsigned int Selection )
 {
-    return pGossipMenu->MenuItemCoded( Selection );
+    return mGossipMenu.MenuItemCoded( Selection );
 }
 
@@ -132,9 +128,9 @@
     data << uint32(0);                                      // new 2.4.0
     data << uint32( TitleTextId );
-    data << uint32( pGossipMenu->MenuItemCount() );         // max count 0x0F
-
-    for ( unsigned int iI = 0; iI < pGossipMenu->MenuItemCount(); iI++ )
-    {
-        GossipMenuItem const& gItem = pGossipMenu->GetItem(iI);
+    data << uint32( mGossipMenu.MenuItemCount() );         // max count 0x0F
+
+    for ( unsigned int iI = 0; iI < mGossipMenu.MenuItemCount(); iI++ )
+    {
+        GossipMenuItem const& gItem = mGossipMenu.GetItem(iI);
         data << uint32( iI );
         data << uint8( gItem.m_gIcon );
@@ -151,9 +147,9 @@
     }
 
-    data << uint32( pQuestMenu->MenuItemCount() );          // max count 0x20
-
-    for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ )
-    {
-        QuestMenuItem const& qItem = pQuestMenu->GetItem(iI);
+    data << uint32( mQuestMenu.MenuItemCount() );          // max count 0x20
+
+    for ( uint16 iI = 0; iI < mQuestMenu.MenuItemCount(); iI++ )
+    {
+        QuestMenuItem const& qItem = mQuestMenu.GetItem(iI);
         uint32 questID = qItem.m_qId;
         Quest const* pQuest = objmgr.GetQuestTemplate(questID);
@@ -358,9 +354,10 @@
     data << uint32(eEmote._Delay );                         // player emote
     data << uint32(eEmote._Emote );                         // NPC emote
-    data << uint8 ( pQuestMenu->MenuItemCount() );
-
-    for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ )
-    {
-        QuestMenuItem qmi=pQuestMenu->GetItem(iI);
+    data << uint8 ( mQuestMenu.MenuItemCount() );
+
+    for ( uint16 iI = 0; iI < mQuestMenu.MenuItemCount(); iI++ )
+    {
+        QuestMenuItem const& qmi = mQuestMenu.GetItem(iI);
+
         uint32 questID = qmi.m_qId;
         Quest const *pQuest = objmgr.GetQuestTemplate(questID);
Index: trunk/src/game/WorldSocket.cpp
===================================================================
--- trunk/src/game/WorldSocket.cpp (revision 2)
+++ trunk/src/game/WorldSocket.cpp (revision 6)
@@ -1,3 +1,3 @@
-/*
+/* 
  * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
  *
@@ -17,25 +17,31 @@
  */
 
-/** \file
-    \ingroup u2w
-*/
-
 #include "Common.h"
-#include "Log.h"
+#include "WorldSocket.h" 
+#include <ace/Message_Block.h>
+#include <ace/OS_NS_string.h>
+#include <ace/OS_NS_unistd.h>
+#include <ace/os_include/arpa/os_inet.h>
+#include <ace/os_include/netinet/os_tcp.h>
+#include <ace/os_include/sys/os_types.h>
+#include <ace/os_include/sys/os_socket.h>
+#include <ace/OS_NS_string.h>
+#include <ace/Reactor.h>
+#include <ace/Auto_Ptr.h>
+
+#include "Util.h"
+#include "World.h"
+#include "WorldPacket.h"
+#include "SharedDefines.h"
+#include "ByteBuffer.h"
+#include "AddonHandler.h"
 #include "Opcodes.h"
 #include "Database/DatabaseEnv.h"
 #include "Auth/Sha1.h"
-#include "WorldPacket.h"
-#include "WorldSocket.h"
 #include "WorldSession.h"
-#include "World.h"
 #include "WorldSocketMgr.h"
-#include "Policies/SingletonImp.h"
+#include "Log.h"
 #include "WorldLog.h"
-#include "AddonHandler.h"
-#include "sockets/Utility.h"
-#include "Util.h"
-
-// 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
+
 #if defined( __GNUC__ )
 #pragma pack(1)
@@ -44,19 +50,16 @@
 #endif
 
-/// Client Packet Header
+struct ServerPktHeader
+{
+  ACE_UINT16 size;
+  ACE_UINT16 cmd;
+};
+
 struct ClientPktHeader
 {
-    uint16 size;
-    uint32 cmd;
+  ACE_UINT16 size;
+  ACE_UINT32 cmd;
 };
 
-/// Server Packet Header
-struct ServerPktHeader
-{
-    uint16 size;
-    uint16 cmd;
-};
-
-// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
 #if defined( __GNUC__ )
 #pragma pack()
@@ -65,600 +68,1022 @@
 #endif
 
-#define SOCKET_CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S));
-
-/// WorldSocket construction and initialization.
-WorldSocket::WorldSocket(ISocketHandler &sh): TcpSocket(sh), _cmd(0), _remaining(0), _session(NULL)
-{
-    _seed = static_cast<uint32>(rand32());
-    m_LastPingMSTime = 0;                                   // first time it will counted as overspeed maybe, but this is not important
-    m_OverSpeedPings = 0;
-
-    if (sWorld.getConfig(CONFIG_TCP_NO_DELAY))
-        SetTcpNodelay(true);
-}
-
-/// WorldSocket destructor
-WorldSocket::~WorldSocket()
-{
-    if(_session)
-        _session->SetSocket(0);
-
-    WorldPacket *packet;
-
-    ///- Go through the to-be-sent queue and delete remaining packets
-    while(!_sendQueue.empty())
-    {
-        packet = _sendQueue.next();
-        delete packet;
-    }
-}
-
-/// Copy the packet to the to-be-sent queue
-void WorldSocket::SendPacket(WorldPacket const* packet)
-{
-    WorldPacket *pck = new WorldPacket(*packet);
-    ASSERT(pck);
-    _sendQueue.add(pck);
-}
-
-/// On client connection
-void WorldSocket::OnAccept()
-{
-    ///- Add the current socket to the list of sockets to be managed (WorldSocketMgr)
-    sWorldSocketMgr.AddSocket(this);
-    Utility::ResolveLocal();
-
-    ///- Send a AUTH_CHALLENGE packet
-    WorldPacket packet( SMSG_AUTH_CHALLENGE, 4 );
-    packet << _seed;
-
-    SendPacket(&packet);
-}
-
-/// Read the client transmitted data
-void WorldSocket::OnRead()
-{
-    TcpSocket::OnRead();
-
-    while(1)
-    {
-        ///- Read the packet header and decipher it (if needed)
-        if (!_remaining)
-        {
-            if (ibuf.GetLength() < 6)
-                break;
-
-            ClientPktHeader hdr;
-
-            ibuf.Read((char *)&hdr, 6);
-            _crypt.DecryptRecv((uint8 *)&hdr, 6);
-
-            _remaining = ntohs(hdr.size) - 4;
-            _cmd = hdr.cmd;
-        }
-
-        if (ibuf.GetLength() < _remaining)
-            break;
-
-        ///- Read the remaining of the packet
-        WorldPacket packet((uint16)_cmd, _remaining);
-
-        packet.resize(_remaining);
-        if(_remaining) ibuf.Read((char*)packet.contents(), _remaining);
-        _remaining = 0;
-
-        ///- If log of world packets is enable, log the incoming packet
-        if( sWorldLog.LogWorld() )
-        {
-            sWorldLog.Log("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n",
-                (uint32)GetSocket(),
-                packet.size(),
-                LookupOpcodeName(packet.GetOpcode()),
-                packet.GetOpcode());
-
-            uint32 p = 0;
-            while (p < packet.size())
+// used when testing to alow login without password and encryption
+// #define _NETCODE_FAKE_AUTH
+
+WorldSocket::WorldSocket (void) :
+WorldHandler (),
+m_Session (0),
+m_RecvWPct (0),
+m_RecvPct (),
+m_Header (sizeof (ClientPktHeader)),
+m_OutBuffer (0),
+m_OutBufferSize (65536),
+m_OutActive (false),
+m_Seed (static_cast<uint32> (rand32 ())),
+m_OverSpeedPings (0),
+m_LastPingTime (ACE_Time_Value::zero)
+{
+  this->reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
+}
+
+WorldSocket::~WorldSocket (void)
+{
+  if (m_RecvWPct)
+    delete m_RecvWPct;
+
+  if (m_OutBuffer)
+    m_OutBuffer->release ();
+
+  this->closing_ = true;
+
+  this->peer ().close ();
+
+  WorldPacket* pct;
+  while (m_PacketQueue.dequeue_head (pct) == 0)
+    delete pct;
+}
+
+bool
+WorldSocket::IsClosed (void) const
+{
+  return this->closing_;
+}
+
+void
+WorldSocket::CloseSocket (void)
+{
+  {
+    ACE_GUARD (LockType, Guard, m_OutBufferLock);
+
+    if (this->closing_)
+      return;
+
+    this->closing_ = true;
+
+    this->peer ().close_writer ();
+  }
+
+  {
+    ACE_GUARD (LockType, Guard, m_SessionLock);
+
+    m_Session = NULL;
+  }
+
+}
+
+const std::string&
+WorldSocket::GetRemoteAddress (void) const
+{
+  return m_Address;
+}
+
+int
+WorldSocket::SendPacket (const WorldPacket& pct)
+{
+  ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1);
+
+  if (this->closing_)
+    return -1;
+
+  // Dump outgoing packet.
+  if (sWorldLog.LogWorld ())
+    {
+      sWorldLog.Log ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n",
+                     (uint32) get_handle (),
+                     pct.size (),
+                     LookupOpcodeName (pct.GetOpcode ()),
+                     pct.GetOpcode ());
+
+      uint32 p = 0;
+      while (p < pct.size ())
+        {
+          for (uint32 j = 0; j < 16 && p < pct.size (); j++)
+            sWorldLog.Log ("%.2X ", const_cast<WorldPacket&>(pct)[p++]);
+
+          sWorldLog.Log ("\n");
+        }
+
+      sWorldLog.Log ("\n\n");
+    }
+
+  if (iSendPacket (pct) == -1)
+    {
+      WorldPacket* npct;
+
+      ACE_NEW_RETURN (npct, WorldPacket (pct), -1);
+
+      // NOTE maybe check of the size of the queue can be good ?
+      // to make it bounded instead of unbounded
+      if (m_PacketQueue.enqueue_tail (npct) == -1)
+        {
+          delete npct;
+          sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed");
+          return -1;
+        }
+    }
+
+  return 0;
+}
+
+long
+WorldSocket::AddReference (void)
+{
+  return static_cast<long> (this->add_reference ());
+}
+
+long
+WorldSocket::RemoveReference (void)
+{
+  return static_cast<long> (this->remove_reference ());
+}
+
+int
+WorldSocket::open (void *a)
+{
+  ACE_UNUSED_ARG (a);
+
+  // Prevent double call to this func.
+  if (m_OutBuffer)
+    return -1;
+
+  // This will also prevent the socket from being Updated
+  // while we are initializing it.
+  m_OutActive = true;
+
+  // Hook for the manager.
+  if (sWorldSocketMgr->OnSocketOpen (this) == -1)
+    return -1;
+
+  // Allocate the buffer.
+  ACE_NEW_RETURN (m_OutBuffer, ACE_Message_Block (m_OutBufferSize), -1);
+
+  // Store peer address.
+  ACE_INET_Addr remote_addr;
+
+  if (this->peer ().get_remote_addr (remote_addr) == -1)
+    {
+      sLog.outError ("WorldSocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno));
+      return -1;
+    }
+
+  m_Address = remote_addr.get_host_addr ();
+
+  // Send startup packet.
+  WorldPacket packet (SMSG_AUTH_CHALLENGE, 4);
+  packet << m_Seed;
+
+  if (SendPacket (packet) == -1)
+    return -1;
+
+  // Register with ACE Reactor
+  if (this->reactor ()->register_handler
+      (this,
+       ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1)
+    {
+      sLog.outError ("WorldSocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno));
+      return -1;
+    }
+
+  // reactor takes care of the socket from now on
+  this->remove_reference ();
+
+  return 0;
+}
+
+int
+WorldSocket::close (int)
+{
+  this->shutdown ();
+
+  this->closing_ = true;
+
+  this->remove_reference ();
+
+  return 0;
+}
+
+int
+WorldSocket::handle_input (ACE_HANDLE)
+{
+  if (this->closing_)
+    return -1;
+
+  switch (this->handle_input_missing_data ())
+    {
+    case -1 :
+      {
+        if ((errno == EWOULDBLOCK) ||
+            (errno == EAGAIN))
+          {
+            //return 0;
+            return this->Update (); // interesting line ,isnt it ?
+          }
+
+        DEBUG_LOG ("WorldSocket::handle_input: Peer error closing connection errno = %s", ACE_OS::strerror (errno));
+
+        return -1;
+      }
+    case 0:
+      {
+        DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection\n");
+
+        errno = ECONNRESET;
+
+        return -1;
+      }
+    case 1:
+      return 1;
+    }
+
+  //return 0;
+  return this->Update (); // another interesting line ;)
+}
+
+int
+WorldSocket::handle_output (ACE_HANDLE)
+{
+  ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1);
+
+  if (this->closing_)
+    return -1;
+
+  const size_t send_len = m_OutBuffer->length ();
+
+  if (send_len == 0)
+    return this->cancel_wakeup_output (Guard);
+  
+// TODO SO_NOSIGPIPE on platforms that support it
+#ifdef MSG_NOSIGNAL
+  ssize_t n = this->peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL);
+#else
+  ssize_t n = this->peer ().send (m_OutBuffer->rd_ptr (), send_len);
+#endif // MSG_NOSIGNAL
+          
+  if (n == 0)
+    return -1;
+  else if (n == -1)
+    {
+      if (errno == EWOULDBLOCK || errno == EAGAIN)
+        return this->schedule_wakeup_output (Guard);
+
+      return -1;
+    }
+  else if (n < send_len) //now n > 0
+    {
+      m_OutBuffer->rd_ptr (static_cast<size_t> (n));
+
+      // move the data to the base of the buffer
+      m_OutBuffer->crunch ();
+
+      return this->schedule_wakeup_output (Guard);
+    }
+  else //now n == send_len
+    {
+      m_OutBuffer->reset ();
+
+      if (!iFlushPacketQueue ())
+        return this->cancel_wakeup_output (Guard);
+      else
+        return this->schedule_wakeup_output (Guard);
+    }
+
+  ACE_NOTREACHED (return 0);
+}
+
+int
+WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
+{
+  // Critical section
+  {
+    ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1);
+
+    this->closing_ = true;
+
+    if (h == ACE_INVALID_HANDLE)
+      this->peer ().close_writer ();
+  }
+
+  // Critical section
+  {
+    ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
+
+    m_Session = NULL;
+  }
+
+  return 0;
+}
+
+int
+WorldSocket::Update (void)
+{
+  if (this->closing_)
+    return -1;
+
+  if (m_OutActive || m_OutBuffer->length () == 0)
+    return 0;
+
+  return this->handle_output (this->get_handle ());
+}
+
+int
+WorldSocket::handle_input_header (void)
+{
+  ACE_ASSERT (m_RecvWPct == NULL);
+
+  if (m_Header.length () != sizeof (ClientPktHeader))
+    {
+      sLog.outError ("WorldSocket::handle_input_header: internal error: invalid header");
+      errno = EINVAL;
+      return -1;
+    }
+
+  m_Crypt.DecryptRecv ((ACE_UINT8*) m_Header.rd_ptr (), sizeof (ClientPktHeader));
+
+  ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr ());
+
+  header.size = ACE_NTOHS (header.size);
+
+#if ACE_BYTE_ORDER == ACE_BIG_ENDIAN
+  header.cmd = ACE_SWAP_LONG (header.cmd)
+#endif // ACE_BIG_ENDIAN
+
+  if ((header.size < 4) ||
+      (header.size > 10240) ||
+      (header.cmd <= 0) ||
+      (header.cmd > 10240)
+      )
+    {
+      sLog.outError ("WorldSocket::handle_input_header: client sent mailformed packet size = %d , cmd = %d",
+                     header.size,
+                     header.cmd);
+
+      errno = EINVAL;
+      return -1;
+    }
+
+  header.size -= 4;
+
+  ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1);
+
+  if(header.size > 0)
+  {
+     m_RecvWPct->resize (header.size);  
+     m_RecvPct.base ((char*) m_RecvWPct->contents (), m_RecvWPct->size ());
+  }
+  else
+  {
+     ACE_ASSERT(m_RecvPct.space() == 0);
+  }
+
+
+  return 0;
+}
+
+int
+WorldSocket::handle_input_payload (void)
+{
+  // set errno properly here on error !!!
+  // now have a header and payload
+
+  ACE_ASSERT (m_RecvPct.space () == 0);
+  ACE_ASSERT (m_Header.space () == 0);
+  ACE_ASSERT (m_RecvWPct != NULL);
+
+  const int ret = this->ProcessIncoming (m_RecvWPct);
+
+  m_RecvPct.base (NULL, 0);
+  m_RecvPct.reset ();
+  m_RecvWPct = NULL;
+
+  m_Header.reset ();
+
+  if (ret == -1)
+    errno = EINVAL;
+
+  return ret;
+}
+
+int
+WorldSocket::handle_input_missing_data (void)
+{
+  char buf [1024];
+
+  ACE_Data_Block db (sizeof (buf),
+                     ACE_Message_Block::MB_DATA,
+                     buf,
+                     0,
+                     0,
+                     ACE_Message_Block::DONT_DELETE,
+                     0);
+
+  ACE_Message_Block message_block (&db,
+                                   ACE_Message_Block::DONT_DELETE,
+                                   0);
+
+  const size_t recv_size = message_block.space ();
+
+  const ssize_t n = this->peer ().recv (message_block.wr_ptr (),
+                                        recv_size);
+
+  if (n <= 0)
+    return n;
+
+  message_block.wr_ptr (n);
+
+  while (message_block.length () > 0)
+    {
+      if (m_Header.space () > 0)
+        {
+          //need to recieve the header
+          const size_t to_header = (message_block.length () > m_Header.space () ? m_Header.space () : message_block.length ());
+          m_Header.copy (message_block.rd_ptr (), to_header);
+          message_block.rd_ptr (to_header);
+
+          if (m_Header.space () > 0)
             {
-                for (uint32 j = 0; j < 16 && p < packet.size(); j++)
-                    sWorldLog.Log("%.2X ", packet[p++]);
-                sWorldLog.Log("\n");
+              //couldnt recieve the whole header this time
+              ACE_ASSERT (message_block.length () == 0);
+              errno = EWOULDBLOCK;
+              return -1;
             }
-            sWorldLog.Log("\n\n");
-        }
-
-        ///- If the packet is PING, KEEP_ALIVE or AUTH_SESSION, handle immediately
-        switch (_cmd)
-        {
-            case CMSG_KEEP_ALIVE:
-                break;                                      // just ignore, network connectivity timeout preventing
-            case CMSG_PING:
+
+          //we just recieved nice new header
+          if (this->handle_input_header () == -1)
             {
-                _HandlePing(packet);
-                break;
+              ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN));
+              return -1;
             }
-            case CMSG_AUTH_SESSION:
+        }
+
+      // Its possible on some error situations that this happens
+      // for example on closing when epoll recieves more chunked data and stuff
+      // hope this is not hack ,as proper m_RecvWPct is asserted around
+      if (!m_RecvWPct)
+        {
+          sLog.outError ("Forsing close on input m_RecvWPct = NULL");
+          errno = EINVAL;
+          return -1;
+        }
+
+      // We have full readed header, now check the data payload
+      if (m_RecvPct.space () > 0)
+        {
+          //need more data in the payload
+          const size_t to_data = (message_block.length () > m_RecvPct.space () ? m_RecvPct.space () : message_block.length ());
+          m_RecvPct.copy (message_block.rd_ptr (), to_data);
+          message_block.rd_ptr (to_data);
+
+          if (m_RecvPct.space () > 0)
             {
-                _HandleAuthSession(packet);
-                break;
+              //couldnt recieve the whole data this time
+              ACE_ASSERT (message_block.length () == 0);
+              errno = EWOULDBLOCK;
+              return -1;
             }
-            default:
+        }
+
+      //just recieved fresh new payload
+      if (this->handle_input_payload () == -1)
+        {
+          ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN));
+          return -1;
+        }
+    }
+
+  return n == recv_size ? 1 : 2;
+}
+
+int
+WorldSocket::cancel_wakeup_output (GuardType& g)
+{
+  if (!m_OutActive)
+    return 0;
+
+  m_OutActive = false;
+
+  g.release ();
+
+  if (this->reactor ()->cancel_wakeup
+      (this, ACE_Event_Handler::WRITE_MASK) == -1)
+    {
+      // would be good to store errno from reactor with errno guard
+      sLog.outError ("WorldSocket::cancel_wakeup_output");
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+WorldSocket::schedule_wakeup_output (GuardType& g)
+{
+  if (m_OutActive)
+    return 0;
+
+  m_OutActive = true;
+
+  g.release ();
+
+  if (this->reactor ()->schedule_wakeup
+      (this, ACE_Event_Handler::WRITE_MASK) == -1)
+    {
+      sLog.outError ("WorldSocket::schedule_wakeup_output");
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+WorldSocket::ProcessIncoming (WorldPacket* new_pct)
+{
+  ACE_ASSERT (new_pct);
+  
+  // manage memory ;)
+  ACE_Auto_Ptr<WorldPacket> aptr (new_pct);
+
+  const ACE_UINT16 opcode = new_pct->GetOpcode ();
+
+  if (this->closing_)
+    return -1;
+
+  // dump recieved packet
+  if (sWorldLog.LogWorld ())
+    {
+      sWorldLog.Log ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n",
+                     (uint32) get_handle (),
+                     new_pct->size (),
+                     LookupOpcodeName (new_pct->GetOpcode ()),
+                     new_pct->GetOpcode ());
+
+      uint32 p = 0;
+      while (p < new_pct->size ())
+        {
+          for (uint32 j = 0; j < 16 && p < new_pct->size (); j++)
+            sWorldLog.Log ("%.2X ", (*new_pct)[p++]);
+          sWorldLog.Log ("\n");
+        }
+      sWorldLog.Log ("\n\n");
+    }
+
+  // like one switch ;)
+  if (opcode == CMSG_PING)
+    {
+      return HandlePing (*new_pct);
+    }
+  else if (opcode == CMSG_AUTH_SESSION)
+    {
+      if (m_Session)
+        {
+          sLog.outError ("WorldSocket::ProcessIncoming: Player send CMSG_AUTH_SESSION again");
+          return -1;
+        }
+
+      return HandleAuthSession (*new_pct);
+    }
+  else if (opcode == CMSG_KEEP_ALIVE)
+    {
+      DEBUG_LOG ("CMSG_KEEP_ALIVE ,size: %d", new_pct->size ());
+
+      return 0;
+    }
+  else
+    {
+      ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
+
+      if (m_Session != NULL)
+        {
+          // OK ,give the packet to WorldSession
+          aptr.release ();
+          // WARNINIG here we call it with locks held.
+          // Its possible to cause deadlock if QueuePacket calls back
+          m_Session->QueuePacket (new_pct);
+          return 0;
+        }
+      else
+        {
+          sLog.outError ("WorldSocket::ProcessIncoming: Client not authed opcode = ", opcode);
+          return -1;
+        }
+    }
+
+  ACE_NOTREACHED (return 0);
+}
+
+int
+WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
+{
+  uint8 digest[20];
+  uint32 clientSeed;
+  uint32 unk2;
+  uint32 BuiltNumberClient;
+  uint32 id, security;
+  bool tbc = false;
+  LocaleConstant locale;
+  std::string account;
+  Sha1Hash sha1;
+  BigNumber v, s, g, N, x, I;
+  WorldPacket packet, SendAddonPacked;
+
+  BigNumber K;
+
+  if (recvPacket.size () < (4 + 4 + 1 + 4 + 20))
+    {
+      sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size");
+      return -1;
+    }
+
+  // Read the content of the packet
+  recvPacket >> BuiltNumberClient; // for now no use
+  recvPacket >> unk2;
+  recvPacket >> account;
+
+  if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20))
+    {
+      sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check");
+      return -1;
+    }
+
+  recvPacket >> clientSeed;
+  recvPacket.read (digest, 20);
+
+  DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u",
+             BuiltNumberClient,
+             unk2,
+             account.c_str (),
+             clientSeed);
+
+#if defined _NETCODE_FAKE_AUTH
+  bool dontchechtheacc = false;
+  uint8 digest_fake[sizeof (digest)];
+  memset ((void*) digest_fake, '\0', sizeof (digest_fake));
+  if (memcmp ((void*) digest, (void*) digest_fake, sizeof (digest_fake)) == 0)
+    {
+      dontchechtheacc = true;
+    }
+#endif //_NETCODE_FAKE_AUTH
+
+  // Get the account information from the realmd database
+  std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
+  loginDatabase.escape_string (safe_account);
+  // No SQL injection, username escaped.
+
+  QueryResult *result =
+          loginDatabase.PQuery ("SELECT "
+                                "id, " //0
+                                "gmlevel, " //1
+                                "sessionkey, " //2
+                                "last_ip, " //3
+                                "locked, " //4
+                                "sha_pass_hash, " //5
+                                "v, " //6
+                                "s, " //7
+                                "tbc, " //8
+                                "mutetime, " //9
+                                "locale " //10
+                                "FROM account "
+                                "WHERE username = '%s'",
+                                safe_account.c_str ());
+
+  // Stop if the account is not found
+  if (!result)
+    {
+      packet.Initialize (SMSG_AUTH_RESPONSE, 1);
+      packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
+
+      SendPacket (packet);
+
+      sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
+      return -1;
+    }
+
+  Field* fields = result->Fetch ();
+
+  tbc = fields[8].GetUInt8 () && sWorld.getConfig (CONFIG_EXPANSION) > 0;
+
+  N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
+  g.SetDword (7);
+  I.SetHexStr (fields[5].GetString ());
+
+  //In case of leading zeros in the I hash, restore them
+  uint8 mDigest[SHA_DIGEST_LENGTH];
+  memset (mDigest, 0, SHA_DIGEST_LENGTH);
+
+  if (I.GetNumBytes () <= SHA_DIGEST_LENGTH)
+    memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ());
+
+  std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH);
+
+  s.SetHexStr (fields[7].GetString ());
+  sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ());
+  sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH);
+  sha1.Finalize ();
+  x.SetBinary (sha1.GetDigest (), sha1.GetLength ());
+  v = g.ModExp (x, N);
+
+  const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free()
+  const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free()
+  const char* vold = fields[6].GetString ();
+
+  DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v_old: %s v_new: %s",
+             sStr,
+             vold,
+             vStr);
+
+  loginDatabase.PExecute ("UPDATE account "
+                          "SET "
+                          "v = '0', "
+                          "s = '0' "
+                          "WHERE username = '%s'",
+                          safe_account.c_str ());
+
+#if defined _NETCODE_FAKE_AUTH
+  if (!dontchechtheacc)
+    {
+#endif
+      if (!vold || strcmp (vStr, vold))
+        {
+          packet.Initialize (SMSG_AUTH_RESPONSE, 1);
+          packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
+          SendPacket (packet);
+          delete result;
+          OPENSSL_free ((void*) sStr);
+          OPENSSL_free ((void*) vStr);
+
+          sLog.outError ("WorldSocket::HandleAuthSession: User not logged.");
+          return -1;
+        }
+#if defined _NETCODE_FAKE_AUTH
+    }
+#endif
+
+  OPENSSL_free ((void*) sStr);
+  OPENSSL_free ((void*) vStr);
+
+  ///- Re-check ip locking (same check as in realmd).
+  if (fields[4].GetUInt8 () == 1) // if ip is locked
+    {
+      if (strcmp (fields[3].GetString (), GetRemoteAddress ().c_str ()))
+        {
+          packet.Initialize (SMSG_AUTH_RESPONSE, 1);
+          packet << uint8 (AUTH_FAILED);
+          SendPacket (packet);
+
+          delete result;
+          sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs).");
+          return -1;
+        }
+    }
+
+  id = fields[0].GetUInt32 ();
+  security = fields[1].GetUInt16 ();
+  K.SetHexStr (fields[2].GetString ());
+
+  time_t mutetime = time_t (fields[9].GetUInt64 ());
+
+  locale = LocaleConstant (fields[10].GetUInt8 ());
+  if (locale >= MAX_LOCALE)
+    locale = LOCALE_enUS;
+
+  delete result;
+
+#if defined _NETCODE_FAKE_AUTH
+  if (!dontchechtheacc)
+    {
+#endif
+      // Re-check account ban (same check as in realmd) 
+      QueryResult *banresult =
+              loginDatabase.PQuery ("SELECT "
+                                    "bandate, "
+                                    "unbandate "
+                                    "FROM account_banned "
+                                    "WHERE id = '%u' "
+                                    "AND active = 1",
+                                    id);
+
+      if (banresult) // if account banned
+        {
+          packet.Initialize (SMSG_AUTH_RESPONSE, 1);
+          packet << uint8 (AUTH_BANNED);
+          SendPacket (packet);
+
+          delete banresult;
+
+          sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
+          return -1;
+        }
+
+      // Check locked state for server
+      AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit ();
+
+      if (allowedAccountType > SEC_PLAYER && security < allowedAccountType)
+        {
+          WorldPacket Packet (SMSG_AUTH_RESPONSE, 1);
+          Packet << uint8 (AUTH_UNAVAILABLE);
+
+          SendPacket (packet);
+
+          sLog.outBasic ("WorldSocket::HandleAuthSession: User tryes to login but his security level is not enough");
+          return -1;
+        }
+
+      // Check that Key and account name are the same on client and server
+      Sha1Hash sha;
+
+      uint32 t = 0;
+      uint32 seed = m_Seed;
+
+      sha.UpdateData (account);
+      sha.UpdateData ((uint8 *) & t, 4);
+      sha.UpdateData ((uint8 *) & clientSeed, 4);
+      sha.UpdateData ((uint8 *) & seed, 4);
+      sha.UpdateBigNumbers (&K, NULL);
+      sha.Finalize ();
+
+      if (memcmp (sha.GetDigest (), digest, 20))
+        {
+          packet.Initialize (SMSG_AUTH_RESPONSE, 1);
+          packet << uint8 (AUTH_FAILED);
+
+          SendPacket (packet);
+
+          sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed).");
+          return -1;
+        }
+#if defined _NETCODE_FAKE_AUTH
+    }
+#endif
+
+  std::string address = this->GetRemoteAddress ();
+
+  DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
+             account.c_str (),
+             address.c_str ());
+
+  // Update the last_ip in the database
+  // No SQL injection, username escaped.
+  loginDatabase.escape_string (address);
+
+  loginDatabase.PExecute ("UPDATE account "
+                          "SET last_ip = '%s' "
+                          "WHERE username = '%s'",
+                          address.c_str (),
+                          safe_account.c_str ());
+
+  // TODO protect here probably ?
+  // Althought atm the socket is singlethreaded
+  ACE_NEW_RETURN (m_Session, WorldSession (id, this, security, tbc, mutetime, locale), -1);
+
+#if defined _NETCODE_FAKE_AUTH
+  if (!dontchechtheacc)
+    {
+#endif
+      this->m_Crypt.SetKey (&K);
+      this->m_Crypt.Init ();
+#if defined _NETCODE_FAKE_AUTH
+    }
+#endif
+
+  // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec
+  ACE_OS::sleep (ACE_Time_Value (0, 10000));
+
+  // TODO error handling
+  sWorld.AddSession (this->m_Session);
+
+  // Create and send the Addon packet
+  if (sAddOnHandler.BuildAddonPacket (&recvPacket, &SendAddonPacked))
+    SendPacket (SendAddonPacked);
+
+  return 0;
+}
+
+int
+WorldSocket::HandlePing (WorldPacket& recvPacket)
+{
+  uint32 ping;
+  uint32 latency;
+
+  if (recvPacket.size () < 8)
+    {
+      sLog.outError ("WorldSocket::_HandlePing wrong packet size");
+      return -1;
+    }
+
+  // Get the ping packet content
+  recvPacket >> ping;
+  recvPacket >> latency;
+
+  if (m_LastPingTime == ACE_Time_Value::zero)
+    m_LastPingTime = ACE_OS::gettimeofday (); // for 1st ping
+  else
+    {
+      ACE_Time_Value cur_time = ACE_OS::gettimeofday ();
+      ACE_Time_Value diff_time (cur_time);
+      diff_time -= m_LastPingTime;
+      m_LastPingTime = cur_time;
+
+      if (diff_time < ACE_Time_Value (27))
+        {
+          ++m_OverSpeedPings;
+
+          uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS);
+
+          if (max_count && m_OverSpeedPings > max_count)
             {
-                ///- Else, put it in the world session queue for this user (need to be already authenticated)
-                if (_session)
-                    _session->QueuePacket(packet);
-                else
-                    sLog.outDetail("Received out of place packet with cmdid 0x%.4X", _cmd);
-                break;
+              ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
+
+              if (m_Session && m_Session->GetSecurity () == SEC_PLAYER)
+                {
+                  sLog.outError ("WorldSocket::HandlePing: Player kicked for "
+                                 "overspeeded pings adress = %s",
+                                 GetRemoteAddress ().c_str ());
+
+                  return -1;
+                }
             }
         }
-    }
-}
-
-/// On socket closing
-void WorldSocket::CloseSocket()
-{
-    ///- Set CloseAndDelete flag for TcpSocket class
-    SetCloseAndDelete(true);
-
-    ///- Set _session to NULL. Prevent crashes
-    _session = NULL;
-}
-
-/// On socket deleting
-void WorldSocket::OnDelete()
-{
-    ///- Stop sending remaining data through this socket
-    if (_session)
-    {
-        _session->SetSocket(NULL);
-        // Session deleted from World session list at socket==0, This is only back reference from socket to session.
-        _session = NULL;
-    }
-
-    ///- Remove the socket from the WorldSocketMgr list
-    sWorldSocketMgr.RemoveSocket(this);
-
-    ///- Removes socket from player queue
-    sWorld.RemoveQueuedPlayer(this);
-}
-
-/// Handle the client authentication packet
-void WorldSocket::_HandleAuthSession(WorldPacket& recvPacket)
-{
-    uint8 digest[20];
-    uint32 clientSeed;
-    uint32 unk2;
-    uint32 BuiltNumberClient;
-    uint32 id, security;
-    bool tbc = false;
-    std::string account;
-    Sha1Hash sha1;
-    BigNumber v, s, g, N, x, I;
-    WorldPacket packet, SendAddonPacked;
-
-    BigNumber K;
-
-    SOCKET_CHECK_PACKET_SIZE(recvPacket,4+4+1+4+20);
-
-    ///- Read the content of the packet
-    recvPacket >> BuiltNumberClient;                        // for now no use
-    recvPacket >> unk2;
-    recvPacket >> account;
-
-    // recheck size
-    SOCKET_CHECK_PACKET_SIZE(recvPacket,4+4+(account.size()+1)+4+20);
-
-    recvPacket >> clientSeed;
-    recvPacket.read(digest, 20);
-
-    sLog.outDebug("Auth: client %u, unk2 %u, account %s, clientseed %u", BuiltNumberClient, unk2, account.c_str(), clientSeed);
-
-    ///- Normalize account name
-    //utf8ToUpperOnlyLatin(account); -- client already send account in expected form
-
-    ///- Get the account information from the realmd database
-    std::string safe_account = account;                     // Duplicate, else will screw the SHA hash verification below
-    loginDatabase.escape_string(safe_account);
-    //No SQL injection, username escaped.
-    //                                                 0   1        2           3        4       5              6  7  8    9         10
-    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());
-
-    ///- Stop if the account is not found
-    if ( !result )
-    {
-        packet.Initialize( SMSG_AUTH_RESPONSE, 1 );
-        packet << uint8( AUTH_UNKNOWN_ACCOUNT );
-        SendPacket( &packet );
-        sLog.outDetail( "SOCKET: Sent Auth Response (unknown account)." );
-        return;
-    }
-
-    Field* fields = result->Fetch();
-
-    tbc = fields[8].GetUInt8() && sWorld.getConfig(CONFIG_EXPANSION) > 0;
-
-    N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
-    g.SetDword(7);
-    I.SetHexStr(fields[5].GetString());
-
-    //In case of leading zeros in the I hash, restore them
-    uint8 mDigest[SHA_DIGEST_LENGTH];
-    memset(mDigest,0,SHA_DIGEST_LENGTH);
-    if (I.GetNumBytes() <= SHA_DIGEST_LENGTH)
-        memcpy(mDigest,I.AsByteArray(),I.GetNumBytes());
-
-    std::reverse(mDigest,mDigest+SHA_DIGEST_LENGTH);
-
-    s.SetHexStr(fields[7].GetString());
-    sha1.UpdateData(s.AsByteArray(), s.GetNumBytes());
-    sha1.UpdateData(mDigest, SHA_DIGEST_LENGTH);
-    sha1.Finalize();
-    x.SetBinary(sha1.GetDigest(), sha1.GetLength());
-    v = g.ModExp(x, N);
-
-    const char* sStr = s.AsHexStr();                        //Must be freed by OPENSSL_free()
-    const char* vStr = v.AsHexStr();                        //Must be freed by OPENSSL_free()
-    const char* vold = fields[6].GetString();
-    sLog.outDebug("SOCKET: (s,v) check s: %s v_old: %s v_new: %s", sStr, vold, vStr );
-    loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE username = '%s'", safe_account.c_str());
-    if ( !vold || strcmp( vStr, vold ) )
-    {
-        packet.Initialize( SMSG_AUTH_RESPONSE, 1 );
-        packet << uint8( AUTH_UNKNOWN_ACCOUNT );
-        SendPacket( &packet );
-        sLog.outDetail( "SOCKET: User not logged.");
-        delete result;
-        OPENSSL_free((void*)sStr);
-        OPENSSL_free((void*)vStr);
-        return;
-    }
-    OPENSSL_free((void*)sStr);
-    OPENSSL_free((void*)vStr);
-
-    ///- Re-check ip locking (same check as in realmd).
-    if(fields[4].GetUInt8() == 1)                           // if ip is locked
-    {
-        if ( strcmp(fields[3].GetString(),GetRemoteAddress().c_str()) )
-        {
-            packet.Initialize( SMSG_AUTH_RESPONSE, 1 );
-            packet << uint8( AUTH_FAILED );
-            SendPacket( &packet );
-
-            sLog.outDetail( "SOCKET: Sent Auth Response (Account IP differs)." );
-            delete result;
-            return;
-        }
-    }
-
-    id = fields[0].GetUInt32();
-    security = fields[1].GetUInt16();
-    K.SetHexStr(fields[2].GetString());
-    time_t mutetime = time_t(fields[9].GetUInt64());
-
-    LocaleConstant locale = LocaleConstant(fields[10].GetUInt8());
-    if (locale>=MAX_LOCALE)
-        locale=LOCALE_enUS;
-
-    delete result;
-
-    ///- Re-check account ban (same check as in realmd) /// TO DO: why on earth do 2 checks for same thing?
-    QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = '%u' AND active = 1", id);
-    if(banresult)                                           // if account banned
-    {
-        packet.Initialize( SMSG_AUTH_RESPONSE, 1 );
-        packet << uint8( AUTH_BANNED );
-        SendPacket( &packet );
-
-        sLog.outDetail( "SOCKET: Sent Auth Response (Account banned)." );
-        delete banresult;
-        return;
-    }
-
-    ///- Check locked state for server
-    AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit();
-    if( allowedAccountType > SEC_PLAYER && security < allowedAccountType)
-    {
-        WorldPacket Packet(SMSG_AUTH_RESPONSE, 1);
-        Packet << uint8(AUTH_UNAVAILABLE);
-        SendPacket(&Packet);
-        return;
-    }
-
-    ///- kick already loaded player with same account (if any) and remove session
-    ///- if player is in loading and want to load again, return
-    if(!sWorld.RemoveSession(id))
-    {
-        return;
-    }
-
-    ///- Check that Key and account name are the same on client and server
-    Sha1Hash sha;
-
-    uint32 t = 0;
-    uint32 seed = _seed;
-
-    sha.UpdateData(account);
-    sha.UpdateData((uint8 *)&t, 4);
-    sha.UpdateData((uint8 *)&clientSeed, 4);
-    sha.UpdateData((uint8 *)&seed, 4);
-    sha.UpdateBigNumbers(&K, NULL);
-    sha.Finalize();
-
-    if (memcmp(sha.GetDigest(), digest, 20))
-    {
-        packet.Initialize( SMSG_AUTH_RESPONSE, 1 );
-        packet << uint8( AUTH_FAILED );
-        SendPacket( &packet );
-
-        sLog.outDetail( "SOCKET: Sent Auth Response (authentication failed)." );
-        return;
-    }
-
-    ///- Initialize the encryption with the Key
-    _crypt.SetKey(&K);
-    _crypt.Init();
-
-    ///- Send 'Auth is ok'
-    packet.Initialize( SMSG_AUTH_RESPONSE, 1+4+1+4+1 );
-    packet << uint8( AUTH_OK );
-    packet << uint32(0);                                    // unknown random value...
-    packet << uint8(0);                                     // can be 0 and 2
-    packet << uint32(0);                                    // const 0
-    packet << uint8(tbc ? 1 : 0);                           // 0 - normal, 1 - TBC, must be set in database manually for each account
-    SendPacket(&packet);
-
-    ///- Create a new WorldSession for the player and add it to the World
-    _session = new WorldSession(id, this,security,tbc,mutetime,locale);
-    sWorld.AddSession(_session);
-
-    if(sLog.IsOutDebug())                                   // optimize disabled debug output
-    {
-        sLog.outDebug( "SOCKET: Client '%s' authenticated successfully.", account.c_str() );
-        sLog.outDebug( "Account: '%s' Logged in from IP %s.", account.c_str(), GetRemoteAddress().c_str());
-    }
-
-    ///- Update the last_ip in the database
-    //No SQL injection, username escaped.
-    std::string address = GetRemoteAddress();
-    loginDatabase.escape_string(address);
-    loginDatabase.PExecute("UPDATE account SET last_ip = '%s' WHERE username = '%s'",address.c_str(), safe_account.c_str());
-
-    // do small delay (10ms) at accepting successful authed connection to prevent dropping packets by client
-    // don't must harm anyone (let login ~100 accounts in 1 sec ;) )
-    #ifdef WIN32
-    Sleep(10);
-    #else
-    ZThread::Thread::sleep(10);
-    #endif
-
-    ///- Check that we do not exceed the maximum number of online players in the realm
-    uint32 Sessions  = sWorld.GetActiveAndQueuedSessionCount();
-    uint32 pLimit    = sWorld.GetPlayerAmountLimit();
-    uint32 QueueSize = sWorld.GetQueueSize();               //number of players in the queue
-    bool   inQueue   = false;
-    --Sessions;                                             //so we don't count the user trying to login as a session and queue the socket that we are using
-
-    if( pLimit >  0 && Sessions >= pLimit && security == SEC_PLAYER )
-    {
-        sWorld.AddQueuedPlayer(this);
-        SendAuthWaitQue(sWorld.GetQueuePos(this));
-        sWorld.UpdateMaxSessionCounters();
-        sLog.outDetail( "PlayerQueue: %s is in Queue Position (%u).",safe_account.c_str(),++QueueSize);
-        inQueue = true;
-    }
-
-    ///- Create and send the Addon packet
-    if(sAddOnHandler.BuildAddonPacket(&recvPacket, &SendAddonPacked))
-        SendPacket(&SendAddonPacked);
-
-    if(inQueue)
-        return;
-
-    sWorld.UpdateMaxSessionCounters();
-
-    // Updates the population
-    if (pLimit > 0)
-    {
-        float popu = sWorld.GetActiveSessionCount();        //updated number of users on the server
-        popu /= pLimit;
-        popu *= 2;
-        loginDatabase.PExecute("UPDATE realmlist SET population = '%f' WHERE id = '%d'",popu,realmID);
-        sLog.outDetail( "Server Population (%f).",popu);
-    }
-
-    return;
-}
-
-/// Handle the Ping packet
-void WorldSocket::_HandlePing(WorldPacket& recvPacket)
-{
-    uint32 ping;
-    uint32 latency;
-
-    CHECK_PACKET_SIZE(recvPacket,8);
-
-    ///- Get the ping packet content
-    recvPacket >> ping;
-    recvPacket >> latency;
-
-    if (_session )
-        _session->SetLatency(latency);
-
-    ///- check ping speed for players
-    if(_session && _session->GetSecurity() == SEC_PLAYER)
-    {
-        uint32 cur_mstime = getMSTime();
-
-        // can overflow and start from 0
-        uint32 diff_mstime = getMSTimeDiff(m_LastPingMSTime,cur_mstime);
-        m_LastPingMSTime = cur_mstime;
-        if(diff_mstime < 27000)                             // should be 30000 (=30 secs), add little tolerance
-        {
-            ++m_OverSpeedPings;
-
-            uint32 max_count = sWorld.getConfig(CONFIG_MAX_OVERSPEED_PINGS);
-            if(max_count && m_OverSpeedPings > max_count)
+      else
+        m_OverSpeedPings = 0;
+    }
+
+  // critical section
+  {
+    ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
+
+    if (m_Session)
+      m_Session->SetLatency (latency);
+    else
+      {
+        sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, "
+                       "but is not authenticated or got recently kicked,"
+                       " adress = %s",
+                       this->GetRemoteAddress ().c_str ());
+        return -1;
+      }
+  }
+
+  WorldPacket packet (SMSG_PONG, 4);
+  packet << ping;
+  return this->SendPacket (packet);
+}
+
+int
+WorldSocket::iSendPacket (const WorldPacket& pct)
+{
+  if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader))
+    {
+      errno = ENOBUFS;
+      return -1;
+    }
+
+  ServerPktHeader header;
+
+  header.cmd = pct.GetOpcode ();
+
+#if ACE_BYTE_ORDER == ACE_BIG_ENDIAN
+  header.cmd = ACE_SWAP_WORD (header.cmd)
+#endif
+          
+  header.size = (uint16) pct.size () + 2;
+  header.size = ACE_HTONS (header.size);
+
+  m_Crypt.EncryptSend ((uint8*) & header, sizeof (header));
+
+  if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1)
+    ACE_ASSERT (false);
+
+  if (!pct.empty ())
+    if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1)
+      ACE_ASSERT (false);
+
+  return 0;
+}
+
+bool
+WorldSocket::iFlushPacketQueue ()
+{
+  WorldPacket *pct;
+  bool haveone = false;
+
+  while (m_PacketQueue.dequeue_head (pct) == 0)
+    {
+      if (iSendPacket (*pct) == -1)
+        {
+          if (m_PacketQueue.enqueue_head (pct) == -1)
             {
-                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());
-                _session->KickPlayer();
-                return;
+              delete pct;
+              sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head");
+              return false;
             }
-        }
-        else
-            m_OverSpeedPings = 0;
-
-    }
-
-    ///- And put the pong answer in the to-be-sent queue
-    WorldPacket packet( SMSG_PONG, 4 );
-    packet << ping;
-    SendPacket(&packet);
-
-    return;
-}
-
-/// Handle the update order for the socket
-void WorldSocket::SendSinglePacket()
-{
-    WorldPacket *packet;
-    ServerPktHeader hdr;
-
-    ///- If we have packet to send
-    if (!_sendQueue.empty())
-    {
-        packet = _sendQueue.next();
-
-        hdr.size = ntohs((uint16)packet->size() + 2);
-        hdr.cmd = packet->GetOpcode();
-
-        if( sWorldLog.LogWorld() )
-        {
-            sWorldLog.Log("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n",
-                (uint32)GetSocket(),
-                packet->size(),
-                LookupOpcodeName(packet->GetOpcode()),
-                packet->GetOpcode());
-
-            uint32 p = 0;
-            while (p < packet->size())
-            {
-                for (uint32 j = 0; j < 16 && p < packet->size(); j++)
-                    sWorldLog.Log("%.2X ", (*packet)[p++]);
-
-                sWorldLog.Log("\n");
-            }
-
-            sWorldLog.Log("\n\n");
-        }
-
-        ///- Encrypt (if needed) the header
-        _crypt.EncryptSend((uint8*)&hdr, 4);
-
-        ///- Send the header and body to the client
-        TcpSocket::SendBuf((char*)&hdr, 4);
-        if(!packet->empty()) TcpSocket::SendBuf((char*)packet->contents(), packet->size());
-
-        delete packet;
-    }
-}
-
-void WorldSocket::Update(time_t diff)
-{
-    const uint32 SEND_PACKETS_MAX = 100;
-    const uint32 SEND_BUFFER_SIZE = 1024;
-
-    uint8 sendBuffer[SEND_BUFFER_SIZE];
-
-    while (!_sendQueue.empty())
-    {
-        bool haveBigPacket = false;
-        uint32 bufferSize = 0;
-
-        ///- While we have packets to send
-        for (uint32 packetCount = 0; (packetCount < SEND_PACKETS_MAX) && !_sendQueue.empty(); packetCount++)
-        {
-            ServerPktHeader *hdr = (ServerPktHeader*)&sendBuffer[bufferSize];
-
-            // check merge possibility.
-            WorldPacket *front = _sendQueue.front();
-            uint32 packetSize = front->size();
-
-            if ((sizeof(*hdr) + packetSize) > SEND_BUFFER_SIZE)
-            {
-                haveBigPacket = true;
-                break;
-            }
-
-            if ((bufferSize + sizeof(*hdr) + packetSize) > sizeof(sendBuffer))
-                break;
-
-            // can be merged
-            WorldPacket *packet = _sendQueue.next();
-
-            hdr->size = ntohs((uint16)packetSize + 2);
-            hdr->cmd = packet->GetOpcode();
-
-            if( sWorldLog.LogWorld() )
-            {
-                sWorldLog.Log("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n",
-                    (uint32)GetSocket(),
-                    packetSize,
-                    LookupOpcodeName(packet->GetOpcode()),
-                    packet->GetOpcode());
-
-                uint32 p = 0;
-                while (p < packetSize)
-                {
-                    for (uint32 j = 0; j < 16 && p < packetSize; j++)
-                        sWorldLog.Log("%.2X ", (*packet)[p++]);
-
-                    sWorldLog.Log("\n");
-                }
-
-                sWorldLog.Log("\n\n");
-            }
-
-            ///- Encrypt (if needed) the header
-            _crypt.EncryptSend((uint8*)hdr, sizeof(*hdr));
-            bufferSize += sizeof(*hdr);
-
-            if (packetSize)
-            {
-                memcpy(&sendBuffer[bufferSize], packet->contents(), packetSize);
-                bufferSize += packetSize;
-            }
-
-            ///- Send the header and body to the client
-            delete packet;
-        }
-
-        // send merged packets
-        if (bufferSize) TcpSocket::SendBuf((char*)sendBuffer, bufferSize);
-        // send too big non-merged packet
-        if (haveBigPacket) SendSinglePacket();
-    }
-}
-
-/// Handle the authentication waiting queue (to be completed)
-void WorldSocket::SendAuthWaitQue(uint32 position)
-{
-    if(position == 0)
-    {
-        WorldPacket packet( SMSG_AUTH_RESPONSE, 1 );
-        packet << uint8( AUTH_OK );
-        SendPacket(&packet);
-    }
-    else
-    {
-        WorldPacket packet( SMSG_AUTH_RESPONSE, 5 );
-        packet << uint8( AUTH_WAIT_QUEUE );
-        packet << uint32 (position);                        //amount of players in queue
-        SendPacket(&packet);
-    }
-}
-
-void WorldSocket::SizeError(WorldPacket const& packet, uint32 size) const
-{
-    sLog.outError("Client send packet %s (%u) with size %u but expected %u (attempt crash server?), skipped",
-        LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size);
-}
+
+          break;
+        }
+      else
+        {
+          haveone = true;
+          delete pct;
+        }
+    }
+
+  return haveone;
+}
Index: trunk/src/game/AggressorAI.cpp
===================================================================
--- trunk/src/game/AggressorAI.cpp (revision 2)
+++ trunk/src/game/AggressorAI.cpp (revision 6)
@@ -44,6 +44,8 @@
 AggressorAI::MoveInLineOfSight(Unit *u)
 {
-    if( i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
+    // Ignore Z for flying creatures
+    if( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
         return;
+    
     if( !i_creature.getVictim() && !i_creature.hasUnitState(UNIT_STAT_STUNDED) && u->isTargetableForAttack() &&
         ( i_creature.IsHostileTo( u ) /*|| u->getVictim() && i_creature.IsFriendlyTo( u->getVictim() )*/ ) &&
Index: trunk/src/game/GridNotifiers.h
===================================================================
--- trunk/src/game/GridNotifiers.h (revision 2)
+++ trunk/src/game/GridNotifiers.h (revision 6)
@@ -113,5 +113,5 @@
         bool i_ownTeamOnly;
         float i_dist;
-        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) {}
+        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) {}
         void Visit(PlayerMapType &m);
         template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
Index: trunk/src/game/StatSystem.cpp
===================================================================
--- trunk/src/game/StatSystem.cpp (revision 2)
+++ trunk/src/game/StatSystem.cpp (revision 6)
@@ -432,13 +432,18 @@
 void Player::UpdateBlockPercentage()
 {
-    // Base value
-    float value = 5.0f;
-    // Modify value from defense skill
-    value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
-    // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura
-    value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT);
-    // Increase from rating
-    value += GetRatingBonusValue(CR_BLOCK);
-    value = value < 0.0f ? 0.0f : value;
+    // No block
+    float value = 0.0f;
+    if(CanBlock())
+    {
+        // Base value
+        value = 5.0f;
+        // Modify value from defense skill
+        value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
+        // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura
+        value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT);
+        // Increase from rating
+        value += GetRatingBonusValue(CR_BLOCK);
+        value = value < 0.0f ? 0.0f : value;
+    }
     SetStatFloatValue(PLAYER_BLOCK_PERCENTAGE, value);
 }
@@ -492,13 +497,18 @@
 void Player::UpdateParryPercentage()
 {
-    // Base parry
-    float value  = 5.0f;
-    // Modify value from defense skill
-    value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
-    // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
-    value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
-    // Parry from rating
-    value += GetRatingBonusValue(CR_PARRY);
-    value = value < 0.0f ? 0.0f : value;
+    // No parry
+    float value = 0.0f;
+    if (CanParry())
+    {
+        // Base parry
+        value  = 5.0f;
+        // Modify value from defense skill
+        value += (int32(GetDefenseSkillValue()) - int32(GetMaxSkillValueForLevel())) * 0.04f;
+        // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
+        value += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
+        // Parry from rating
+        value += GetRatingBonusValue(CR_PARRY);
+        value = value < 0.0f ? 0.0f : value;
+    }
     SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value);
 }
Index: trunk/src/game/Unit.h
===================================================================
--- trunk/src/game/Unit.h (revision 2)
+++ trunk/src/game/Unit.h (revision 6)
@@ -116,4 +116,9 @@
 
 #define MAX_SPELLMOD 32
+
+enum SpellFacingFlags
+{
+    SPELL_FACING_FLAG_INFRONT = 0x0001
+};
 
 #define BASE_MINDAMAGE 1.0f
Index: trunk/src/game/CreatureAISelector.cpp
===================================================================
--- trunk/src/game/CreatureAISelector.cpp (revision 2)
+++ trunk/src/game/CreatureAISelector.cpp (revision 6)
@@ -54,11 +54,9 @@
         {
             if( creature->isGuard() )
-                ainame="GuardAI";
+                ai_factory = ai_registry.GetRegistryItem("GuardAI"); 
             else if(creature->isPet() || creature->isCharmed())
-                ainame="PetAI";
+                ai_factory = ai_registry.GetRegistryItem("PetAI");
             else if(creature->isTotem())
-                ainame="TotemAI";
-
-            ai_factory = ai_registry.GetRegistryItem( ainame.c_str() );
+                ai_factory = ai_registry.GetRegistryItem("TotemAI");
         }
 
Index: trunk/src/game/Makefile.am
===================================================================
--- trunk/src/game/Makefile.am (revision 2)
+++ trunk/src/game/Makefile.am (revision 6)
@@ -31,4 +31,6 @@
 $(POSTGRE_INCLUDES) \
 -I$(top_srcdir)/dep/include \
+-I$(top_srcdir)/dep/ACE_wrappers \
+-I$(top_builddir)/dep/ACE_wrappers \
 -I$(top_srcdir)/src/framework \
 -I$(top_srcdir)/src/shared \
Index: trunk/src/game/World.h
===================================================================
--- trunk/src/game/World.h (revision 2)
+++ trunk/src/game/World.h (revision 6)
@@ -363,8 +363,8 @@
 
         //player Queue
-        typedef std::list<WorldSocket*> Queue;
-        void AddQueuedPlayer(WorldSocket* Socket);
-        void RemoveQueuedPlayer(WorldSocket* Socket);
-        int32 GetQueuePos(WorldSocket* Socket);
+        typedef std::list<WorldSession*> Queue;
+        void AddQueuedPlayer(WorldSession*);
+        void RemoveQueuedPlayer(WorldSession*);
+        int32 GetQueuePos(WorldSession*);
         uint32 GetQueueSize() const { return m_QueuedPlayer.size(); }
 
@@ -526,4 +526,8 @@
         //Player Queue
         Queue m_QueuedPlayer;
+        
+        //sessions that are added async
+        void AddSession_(WorldSession* s);
+        ZThread::LockedQueue<WorldSession*, ZThread::FastMutex> addSessQueue;
 };
 
Index: trunk/src/game/WorldSession.h
===================================================================
--- trunk/src/game/WorldSession.h (revision 2)
+++ trunk/src/game/WorldSession.h (revision 6)
@@ -89,5 +89,5 @@
         char const* GetPlayerName() const;
         void SetSecurity(uint32 security) { _security = security; }
-        void SetSocket(WorldSocket *sock);
+        std::string& GetRemoteAddress() { return m_Address; }
         void SetPlayer(Player *plr) { _player = plr; }
         bool IsTBC() const { return m_isTBC; }
@@ -111,6 +111,9 @@
         void KickPlayer();
 
-        void QueuePacket(WorldPacket& packet);
+        void QueuePacket(WorldPacket* new_packet);
         bool Update(uint32 diff);
+        
+        /// Handle the authentication waiting queue (to be completed)
+        void SendAuthWaitQue(uint32 position);
 
         //void SendTestCreatureQueryOpcode( uint32 entry, uint64 guid, uint32 testvalue );
@@ -619,5 +622,6 @@
         void logUnexpectedOpcode(WorldPacket *packet, const char * reason);
         Player *_player;
-        WorldSocket *_socket;
+        WorldSocket *m_Socket;
+        std::string m_Address;
 
         uint32 _security;
Index: trunk/src/game/Unit.cpp
===================================================================
--- trunk/src/game/Unit.cpp (revision 2)
+++ trunk/src/game/Unit.cpp (revision 6)
@@ -2991,7 +2991,7 @@
         if(player->CanParry() )
         {
-            Item *tmpitem = ((Player*)this)->GetWeaponForAttack(BASE_ATTACK,true);
+            Item *tmpitem = player->GetWeaponForAttack(BASE_ATTACK,true);
             if(!tmpitem)
-                tmpitem = ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true);
+                tmpitem = player->GetWeaponForAttack(OFF_ATTACK,true);
 
             if(tmpitem)
@@ -3018,9 +3018,13 @@
     if(GetTypeId() == TYPEID_PLAYER)
     {
-        Item *tmpitem = ((Player const*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
-        if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block)
-            return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
-        else
-            return 0.0f;
+        Player const* player = (Player const*)this;
+        if(player->CanBlock() )
+        {
+            Item *tmpitem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
+            if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block)
+                return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
+        }
+        // is player but has no block ability or no not broken shield equiped
+        return 0.0f;
     }
     else
@@ -3416,5 +3420,5 @@
         return c->canSwim();
     else
-        return c->canWalk();
+        return c->canWalk() || c->canFly();
 }
 
Index: trunk/src/game/ObjectMgr.h
===================================================================
--- trunk/src/game/ObjectMgr.h (revision 2)
+++ trunk/src/game/ObjectMgr.h (revision 6)
@@ -43,4 +43,5 @@
 #include <string>
 #include <map>
+#include <limits>
 
 extern SQLStorage sCreatureStorage;
@@ -60,4 +61,17 @@
 class TransportPath;
 class Item;
+
+struct GameTele
+{
+    float  position_x;
+    float  position_y;
+    float  position_z;
+    float  orientation;
+    uint32 mapId;
+    std::string name;
+    std::wstring wnameLow;
+};
+
+typedef HM_NAMESPACE::hash_map<uint32, GameTele > GameTeleMap;
 
 struct ScriptInfo
@@ -144,8 +158,8 @@
     uint32 repfaction2;
     bool is_teamaward1;
-    uint32 reputration_max_cap1;
+    uint32 reputation_max_cap1;
     int32 repvalue1;
     bool is_teamaward2;
-    uint32 reputration_max_cap2;
+    uint32 reputation_max_cap2;
     int32 repvalue2;
     bool team_dependent;
@@ -212,4 +226,21 @@
 };
 
+// NPC gossip text id
+typedef HM_NAMESPACE::hash_map<uint32, uint32> CacheNpcTextIdMap;
+
+// Vendors
+struct VendorItem
+{
+    uint32 item;
+    uint32 maxcount;
+    uint32 incrtime;
+    uint32 ExtendedCost;
+};
+typedef std::vector<VendorItem*> VendorItemList;
+
+typedef HM_NAMESPACE::hash_map<uint32, VendorItemList> CacheVendorItemMap;
+
+typedef HM_NAMESPACE::hash_map<uint32, TrainerSpellData> CacheTrainerSpellMap;
+
 enum SkillRangeType
 {
@@ -467,6 +498,6 @@
         void LoadSpellScripts();
 
-        bool LoadMangosStrings(DatabaseType& db, char const* table, bool positive_entries);
-        bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",true); }
+        bool LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value);
+        bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",1,std::numeric_limits<int32>::max()); }
         void LoadPetCreateSpells();
         void LoadCreatureLocales();
@@ -513,4 +544,9 @@
 
         void LoadWeatherZoneChances();
+        void LoadGameTele();
+
+        void LoadNpcTextId();
+        void LoadVendors();
+        void LoadTrainerSpell();
 
         std::string GeneratePetName(uint32 entry);
@@ -664,4 +700,42 @@
 
             return mConditions[condition_id].Meets(player);
+        }
+
+        GameTele const* GetGameTele(uint32 id) const
+        {
+            GameTeleMap::const_iterator itr = m_GameTeleMap.find(id);
+            if(itr==m_GameTeleMap.end()) return NULL;
+            return &itr->second;
+        }
+        GameTele const* GetGameTele(std::string name) const;
+        GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; }
+        bool AddGameTele(GameTele& data);
+        bool DeleteGameTele(std::string name);
+
+        uint32 GetNpcGossip(uint32 entry) const
+        {
+            CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry);
+            if(iter == m_mCacheNpcTextIdMap.end())
+                return 0;
+            
+            return iter->second;
+        }
+
+        TrainerSpellData const* GetNpcTrainerSpells(uint32 entry) const
+        {
+            CacheTrainerSpellMap::const_iterator  iter = m_mCacheTrainerSpellMap.find(entry);
+            if(iter == m_mCacheTrainerSpellMap.end())
+                return NULL;
+
+            return &iter->second;
+        }
+
+        VendorItemList const* GetNpcVendorItemList(uint32 entry) const
+        {
+            CacheVendorItemMap::const_iterator  iter = m_mCacheVendorItemMap.find(entry);
+            if(iter == m_mCacheVendorItemMap.end())
+                return NULL;
+
+            return &iter->second;
         }
     protected:
@@ -721,4 +795,6 @@
 
         GraveYardMap        mGraveYardMap;
+
+        GameTeleMap         m_GameTeleMap;
 
         typedef             std::vector<LocaleConstant> LocalForIndex;
@@ -771,10 +847,14 @@
         ConditionStore mConditions;
 
+        CacheNpcTextIdMap m_mCacheNpcTextIdMap;
+        CacheVendorItemMap m_mCacheVendorItemMap;
+        CacheTrainerSpellMap m_mCacheTrainerSpellMap;
 };
 
 #define objmgr MaNGOS::Singleton<ObjectMgr>::Instance()
+
+// scripting access functions
+bool MANGOS_DLL_SPEC LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits<int32>::min());
+MANGOS_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id);
+
 #endif
-
-// scripting access functions
-bool MANGOS_DLL_SPEC LoadMangosStrings(DatabaseType& db, char const* table);
-MANGOS_DLL_SPEC const char* GetAreaTriggerScriptNameById(uint32 id);
Index: trunk/src/game/Spell.h
===================================================================
--- trunk/src/game/Spell.h (revision 2)
+++ trunk/src/game/Spell.h (revision 6)
@@ -252,4 +252,5 @@
         void EffectResurrect(uint32 i);
         void EffectParry(uint32 i);
+        void EffectBlock(uint32 i);
         void EffectMomentMove(uint32 i);
         void EffectTransmitted(uint32 i);
Index: trunk/src/game/World.cpp
===================================================================
--- trunk/src/game/World.cpp (revision 2)
+++ trunk/src/game/World.cpp (revision 6)
@@ -22,4 +22,5 @@
 
 #include "Common.h"
+//#include "WorldSocket.h"
 #include "Database/DatabaseEnv.h"
 #include "Config/ConfigEnv.h"
@@ -51,5 +52,4 @@
 #include "GameEvent.h"
 #include "Database/DatabaseImpl.h"
-#include "WorldSocket.h"
 #include "GridNotifiersImpl.h"
 #include "CellImpl.h"
@@ -124,4 +124,6 @@
 
     if(m_resultQueue) delete m_resultQueue;
+    
+    //TODO free addSessQueue
 }
 
@@ -174,23 +176,76 @@
 }
 
-/// Add a session to the session list
 void World::AddSession(WorldSession* s)
 {
-    ASSERT(s);
-
-    WorldSession* old = m_sessions[s->GetAccountId()];
-    m_sessions[s->GetAccountId()] = s;
-
-    // if session already exist, prepare to it deleting at next world update
-    if(old)
-        m_kicked_sessions.insert(old);
-}
-
-int32 World::GetQueuePos(WorldSocket* socket)
+  addSessQueue.add(s);
+}
+
+void
+World::AddSession_ (WorldSession* s)
+{
+  ASSERT (s);
+
+  //NOTE - Still there is race condition in WorldSession* being used in the Sockets
+
+  ///- kick already loaded player with same account (if any) and remove session
+  ///- if player is in loading and want to load again, return
+  if (!RemoveSession (s->GetAccountId ()))
+    {
+      s->KickPlayer ();
+      m_kicked_sessions.insert (s);
+      return;
+    }
+
+  WorldSession* old = m_sessions[s->GetAccountId ()];
+  m_sessions[s->GetAccountId ()] = s;
+
+  // if session already exist, prepare to it deleting at next world update
+  // NOTE - KickPlayer() should be called on "old" in RemoveSession()
+  if (old)
+    m_kicked_sessions.insert (old);
+
+  uint32 Sessions = GetActiveAndQueuedSessionCount ();
+  uint32 pLimit = GetPlayerAmountLimit ();
+  uint32 QueueSize = GetQueueSize (); //number of players in the queue
+  bool inQueue = false;
+  //so we don't count the user trying to 
+  //login as a session and queue the socket that we are using
+  --Sessions;
+
+  if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
+    {
+      AddQueuedPlayer (s);
+      UpdateMaxSessionCounters ();
+      sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
+      return;
+    }
+  
+  WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
+  packet << uint8 (AUTH_OK);
+  packet << uint32 (0); // unknown random value...
+  packet << uint8 (0);
+  packet << uint32 (0);
+  packet << uint8 (s->IsTBC () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
+  s->SendPacket (&packet);
+
+  UpdateMaxSessionCounters ();
+
+  // Updates the population
+  if (pLimit > 0)
+    {
+      float popu = GetActiveSessionCount (); //updated number of users on the server
+      popu /= pLimit;
+      popu *= 2;
+      loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
+      sLog.outDetail ("Server Population (%f).", popu);
+    }
+}
+
+int32 World::GetQueuePos(WorldSession* sess)
 {
     uint32 position = 1;
 
     for(Queue::iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position)
-        if((*iter) == socket)
+        if((*iter) == sess)
             return position;
 
@@ -198,10 +253,22 @@
 }
 
-void World::AddQueuedPlayer(WorldSocket* socket)
-{
-    m_QueuedPlayer.push_back(socket);
-}
-
-void World::RemoveQueuedPlayer(WorldSocket* socket)
+void World::AddQueuedPlayer(WorldSession* sess)
+{
+    m_QueuedPlayer.push_back (sess);
+    
+    // The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
+    WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
+    packet << uint8 (AUTH_WAIT_QUEUE);
+    packet << uint32 (0); // unknown random value...
+    packet << uint8 (0);
+    packet << uint32 (0);
+    packet << uint8 (sess->IsTBC () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
+    packet << uint32(GetQueuePos (sess));
+    sess->SendPacket (&packet);
+    
+    //sess->SendAuthWaitQue (GetQueuePos (sess));
+}
+
+void World::RemoveQueuedPlayer(WorldSession* sess)
 {
     // sessions count including queued to remove (if removed_session set)
@@ -214,8 +281,8 @@
     bool decrease_session = true;
 
-    // search socket to remove and count skipped positions
+    // search to remove and count skipped positions
     for(;iter != m_QueuedPlayer.end(); ++iter, ++position)
     {
-        if(*iter==socket)
+        if(*iter==sess)
         {
             Queue::iterator iter2 = iter;
@@ -237,5 +304,5 @@
     if( (!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty() )
     {
-        WorldSocket * socket = m_QueuedPlayer.front();
+        WorldSession * socket = m_QueuedPlayer.front();
         socket->SendAuthWaitQue(0);
         m_QueuedPlayer.pop_front();
@@ -1016,4 +1083,16 @@
     objmgr.LoadBattleMastersEntry();
 
+    sLog.outString( "Loading GameTeleports..." );
+    objmgr.LoadGameTele();
+
+    sLog.outString( "Loading Npc Text Id..." );
+    objmgr.LoadNpcTextId();                                 // must be after load Creature and NpcText
+
+    sLog.outString( "Loading vendors..." );
+    objmgr.LoadVendors();                                   // must be after load CreatureTemplate and ItemTemplate
+
+    sLog.outString( "Loading trainers..." );
+    objmgr.LoadTrainerSpell();                              // must be after load CreatureTemplate
+
     sLog.outString( "Loading Waypoints..." );
     WaypointMgr.Load();
@@ -2069,7 +2148,8 @@
 {
     // session not removed at kick and will removed in next update tick
-    for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr)
-        if(WorldSession* session = (*itr)->GetSession())
-            session->KickPlayer();
+  //TODO here
+//    for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr)
+//        if(WorldSession* session = (*itr)->GetSession())
+//            session->KickPlayer();
 
     m_QueuedPlayer.empty();
@@ -2321,4 +2401,10 @@
 void World::UpdateSessions( time_t diff )
 {
+    while(!addSessQueue.empty())
+    {
+      WorldSession* sess = addSessQueue.next ();
+      AddSession_ (sess);
+    }
+        
     ///- Delete kicked sessions at add new session
     for (std::set<WorldSession*>::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr)
Index: trunk/src/game/Level2.cpp
===================================================================
--- trunk/src/game/Level2.cpp (revision 2)
+++ trunk/src/game/Level2.cpp (revision 6)
@@ -34,4 +34,5 @@
 #include "GameEvent.h"
 #include "SpellMgr.h"
+#include "AccountMgr.h"
 #include "WaypointManager.h"
 #include "Util.h"
@@ -208,5 +209,5 @@
             result = WorldDatabase.PQuery(
                 "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_ "
-                "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" '""%%%s%%""' ORDER BY order_ ASC LIMIT 1",
+                "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
                 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
         }
@@ -3947,2 +3948,99 @@
     return false;
 }
+
+bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
+{
+  
+    if(!*args)
+        return false;
+
+    std::string ip = strtok((char*)args, " ");
+    char* limit_str = strtok(NULL, " ");
+    int32 limit = limit_str ? atoi(limit_str) : -1;
+
+    loginDatabase.escape_string(ip);
+
+    QueryResult* result = loginDatabase.PQuery("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str());
+
+    return LookupPlayerSearchCommand(result,limit);
+}
+
+bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
+{
+    if(!*args)
+        return false;
+
+    std::string account = strtok((char*)args, " ");
+    char* limit_str = strtok(NULL, " ");
+    int32 limit = limit_str ? atoi(limit_str) : -1;
+
+    if(!AccountMgr::normilizeString(account))
+        return false;
+
+    loginDatabase.escape_string(account);
+
+    QueryResult* result = loginDatabase.PQuery("SELECT id,username FROM account WHERE username = '%s'", account.c_str());
+
+    return LookupPlayerSearchCommand(result,limit);
+}
+
+bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
+{
+  
+    if(!*args)
+        return false;
+
+    std::string email = strtok((char*)args, " ");
+    char* limit_str = strtok(NULL, " ");
+    int32 limit = limit_str ? atoi(limit_str) : -1;
+
+    loginDatabase.escape_string(email);
+
+    QueryResult* result = loginDatabase.PQuery("SELECT id,username FROM account WHERE email = '%s'", email.c_str());
+
+    return LookupPlayerSearchCommand(result,limit);
+}
+
+bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
+{
+    if(!result)
+    {
+        PSendSysMessage(LANG_NO_PLAYERS_FOUND);
+        SetSentErrorMessage(true);
+        return false;
+    }
+
+    int i =0;
+    do
+    {
+        Field* fields = result->Fetch();
+        uint32 acc_id = fields[0].GetUInt32();
+        std::string acc_name = fields[1].GetCppString();
+        
+        QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
+        if(chars)
+        {
+            PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
+
+            uint64 guid = 0;
+            std::string name;
+
+            do
+            {
+                Field* charfields = chars->Fetch();
+                guid = charfields[0].GetUInt64();
+                name = charfields[1].GetCppString();
+
+                PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
+                ++i;
+
+            } while( chars->NextRow() && ( limit == -1 || i < limit ) );
+
+            delete chars;
+        }
+    } while(result->NextRow());
+
+    delete result;
+
+    return true;
+}
Index: trunk/src/game/CharacterHandler.cpp
===================================================================
--- trunk/src/game/CharacterHandler.cpp (revision 2)
+++ trunk/src/game/CharacterHandler.cpp (revision 6)
@@ -20,5 +20,5 @@
 #include "Database/DatabaseEnv.h"
 #include "WorldPacket.h"
-#include "WorldSocket.h"
+#include "SharedDefines.h"
 #include "WorldSession.h"
 #include "Opcodes.h"
@@ -367,5 +367,5 @@
     SendPacket( &data );
 
-    std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-";
+    std::string IP_str = GetRemoteAddress().c_str();
     sLog.outBasic("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str());
     sLog.outChar("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str());
@@ -417,5 +417,5 @@
         return;
 
-    std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-";
+    std::string IP_str = GetRemoteAddress();
     sLog.outBasic("Account: %d (IP: %s) Delete Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid));
     sLog.outChar("Account: %d (IP: %s) Delete Character:[%s] (guid: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid));
@@ -735,5 +735,5 @@
         SendNotification("GM mode is ON");
 
-    std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-";
+    std::string IP_str = GetRemoteAddress();
     sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUID());
 
@@ -967,5 +967,5 @@
     CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid));
 
-    std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-";
+    std::string IP_str = GetRemoteAddress();
     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());
 
Index: trunk/src/game/WorldSession.cpp
===================================================================
--- trunk/src/game/WorldSession.cpp (revision 2)
+++ trunk/src/game/WorldSession.cpp (revision 6)
@@ -21,4 +21,5 @@
 */
 
+#include "WorldSocket.h"
 #include "Common.h"
 #include "Database/DatabaseEnv.h"
@@ -43,8 +44,13 @@
 WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, bool tbc, time_t mute_time, LocaleConstant locale) :
 LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time),
-_player(NULL), _socket(sock),_security(sec), _accountId(id), m_isTBC(tbc),
+_player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_isTBC(tbc),
 m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)),
 _logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0)
 {
+   if (sock)
+     {
+       m_Address = sock->GetRemoteAddress ();
+       sock->AddReference ();
+     }
 }
 
@@ -57,8 +63,10 @@
 
     /// - If have unclosed socket, close it
-    if(_socket)
-        _socket->CloseSocket();
-
-    _socket = NULL;
+  if (m_Socket)
+    {
+      m_Socket->CloseSocket ();   
+      m_Socket->RemoveReference ();
+      m_Socket = NULL;
+    }
 
     ///- empty incoming packet queue
@@ -68,4 +76,6 @@
         delete packet;
     }
+    
+    sWorld.RemoveQueuedPlayer(this);
 }
 
@@ -82,14 +92,8 @@
 }
 
-/// Set the WorldSocket associated with this session
-void WorldSession::SetSocket(WorldSocket *sock)
-{
-    _socket = sock;
-}
-
 /// Send a packet to the client
 void WorldSession::SendPacket(WorldPacket const* packet)
 {
-    if (!_socket)
+    if (!m_Socket)
         return;
     #ifdef MANGOS_DEBUG
@@ -125,14 +129,16 @@
         sendLastPacketBytes = packet->wpos();               // wpos is real written size
     }
-    #endif                                                  // !MANGOS_DEBUG
-
-    _socket->SendPacket(packet);
+#endif                                                  // !MANGOS_DEBUG
+
+  if (m_Socket->SendPacket (*packet) == -1)
+    {
+      m_Socket->CloseSocket ();
+    }
 }
 
 /// Add an incoming packet to the queue
-void WorldSession::QueuePacket(WorldPacket& packet)
-{
-    WorldPacket *pck = new WorldPacket(packet);
-    _recvQueue.add(pck);
+void WorldSession::QueuePacket(WorldPacket* new_packet)
+{
+    _recvQueue.add(new_packet);
 }
 
@@ -149,4 +155,11 @@
 bool WorldSession::Update(uint32 /*diff*/)
 {
+  if (m_Socket)
+    if (m_Socket->IsClosed ())
+      { 
+        m_Socket->RemoveReference ();
+        m_Socket = NULL;
+      }
+  
     WorldPacket *packet;
 
@@ -211,8 +224,8 @@
     ///- If necessary, log the player out
     time_t currTime = time(NULL);
-    if (!_socket || (ShouldLogOut(currTime) && !m_playerLoading))
+    if (!m_Socket || (ShouldLogOut(currTime) && !m_playerLoading))
         LogoutPlayer(true);
 
-    if (!_socket)
+    if (!m_Socket)
         return false;                                       //Will remove this session from the world session map
 
@@ -344,5 +357,5 @@
         // remove player from the group if he is:
         // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
-        if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && _socket)
+        if(_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
             _player->RemoveFromGroup();
 
@@ -386,10 +399,8 @@
 void WorldSession::KickPlayer()
 {
-    if(!_socket)
-        return;
-
-    // player will be logout and session will removed in next update tick
-    _socket->CloseSocket();
-    _socket = NULL;
+  if (m_Socket)
+    {
+      m_Socket->CloseSocket ();
+    }
 }
 
@@ -462,2 +473,21 @@
         recvPacket.GetOpcode());
 }
+
+void WorldSession::SendAuthWaitQue(uint32 position)
+ {
+     if(position == 0)
+     {
+         WorldPacket packet( SMSG_AUTH_RESPONSE, 1 );
+         packet << uint8( AUTH_OK );
+         SendPacket(&packet);
+     }
+     else
+     {
+         WorldPacket packet( SMSG_AUTH_RESPONSE, 5 );
+         packet << uint8( AUTH_WAIT_QUEUE );
+         packet << uint32 (position);
+         SendPacket(&packet);
+     }
+ }
+ 
+
Index: trunk/src/game/Player.cpp
===================================================================
--- trunk/src/game/Player.cpp (revision 2)
+++ trunk/src/game/Player.cpp (revision 6)
@@ -357,4 +357,5 @@
     m_ArmorProficiency = 0;
     m_canParry = false;
+    m_canBlock = false;
     m_canDualWield = false;
     m_ammoDPS = 0.0f;
@@ -617,6 +618,4 @@
             ++action_itr[i];
     }
-
-    UpdateBlockPercentage();
 
     for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++)
@@ -2249,10 +2248,6 @@
         SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1+i, 0.0f);
 
-    // Base parry percents
-    SetFloatValue(PLAYER_PARRY_PERCENTAGE, 5.0f);
-
-    //Base block percentage
-    SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 5.0f);
-
+    SetFloatValue(PLAYER_PARRY_PERCENTAGE, 0.0f);
+    SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 0.0f);
     SetUInt32Value(PLAYER_SHIELD_BLOCK, 0);
 
@@ -3287,9 +3282,4 @@
         updateVisualBits.SetBit(i);
 
-    for(uint16 i = 0; i < INVENTORY_SLOT_BAG_END; i++)
-    {
-        updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + i*2));
-        updateVisualBits.SetBit((uint16)(PLAYER_FIELD_INV_SLOT_HEAD + (i*2) + 1));
-    }
     //Players visible items are not inventory stuff
     //431) = 884 (0x374) = main weapon
@@ -3406,16 +3396,16 @@
 
     // known spell
-    if(HasSpell(trainer_spell->spell->Id))
+    if(HasSpell(trainer_spell->spell))
         return TRAINER_SPELL_GRAY;
 
     // check race/class requirement
-    if(!IsSpellFitByClassAndRace(trainer_spell->spell->Id))
+    if(!IsSpellFitByClassAndRace(trainer_spell->spell))
         return TRAINER_SPELL_RED;
 
     // check level requirement
-    if(getLevel() < ( trainer_spell->reqlevel ? trainer_spell->reqlevel : trainer_spell->spell->spellLevel))
+    if(getLevel() < trainer_spell->reqlevel)
         return TRAINER_SPELL_RED;
 
-    if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell->Id))
+    if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell))
     {
         // check prev.rank requirement
@@ -3432,12 +3422,15 @@
         return TRAINER_SPELL_RED;
 
+    // exist, already checked at loading
+    SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->spell);
+
     // secondary prof. or not prof. spell
-    uint32 skill = trainer_spell->spell->EffectMiscValue[1];
-
-    if(trainer_spell->spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill))
+    uint32 skill = spell->EffectMiscValue[1];
+
+    if(spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill))
         return TRAINER_SPELL_GREEN;
 
     // check primary prof. limit
-    if(spellmgr.IsPrimaryProfessionFirstRankSpell(trainer_spell->spell->Id) && GetFreePrimaryProffesionPoints() == 0)
+    if(spellmgr.IsPrimaryProfessionFirstRankSpell(spell->Id) && GetFreePrimaryProffesionPoints() == 0)
         return TRAINER_SPELL_RED;
 
@@ -4877,7 +4870,5 @@
 
         if(pskill == SKILL_DEFENSE)
-        {
-            UpdateBlockPercentage();
-        }
+            UpdateDefenseBonusesMod();
     }
 }
@@ -5791,5 +5782,5 @@
         FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(Rep->repfaction1);
         uint32 current_reputation_rank1 = GetReputationRank(factionEntry1);
-        if(factionEntry1 && current_reputation_rank1 <= Rep->reputration_max_cap1)
+        if(factionEntry1 && current_reputation_rank1 <= Rep->reputation_max_cap1)
             ModifyFactionReputation(factionEntry1, donerep1);
 
@@ -5809,5 +5800,5 @@
         FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(Rep->repfaction2);
         uint32 current_reputation_rank2 = GetReputationRank(factionEntry2);
-        if(factionEntry2 && current_reputation_rank2 <= Rep->reputration_max_cap2)
+        if(factionEntry2 && current_reputation_rank2 <= Rep->reputation_max_cap2)
             ModifyFactionReputation(factionEntry2, donerep2);
 
@@ -11553,6 +11544,6 @@
     }
 
-    QuestMenu *qm = PlayerTalkClass->GetQuestMenu();
-    qm->ClearMenu();
+    QuestMenu &qm = PlayerTalkClass->GetQuestMenu();
+    qm.ClearMenu();
 
     for(QuestRelations::const_iterator i = pObjectQIR->lower_bound(pObject->GetEntry()); i != pObjectQIR->upper_bound(pObject->GetEntry()); ++i)
@@ -11561,9 +11552,9 @@
         QuestStatus status = GetQuestStatus( quest_id );
         if ( status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus( quest_id ) )
-            qm->AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP);
+            qm.AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP);
         else if ( status == QUEST_STATUS_INCOMPLETE )
-            qm->AddMenuItem(quest_id, DIALOG_STATUS_INCOMPLETE);
+            qm.AddMenuItem(quest_id, DIALOG_STATUS_INCOMPLETE);
         else if (status == QUEST_STATUS_AVAILABLE )
-            qm->AddMenuItem(quest_id, DIALOG_STATUS_CHAT);
+            qm.AddMenuItem(quest_id, DIALOG_STATUS_CHAT);
     }
 
@@ -11577,7 +11568,7 @@
 
         if (pQuest->IsAutoComplete() && CanTakeQuest(pQuest, false))
-            qm->AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP);
+            qm.AddMenuItem(quest_id, DIALOG_STATUS_REWARD_REP);
         else if ( status == QUEST_STATUS_NONE && CanTakeQuest( pQuest, false ) )
-            qm->AddMenuItem(quest_id, DIALOG_STATUS_AVAILABLE);
+            qm.AddMenuItem(quest_id, DIALOG_STATUS_AVAILABLE);
     }
 }
@@ -11585,13 +11576,17 @@
 void Player::SendPreparedQuest( uint64 guid )
 {
-    QuestMenu* pQuestMenu = PlayerTalkClass->GetQuestMenu();
-    if( !pQuestMenu || pQuestMenu->MenuItemCount() < 1 )
+    QuestMenu& questMenu = PlayerTalkClass->GetQuestMenu();
+    if( questMenu.Empty() )
         return;
 
-    uint32 status = pQuestMenu->GetItem(0).m_qIcon;
-    if ( pQuestMenu->MenuItemCount() == 1 )
+    QuestMenuItem const& qmi0 = questMenu.GetItem( 0 );
+
+    uint32 status = qmi0.m_qIcon;
+
+    // single element case
+    if ( questMenu.MenuItemCount() == 1 )
     {
         // Auto open -- maybe also should verify there is no greeting
-        uint32 quest_id = pQuestMenu->GetItem(0).m_qId;
+        uint32 quest_id = qmi0.m_qId;
         Quest const* pQuest = objmgr.GetQuestTemplate(quest_id);
         if ( pQuest )
@@ -11608,4 +11603,5 @@
         }
     }
+    // multiply entries
     else
     {
@@ -13772,11 +13768,4 @@
                 break;
         }
-    }
-
-    //Unmount Player from previous mount, so speed bug with mount is no more...
-    if(IsMounted())
-    {
-        Unmount();
-        RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
     }
 
@@ -15627,6 +15616,4 @@
 void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const
 {
-    bool pre = (msgtype==CHAT_MSG_EMOTE);
-
     *data << (uint8)msgtype;
     *data << (uint32)language;
@@ -15634,7 +15621,5 @@
     *data << (uint32)language;                               //language 2.1.0 ?
     *data << (uint64)GetGUID();
-    *data << (uint32)(text.length()+1+(pre?3:0));
-    if(pre)
-        data->append("%s ",3);
+    *data << (uint32)(text.length()+1);
     *data << text;
     *data << (uint8)chatTag();
@@ -17152,4 +17137,8 @@
     data << (float)0.01666667f;                             // game speed
     GetSession()->SendPacket( &data );
+
+    // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment
+    if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight())
+        SetUnitMovementFlags(GetUnitMovementFlags() | MOVEMENTFLAG_FLYING2);
 }
 
@@ -17163,7 +17152,7 @@
     static const AuraType auratypes[] =
     {
-        SPELL_AURA_MOD_FEAR,     SPELL_AURA_TRANSFORM, SPELL_AURA_WATER_WALK,
-        SPELL_AURA_FEATHER_FALL, SPELL_AURA_HOVER,     SPELL_AURA_SAFE_FALL,
-        SPELL_AURA_FLY,          SPELL_AURA_NONE
+        SPELL_AURA_MOD_FEAR,     SPELL_AURA_TRANSFORM,                 SPELL_AURA_WATER_WALK,
+        SPELL_AURA_FEATHER_FALL, SPELL_AURA_HOVER,                     SPELL_AURA_SAFE_FALL,
+        SPELL_AURA_FLY,          SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED, SPELL_AURA_NONE
     };
     for(AuraType const* itr = &auratypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr)
@@ -18117,14 +18106,28 @@
 }
 
-bool ItemPosCount::isContainedIn(ItemPosCountVec &vec)
+void Player::SetCanParry( bool value )
+{
+    if(m_canParry==value)
+        return; 
+
+    m_canParry = value;
+    UpdateParryPercentage();
+}
+
+void Player::SetCanBlock( bool value )
+{
+    if(m_canBlock==value)
+        return; 
+
+    m_canBlock = value;
+    UpdateBlockPercentage();
+}
+
+bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const
 {
     for(ItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr)
-    {
-        if(itr->pos == this->pos/* && itr->count == this.count*/)
-        {
+        if(itr->pos == this->pos)
             return true;
-        }
-    }
+
     return false;
 }
-
Index: trunk/src/game/Guild.h
===================================================================
--- trunk/src/game/Guild.h (revision 2)
+++ trunk/src/game/Guild.h (revision 6)
@@ -217,4 +217,6 @@
 {
     GuildItemPosCount(uint8 _slot, uint8 _count) : slot(_slot), count(_count) {}
+
+    bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const;
 
     uint8 slot;
Index: trunk/src/game/NPCHandler.cpp
===================================================================
--- trunk/src/game/NPCHandler.cpp (revision 2)
+++ trunk/src/game/NPCHandler.cpp (revision 6)
@@ -130,7 +130,4 @@
         GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
 
-    // Lazy loading at first access
-    unit->LoadTrainerSpells();
-
     // trainer list loaded at check;
     if(!unit->isCanTrainingOf(_player,true))
@@ -145,12 +142,17 @@
     }
 
-    Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells();
-
-    WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells.size()*38 + strTitle.size()+1);
+    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
+    if(!trainer_spells)
+    {
+        sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", guid, unit->GetEntry());
+        return;
+    }
+
+    WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
     data << guid;
-    data << uint32(unit->GetTrainerType());
+    data << uint32(trainer_spells->trainerType);
 
     size_t count_pos = data.wpos();
-    data << uint32(trainer_spells.size());
+    data << uint32(trainer_spells->spellList.size());
 
     // reputation discount
@@ -158,24 +160,26 @@
 
     uint32 count = 0;
-    for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr)
-    {
-        if(!_player->IsSpellFitByClassAndRace(itr->spell->Id))
+    for(TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
+    {
+        TrainerSpell const* tSpell = *itr;
+
+        if(!_player->IsSpellFitByClassAndRace(tSpell->spell))
             continue;
 
         ++count;
 
-        bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(itr->spell->Id);
-
-        SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(itr->spell->Id);
-
-        data << uint32(itr->spell->Id);
-        data << uint8(_player->GetTrainerSpellState(&*itr));
-        data << uint32(floor(itr->spellcost * fDiscountMod));
+        bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell);
+
+        SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell);
+
+        data << uint32(tSpell->spell);
+        data << uint8(_player->GetTrainerSpellState(tSpell));
+        data << uint32(floor(tSpell->spellcost * fDiscountMod));
 
         data << uint32(primary_prof_first_rank ? 1 : 0);    // primary prof. learn confirmation dialog
         data << uint32(primary_prof_first_rank ? 1 : 0);    // must be equal prev. field to have learn button in enabled state
-        data << uint8(itr->reqlevel ? itr->reqlevel : itr->spell->spellLevel);
-        data << uint32(itr->reqskill);
-        data << uint32(itr->reqskillvalue);
+        data << uint8(tSpell->reqlevel);
+        data << uint32(tSpell->reqskill);
+        data << uint32(tSpell->reqskillvalue);
         data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
         data << uint32(chain_node && chain_node->prev ? chain_node->req : 0);
@@ -210,24 +214,14 @@
         GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
 
-    // Lazy loading at first access
-    unit->LoadTrainerSpells();
-
     if(!unit->isCanTrainingOf(_player,true))
         return;
 
-    TrainerSpell const* trainer_spell = NULL;
-
     // check present spell in trainer spell list
-    Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells();
-    for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr)
-    {
-        if(itr->spell->Id == spellId)
-        {
-            trainer_spell = &*itr;
-            break;
-        }
-    }
+    TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
+    if(!trainer_spells)
+        return; 
 
     // not found, cheat?
+    TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
     if(!trainer_spell)
         return;
@@ -255,5 +249,5 @@
 
     // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
-    _player->learnSpell(trainer_spell->spell->Id);
+    _player->learnSpell(trainer_spell->spell);
 
     data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
Index: trunk/src/game/Spell.cpp
===================================================================
--- trunk/src/game/Spell.cpp (revision 2)
+++ trunk/src/game/Spell.cpp (revision 6)
@@ -524,4 +524,5 @@
                 case SPELL_EFFECT_RESURRECT:
                 case SPELL_EFFECT_PARRY:
+                case SPELL_EFFECT_BLOCK:
                 case SPELL_EFFECT_CREATE_ITEM:
                 case SPELL_EFFECT_TRIGGER_SPELL:
@@ -3477,14 +3478,20 @@
             case SPELL_EFFECT_DUMMY:
             {
-                // Execute
-                if(m_spellInfo->SpellIconID == 1648)
+                if(m_spellInfo->SpellIconID == 1648)        // Execute
                 {
                     if(!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2)
                         return SPELL_FAILED_BAD_TARGETS;
                 }
-                else if (m_spellInfo->Id == 51582)
+                else if (m_spellInfo->Id == 51582)          // Rocket Boots Engaged
                 {
                     if(m_caster->IsInWater())
                         return SPELL_FAILED_ONLY_ABOVEWATER;
+                }
+                else if(m_spellInfo->SpellIconID==156)      // Holy Shock
+                {
+                    // spell different for friends and enemies
+                    // hart version required facing
+                    if(m_targets.getUnitTarget() && !m_caster->IsFriendlyTo(m_targets.getUnitTarget()) && !m_caster->HasInArc( M_PI, target ))
+                        return SPELL_FAILED_UNIT_NOT_INFRONT;
                 }
                 break;
@@ -4232,59 +4239,7 @@
         if(dist < min_range)
             return SPELL_FAILED_TOO_CLOSE;
-        if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER &&
-            !IsPositiveSpell(m_spellInfo->Id) && !m_caster->HasInArc( M_PI, target ) )
-        {
-            // Spell-Family Related Checks
-            switch (m_spellInfo->SpellFamilyName)
-            {
-                case SPELLFAMILY_PRIEST:
-                {
-                    // Shadow Word: Death, castable without facing
-                    if (m_spellInfo->SpellFamilyFlags & 0x200000000LL)
-                        return 0;                           // this is not TARGET_FLAG_DEST_LOCATION so we can return safely
-                    break;
-                }
-                case SPELLFAMILY_PALADIN:
-                {
-                    // Holy Shock, require facing
-                    if (m_spellInfo->SpellFamilyFlags & 0x200000LL)
-                        return SPELL_FAILED_UNIT_NOT_INFRONT;
-                    break;
-                }
-                case SPELLFAMILY_WARRIOR:
-                {
-                    // Charge, require facing
-                    if (m_spellInfo->SpellFamilyFlags & 1)
-                        return SPELL_FAILED_UNIT_NOT_INFRONT;
-                    break;
-                }
-            }
-
-            // Ranged Weapon
-            if (IsRangedSpell())
-                return SPELL_FAILED_UNIT_NOT_INFRONT;
-
-            // Melee Combat
-            if (m_spellInfo->rangeIndex == 2)
-                return SPELL_FAILED_UNIT_NOT_INFRONT;
-
-            // Missile Effect
-            if (m_spellInfo->speed > 0)
-                return SPELL_FAILED_UNIT_NOT_INFRONT;
-
-            // Channeled Spells need facing
-            if (IsChanneledSpell(m_spellInfo))
-                return SPELL_FAILED_UNIT_NOT_INFRONT;
-
-            // Direct Damage and charge effects
-            for (uint8 i=0;i<3;++i)
-            {
-                if (m_spellInfo->Effect[i] == SPELL_EFFECT_SCHOOL_DAMAGE ||
-                    m_spellInfo->Effect[i] == SPELL_EFFECT_POWER_BURN ||
-                    m_spellInfo->Effect[i] == SPELL_EFFECT_HEALTH_LEECH ||
-                    m_spellInfo->Effect[i] == SPELL_EFFECT_CHARGE)
-                    return SPELL_FAILED_UNIT_NOT_INFRONT;
-            }
-        }
+        if( m_caster->GetTypeId() == TYPEID_PLAYER &&
+            (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc( M_PI, target ) )
+            return SPELL_FAILED_UNIT_NOT_INFRONT;
     }
 
Index: trunk/src/game/SharedDefines.h
===================================================================
--- trunk/src/game/SharedDefines.h (revision 2)
+++ trunk/src/game/SharedDefines.h (revision 6)
@@ -1995,3 +1995,107 @@
     SUMMON_TYPE_POSESSED2   = 428
 };
+
+enum ResponseCodes
+{
+    RESPONSE_SUCCESS                                       = 0x00,
+    RESPONSE_FAILURE                                       = 0x01,
+    RESPONSE_CANCELLED                                     = 0x02,
+    RESPONSE_DISCONNECTED                                  = 0x03,
+    RESPONSE_FAILED_TO_CONNECT                             = 0x04,
+    RESPONSE_CONNECTED                                     = 0x05,
+    RESPONSE_VERSION_MISMATCH                              = 0x06,
+
+    CSTATUS_CONNECTING                                     = 0x07,
+    CSTATUS_NEGOTIATING_SECURITY                           = 0x08,
+    CSTATUS_NEGOTIATION_COMPLETE                           = 0x09,
+    CSTATUS_NEGOTIATION_FAILED                             = 0x0A,
+    CSTATUS_AUTHENTICATING                                 = 0x0B,
+
+    AUTH_OK                                                = 0x0C,
+    AUTH_FAILED                                            = 0x0D,
+    AUTH_REJECT                                            = 0x0E,
+    AUTH_BAD_SERVER_PROOF                                  = 0x0F,
+    AUTH_UNAVAILABLE                                       = 0x10,
+    AUTH_SYSTEM_ERROR                                      = 0x11,
+    AUTH_BILLING_ERROR                                     = 0x12,
+    AUTH_BILLING_EXPIRED                                   = 0x13,
+    AUTH_VERSION_MISMATCH                                  = 0x14,
+    AUTH_UNKNOWN_ACCOUNT                                   = 0x15,
+    AUTH_INCORRECT_PASSWORD                                = 0x16,
+    AUTH_SESSION_EXPIRED                                   = 0x17,
+    AUTH_SERVER_SHUTTING_DOWN                              = 0x18,
+    AUTH_ALREADY_LOGGING_IN                                = 0x19,
+    AUTH_LOGIN_SERVER_NOT_FOUND                            = 0x1A,
+    AUTH_WAIT_QUEUE                                        = 0x1B,
+    AUTH_BANNED                                            = 0x1C,
+    AUTH_ALREADY_ONLINE                                    = 0x1D,
+    AUTH_NO_TIME                                           = 0x1E,
+    AUTH_DB_BUSY                                           = 0x1F,
+    AUTH_SUSPENDED                                         = 0x20,
+    AUTH_PARENTAL_CONTROL                                  = 0x21,
+    AUTH_LOCKED_ENFORCED                                   = 0x22,
+
+    REALM_LIST_IN_PROGRESS                                 = 0x23,
+    REALM_LIST_SUCCESS                                     = 0x24,
+    REALM_LIST_FAILED                                      = 0x25,
+    REALM_LIST_INVALID                                     = 0x26,
+    REALM_LIST_REALM_NOT_FOUND                             = 0x27,
+
+    ACCOUNT_CREATE_IN_PROGRESS                             = 0x28,
+    ACCOUNT_CREATE_SUCCESS                                 = 0x29,
+    ACCOUNT_CREATE_FAILED                                  = 0x2A,
+
+    CHAR_LIST_RETRIEVING                                   = 0x2B,
+    CHAR_LIST_RETRIEVED                                    = 0x2C,
+    CHAR_LIST_FAILED                                       = 0x2D,
+
+    CHAR_CREATE_IN_PROGRESS                                = 0x2E,
+    CHAR_CREATE_SUCCESS                                    = 0x2F,
+    CHAR_CREATE_ERROR                                      = 0x30,
+    CHAR_CREATE_FAILED                                     = 0x31,
+    CHAR_CREATE_NAME_IN_USE                                = 0x32,
+    CHAR_CREATE_DISABLED                                   = 0x33,
+    CHAR_CREATE_PVP_TEAMS_VIOLATION                        = 0x34,
+    CHAR_CREATE_SERVER_LIMIT                               = 0x35,
+    CHAR_CREATE_ACCOUNT_LIMIT                              = 0x36,
+    CHAR_CREATE_SERVER_QUEUE                               = 0x37,
+    CHAR_CREATE_ONLY_EXISTING                              = 0x38,
+    CHAR_CREATE_EXPANSION                                  = 0x39,
+
+    CHAR_DELETE_IN_PROGRESS                                = 0x3A,
+    CHAR_DELETE_SUCCESS                                    = 0x3B,
+    CHAR_DELETE_FAILED                                     = 0x3C,
+    CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER                 = 0x3D,
+    CHAR_DELETE_FAILED_GUILD_LEADER                        = 0x3E,
+    CHAR_DELETE_FAILED_ARENA_CAPTAIN                       = 0x3F,
+
+    CHAR_LOGIN_IN_PROGRESS                                 = 0x40,
+    CHAR_LOGIN_SUCCESS                                     = 0x41,
+    CHAR_LOGIN_NO_WORLD                                    = 0x42,
+    CHAR_LOGIN_DUPLICATE_CHARACTER                         = 0x43,
+    CHAR_LOGIN_NO_INSTANCES                                = 0x44,
+    CHAR_LOGIN_FAILED                                      = 0x45,
+    CHAR_LOGIN_DISABLED                                    = 0x46,
+    CHAR_LOGIN_NO_CHARACTER                                = 0x47,
+    CHAR_LOGIN_LOCKED_FOR_TRANSFER                         = 0x48,
+    CHAR_LOGIN_LOCKED_BY_BILLING                           = 0x49,
+
+    CHAR_NAME_SUCCESS                                      = 0x4A,
+    CHAR_NAME_FAILURE                                      = 0x4B,
+    CHAR_NAME_NO_NAME                                      = 0x4C,
+    CHAR_NAME_TOO_SHORT                                    = 0x4D,
+    CHAR_NAME_TOO_LONG                                     = 0x4E,
+    CHAR_NAME_INVALID_CHARACTER                            = 0x4F,
+    CHAR_NAME_MIXED_LANGUAGES                              = 0x50,
+    CHAR_NAME_PROFANE                                      = 0x51,
+    CHAR_NAME_RESERVED                                     = 0x52,
+    CHAR_NAME_INVALID_APOSTROPHE                           = 0x53,
+    CHAR_NAME_MULTIPLE_APOSTROPHES                         = 0x54,
+    CHAR_NAME_THREE_CONSECUTIVE                            = 0x55,
+    CHAR_NAME_INVALID_SPACE                                = 0x56,
+    CHAR_NAME_CONSECUTIVE_SPACES                           = 0x57,
+    CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS        = 0x58,
+    CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59,
+    CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME            = 0x5A,
+};
 #endif
Index: trunk/src/game/Creature.cpp
===================================================================
--- trunk/src/game/Creature.cpp (revision 2)
+++ trunk/src/game/Creature.cpp (revision 6)
@@ -47,10 +47,26 @@
 #include "Policies/SingletonImp.h"
 
+void TrainerSpellData::Clear()
+{
+    for (TrainerSpellList::iterator itr = spellList.begin(); itr != spellList.end(); ++itr)
+        delete (*itr);
+    spellList.empty();
+}
+
+TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
+{
+    for(TrainerSpellList::const_iterator itr = spellList.begin(); itr != spellList.end(); ++itr)
+        if((*itr)->spell == spell_id)
+            return *itr;
+
+    return NULL;
+}
+
 Creature::Creature() :
 Unit(), i_AI(NULL),
 lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
-m_itemsLoaded(false), m_trainerSpellsLoaded(false), m_trainer_type(0), m_lootMoney(0), m_lootRecipient(0),
+m_itemsLoaded(false), m_lootMoney(0), m_lootRecipient(0),
 m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
-m_gossipOptionLoaded(false),m_NPCTextId(0), m_emoteState(0), m_isPet(false), m_isTotem(false),
+m_gossipOptionLoaded(false),m_emoteState(0), m_isPet(false), m_isTotem(false),
 m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
 m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
@@ -72,5 +88,4 @@
     CleanupsBeforeDelete();
 
-    m_trainer_spells.clear();
     m_vendor_items.clear();
 
@@ -91,56 +106,4 @@
     if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this);
     Unit::RemoveFromWorld();
-}
-
-void Creature::LoadTrainerSpells()
-{
-    if(m_trainerSpellsLoaded)
-        return;
-
-    m_trainer_spells.clear();
-    m_trainer_type = 0;
-
-    Field *fields;
-    QueryResult *result = WorldDatabase.PQuery("SELECT spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer WHERE entry = '%u'", GetEntry());
-
-    if(!result)
-        return;
-
-    do
-    {
-        fields = result->Fetch();
-
-        uint32 spellid = fields[0].GetUInt32();
-        SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid);
-
-        if(!spellinfo)
-        {
-            sLog.outErrorDb("Trainer (Entry: %u ) has non existing spell %u",GetEntry(),spellid);
-            continue;
-        }
-
-        if(!SpellMgr::IsSpellValid(spellinfo))
-        {
-            sLog.outErrorDb("LoadTrainerSpells: Trainer (Entry: %u) has broken learning spell %u.", GetEntry(), spellid);
-            continue;
-        }
-
-        if(SpellMgr::IsProfessionSpell(spellinfo->Id))
-            m_trainer_type = 2;
-
-        TrainerSpell tspell;
-        tspell.spell        = spellinfo;
-        tspell.spellcost    = fields[1].GetUInt32();
-        tspell.reqskill     = fields[2].GetUInt32();
-        tspell.reqskillvalue= fields[3].GetUInt32();
-        tspell.reqlevel     = fields[4].GetUInt32();
-
-        m_trainer_spells.push_back(tspell);
-
-    } while( result->NextRow() );
-
-    delete result;
-
-    m_trainerSpellsLoaded = true;
 }
 
@@ -551,5 +514,8 @@
         return false;
 
-    if(m_trainer_spells.empty())
+    TrainerSpellData const* trainer_spells = GetTrainerSpells();
+
+
+    if(!trainer_spells || trainer_spells->spellList.empty())
     {
         sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_TRAINER but have empty trainer spell list.",
@@ -719,7 +685,4 @@
                         break;
                     case GOSSIP_OPTION_TRAINER:
-                        // Lazy loading at first access
-                        LoadTrainerSpells();
-
                         if(!isCanTrainingOf(pPlayer,false))
                             cantalking=false;
@@ -757,5 +720,5 @@
             if(!gso->Option.empty() && cantalking )
             {                                               //note for future dev: should have database fields for BoxMessage & BoxMoney
-                pm->GetGossipMenu()->AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false);
+                pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false);
                 ingso=gso;
             }
@@ -764,9 +727,8 @@
 
     ///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-)
-    if(pm->GetGossipMenu()->MenuItemCount()==0 && !pm->GetQuestMenu()->MenuItemCount())
+    if(pm->Empty())
     {
         if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER))
         {
-            LoadTrainerSpells();                            // Lazy loading at first access
             isCanTrainingOf(pPlayer,true);                  // output error message if need
         }
@@ -783,8 +745,8 @@
         return;
 
-    GossipMenu* gossipmenu = player->PlayerTalkClass->GetGossipMenu();
+    GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu();
 
     // in case empty gossip menu open quest menu if any
-    if (gossipmenu->MenuItemCount() == 0 && GetNpcTextId() == 0)
+    if (gossipmenu.Empty() && GetNpcTextId() == 0)
     {
         player->SendPreparedQuest(GetGUID());
@@ -799,6 +761,10 @@
 void Creature::OnGossipSelect(Player* player, uint32 option)
 {
-    GossipMenu* gossipmenu = player->PlayerTalkClass->GetGossipMenu();
-    uint32 action=gossipmenu->GetItem(option).m_gAction;
+    GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu();
+
+    if(option >= gossipmenu.MenuItemCount())
+        return;
+
+    uint32 action=gossipmenu.GetItem(option).m_gAction;
     uint32 zoneid=GetZoneId();
     uint64 guid=GetGUID();
@@ -969,19 +935,8 @@
 uint32 Creature::GetNpcTextId()
 {
-    // already loaded and cached
-    if(m_NPCTextId)
-        return m_NPCTextId;
-
-    QueryResult* result = WorldDatabase.PQuery("SELECT textid FROM npc_gossip WHERE npc_guid= '%u'", m_DBTableGuid);
-    if(result)
-    {
-        Field *fields = result->Fetch();
-        m_NPCTextId = fields[0].GetUInt32();
-        delete result;
-    }
-    else
-        m_NPCTextId = DEFAULT_GOSSIP_MESSAGE;
-
-    return m_NPCTextId;
+    if(uint32 pos = objmgr.GetNpcGossip(m_DBTableGuid))
+        return pos;
+
+    return DEFAULT_GOSSIP_MESSAGE;
 }
 
@@ -1400,35 +1355,10 @@
     m_vendor_items.clear();
 
-    QueryResult *result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry = '%u'", GetEntry());
-
-    if(!result)
+    VendorItemList const* vList = objmgr.GetNpcVendorItemList(GetEntry());
+    if(!vList)
         return;
 
-    do
-    {
-        Field *fields = result->Fetch();
-
-        if (GetItemCount() >= MAX_VENDOR_ITEMS)
-        {
-            sLog.outErrorDb( "Vendor %u has too many items (%u >= %i). Check the DB!", GetEntry(), GetItemCount(), MAX_VENDOR_ITEMS );
-            break;
-        }
-
-        uint32 item_id = fields[0].GetUInt32();
-        if(!sItemStorage.LookupEntry<ItemPrototype>(item_id))
-        {
-            sLog.outErrorDb("Vendor %u have in item list non-existed item %u",GetEntry(),item_id);
-            continue;
-        }
-
-        uint32 ExtendedCost = fields[3].GetUInt32();
-        if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost))
-            sLog.outErrorDb("Item (Entry: %u) has wrong ExtendedCost (%u) for vendor (%u)",item_id,ExtendedCost,GetEntry());
-
-        AddItem( item_id, fields[1].GetUInt32(), fields[2].GetUInt32(), ExtendedCost);
-    }
-    while( result->NextRow() );
-
-    delete result;
+    for (VendorItemList::const_iterator _item_iter = vList->begin(); _item_iter != vList->end(); ++_item_iter)
+        AddItem( (*_item_iter)->item, (*_item_iter)->maxcount, (*_item_iter)->incrtime, (*_item_iter)->ExtendedCost);
 
     m_itemsLoaded = true;
@@ -1992,2 +1922,7 @@
     return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptName;
 }
+
+TrainerSpellData const* Creature::GetTrainerSpells() const
+{
+    return objmgr.GetNpcTrainerSpells(GetEntry());
+}
Index: trunk/src/game/ObjectMgr.cpp
===================================================================
--- trunk/src/game/ObjectMgr.cpp (revision 2)
+++ trunk/src/game/ObjectMgr.cpp (revision 6)
@@ -133,4 +133,11 @@
     for(ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr)
         delete itr->second;
+
+    for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
+        for (VendorItemList::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
+            delete (*itr2);
+
+    for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr)
+        itr->second.Clear();
 }
 
@@ -255,10 +262,10 @@
 void ObjectMgr::SendAuctionWonMail( AuctionEntry *auction )
 {
-    Item *pItem = objmgr.GetAItem(auction->item_guidlow);
+    Item *pItem = GetAItem(auction->item_guidlow);
     if(!pItem)
         return;
 
     uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
-    Player *bidder = objmgr.GetPlayer(bidder_guid);
+    Player *bidder = GetPlayer(bidder_guid);
 
     uint32 bidder_accId = 0;
@@ -328,5 +335,5 @@
             bidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, bidder_guid, 0, 0, auction->item_template);
         else
-            objmgr.RemoveAItem(pItem->GetGUIDLow());        // we have to remove the item, before we delete it !!
+            RemoveAItem(pItem->GetGUIDLow());               // we have to remove the item, before we delete it !!
 
         // will delete item or place to receiver mail list
@@ -337,5 +344,5 @@
     {
         CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", pItem->GetGUIDLow());
-        objmgr.RemoveAItem(pItem->GetGUIDLow());            // we have to remove the item, before we delete it !!
+        RemoveAItem(pItem->GetGUIDLow());                   // we have to remove the item, before we delete it !!
         delete pItem;
     }
@@ -345,5 +352,5 @@
 {
     uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER);
-    Player *owner = objmgr.GetPlayer(owner_guid);
+    Player *owner = GetPlayer(owner_guid);
 
     // owner exist (online or offline)
@@ -376,5 +383,5 @@
 {
     uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER);
-    Player *owner = objmgr.GetPlayer(owner_guid);
+    Player *owner = GetPlayer(owner_guid);
 
     uint32 owner_accId = 0;
@@ -415,5 +422,5 @@
 void ObjectMgr::SendAuctionExpiredMail( AuctionEntry * auction )
 {                                                           //return an item in auction to its owner by mail
-    Item *pItem = objmgr.GetAItem(auction->item_guidlow);
+    Item *pItem = GetAItem(auction->item_guidlow);
     if(!pItem)
     {
@@ -423,5 +430,5 @@
 
     uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER);
-    Player *owner = objmgr.GetPlayer(owner_guid);
+    Player *owner = GetPlayer(owner_guid);
 
     uint32 owner_accId = 0;
@@ -438,5 +445,5 @@
             owner->GetSession()->SendAuctionOwnerNotification( auction );
         else
-            objmgr.RemoveAItem(pItem->GetGUIDLow());        // we have to remove the item, before we delete it !!
+            RemoveAItem(pItem->GetGUIDLow());               // we have to remove the item, before we delete it !!
 
         MailItemsInfo mi;
@@ -451,5 +458,5 @@
     {
         CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'",pItem->GetGUIDLow());
-        objmgr.RemoveAItem(pItem->GetGUIDLow());            // we have to remove the item, before we delete it !!
+        RemoveAItem(pItem->GetGUIDLow());                   // we have to remove the item, before we delete it !!
         delete pItem;
     }
@@ -1737,5 +1744,5 @@
         uint32 item_template    = fields[1].GetUInt32();
 
-        ItemPrototype const *proto = objmgr.GetItemPrototype(item_template);
+        ItemPrototype const *proto = GetItemPrototype(item_template);
 
         if(!proto)
@@ -3688,5 +3695,5 @@
             case SCRIPT_COMMAND_QUEST_EXPLORED:
             {
-                Quest const* quest = objmgr.GetQuestTemplate(tmp.datalong);
+                Quest const* quest = GetQuestTemplate(tmp.datalong);
                 if(!quest)
                 {
@@ -3768,5 +3775,5 @@
 void ObjectMgr::LoadQuestEndScripts()
 {
-    objmgr.LoadScripts(sQuestEndScripts,  "quest_end_scripts");
+    LoadScripts(sQuestEndScripts,  "quest_end_scripts");
 
     // check ids
@@ -3780,5 +3787,5 @@
 void ObjectMgr::LoadQuestStartScripts()
 {
-    objmgr.LoadScripts(sQuestStartScripts,"quest_start_scripts");
+    LoadScripts(sQuestStartScripts,"quest_start_scripts");
 
     // check ids
@@ -3792,5 +3799,5 @@
 void ObjectMgr::LoadSpellScripts()
 {
-    objmgr.LoadScripts(sSpellScripts, "spell_scripts");
+    LoadScripts(sSpellScripts, "spell_scripts");
 
     // check ids
@@ -3827,5 +3834,5 @@
 void ObjectMgr::LoadEventScripts()
 {
-    objmgr.LoadScripts(sEventScripts, "event_scripts");
+    LoadScripts(sEventScripts, "event_scripts");
 
     std::set<uint32> evt_scripts;
@@ -4231,5 +4238,5 @@
         Player *pl = 0;
         if (serverUp)
-            pl = objmgr.GetPlayer((uint64)m->receiver);
+            pl = GetPlayer((uint64)m->receiver);
         if (pl && pl->m_mailsLoaded)
         {                                                   //this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail
@@ -4504,5 +4511,5 @@
         {
             mount_entry = node->alliance_mount_type;
-            CreatureInfo const *ci = objmgr.GetCreatureTemplate(mount_entry);
+            CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
             if(ci)
                 mount_id = ci->DisplayID_A;
@@ -4511,5 +4518,5 @@
         {
             mount_entry = node->horde_mount_type;
-            CreatureInfo const *ci = objmgr.GetCreatureTemplate(mount_entry);
+            CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
             if(ci)
                 mount_id = ci->DisplayID_H;
@@ -4517,5 +4524,5 @@
     }
 
-    CreatureModelInfo const *minfo = objmgr.GetCreatureModelInfo(mount_id);
+    CreatureModelInfo const *minfo = GetCreatureModelInfo(mount_id);
     if(!minfo)
     {
@@ -4809,5 +4816,5 @@
         if(at.requiredItem)
         {
-            ItemPrototype const *pProto = objmgr.GetItemPrototype(at.requiredItem);
+            ItemPrototype const *pProto = GetItemPrototype(at.requiredItem);
             if(!pProto)
             {
@@ -4818,5 +4825,5 @@
         if(at.requiredItem2)
         {
-            ItemPrototype const *pProto = objmgr.GetItemPrototype(at.requiredItem2);
+            ItemPrototype const *pProto = GetItemPrototype(at.requiredItem2);
             if(!pProto)
             {
@@ -4828,5 +4835,5 @@
         if(at.heroicKey)
         {
-            ItemPrototype const *pProto = objmgr.GetItemPrototype(at.heroicKey);
+            ItemPrototype const *pProto = GetItemPrototype(at.heroicKey);
             if(!pProto)
             {
@@ -4838,5 +4845,5 @@
         if(at.heroicKey2)
         {
-            ItemPrototype const *pProto = objmgr.GetItemPrototype(at.heroicKey2);
+            ItemPrototype const *pProto = GetItemPrototype(at.heroicKey2);
             if(!pProto)
             {
@@ -5446,5 +5453,5 @@
     if(list0.empty() || list1.empty())
     {
-        CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(entry);
+        CreatureInfo const *cinfo = GetCreatureTemplate(entry);
         char* petname = GetPetName(cinfo->family, sWorld.GetDefaultDbcLocale());
         if(!petname)
@@ -5540,8 +5547,8 @@
         repOnKill.repfaction2          = fields[2].GetUInt32();
         repOnKill.is_teamaward1        = fields[3].GetBool();
-        repOnKill.reputration_max_cap1 = fields[4].GetUInt32();
+        repOnKill.reputation_max_cap1  = fields[4].GetUInt32();
         repOnKill.repvalue1            = fields[5].GetInt32();
         repOnKill.is_teamaward2        = fields[6].GetBool();
-        repOnKill.reputration_max_cap2 = fields[7].GetUInt32();
+        repOnKill.reputation_max_cap2  = fields[7].GetUInt32();
         repOnKill.repvalue2            = fields[8].GetInt32();
         repOnKill.team_dependent       = fields[9].GetUInt8();
@@ -6098,10 +6105,10 @@
 }
 
-bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, bool positive_entries)
+bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value)
 {
     // cleanup affected map part for reloading case
     for(MangosStringLocaleMap::iterator itr = mMangosStringLocaleMap.begin(); itr != mMangosStringLocaleMap.end();)
     {
-        if(itr->first > 0 && positive_entries || itr->first < 0 && !positive_entries)
+        if(itr->first >= min_value && itr->first <= max_value)
         {
             MangosStringLocaleMap::iterator itr2 = itr;
@@ -6122,10 +6129,12 @@
 
         sLog.outString("");
-        if(positive_entries)                                // error only in case internal strings
+        if(min_value > 0)                                   // error only in case internal strings
             sLog.outErrorDb(">> Loaded 0 mangos strings. DB table `%s` is empty. Cannot continue.",table);
         else
-            sLog.outString(">> Loaded 0 mangos strings. DB table `%s` is empty.",table);
+            sLog.outString(">> Loaded 0 string templates. DB table `%s` is empty.",table);
         return false;
     }
+
+    uint32 count = 0;
 
     barGoLink bar(result->GetRowCount());
@@ -6143,25 +6152,22 @@
             continue;
         }
-        else if(entry < 0)
-        {
-            if(positive_entries)
-            {
-                sLog.outString("Table `%s` contain unexpected negative entry %i, ignored.",table,entry);
-                continue;
-            }
-        }
-        else
-        {
-            if(!positive_entries)
-            {
-                sLog.outString("Table `%s` contain unexpected positive entry %i, ignored.",table,entry);
-                continue;
-            }
+        else if(entry < min_value || entry > max_value)
+        {
+            int32 start = min_value > 0 ? min_value : max_value;
+            int32 end   = min_value > 0 ? max_value : min_value;
+            sLog.outString("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,start,end);
+            continue;
         }
 
         MangosStringLocale& data = mMangosStringLocaleMap[entry];
 
-        if(data.Content.size() < 1)
-            data.Content.resize(1);
+        if(data.Content.size() > 0)
+        {
+            sLog.outString("Table `%s` contain data for already loaded entry  %i (from another table?), ignored.",table,entry);
+            continue;
+        }
+
+        data.Content.resize(1);
+        ++count;
 
         // 0 -> default, idx in to idx+1
@@ -6189,5 +6195,9 @@
 
     sLog.outString();
-    sLog.outString( ">> Loaded %u MaNGOS strings from table %s", mMangosStringLocaleMap.size(),table);
+    if(min_value > 0)                                       // internal mangos strings
+        sLog.outString( ">> Loaded %u MaNGOS strings from table %s", count,table);
+    else
+        sLog.outString( ">> Loaded %u string templates from %s", count,table);
+
     return true;
 }
@@ -6500,4 +6510,334 @@
 }
 
+void ObjectMgr::LoadGameTele()
+{
+    m_GameTeleMap.clear();                                  // for relaod case
+
+    uint32 count = 0;
+    QueryResult *result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, map, name FROM game_tele");
+
+    if( !result )
+    {
+        barGoLink bar( 1 );
+
+        bar.step();
+
+        sLog.outString();
+        sLog.outErrorDb(">> Loaded `game_tele`, table is empty!");
+        return;
+    }
+
+    barGoLink bar( result->GetRowCount() );
+
+    do
+    {
+        bar.step();
+
+        Field *fields = result->Fetch();
+
+        uint32 id         = fields[0].GetUInt32();
+
+        GameTele gt;
+
+        gt.position_x     = fields[1].GetFloat();
+        gt.position_y     = fields[2].GetFloat();
+        gt.position_z     = fields[3].GetFloat();
+        gt.orientation    = fields[4].GetFloat();
+        gt.mapId          = fields[5].GetUInt32();
+        gt.name           = fields[6].GetCppString();
+
+        if(!MapManager::IsValidMapCoord(gt.mapId,gt.position_x,gt.position_y,gt.position_z,gt.orientation))
+        {
+            sLog.outErrorDb("Wrong position for id %u (name: %s) in `game_tele` table, ignoring.",id,gt.name.c_str());
+            continue;
+        }
+
+        if(!Utf8toWStr(gt.name,gt.wnameLow))
+        {
+            sLog.outErrorDb("Wrong UTF8 name for id %u in `game_tele` table, ignoring.",id);
+            continue;
+        }
+
+        wstrToLower( gt.wnameLow );
+
+        m_GameTeleMap[id] = gt;
+
+        ++count;
+    }
+    while (result->NextRow());
+
+    delete result;
+
+    sLog.outString();
+    sLog.outString( ">> Loaded %u game tele's", count );
+}
+
+GameTele const* ObjectMgr::GetGameTele(std::string name) const
+{
+    // explicit name case
+    std::wstring wname;
+    if(!Utf8toWStr(name,wname))
+        return false;
+
+    // converting string that we try to find to lower case
+    wstrToLower( wname );
+
+    for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr)
+        if(itr->second.wnameLow == wname)
+            return &itr->second;
+
+    return NULL;
+}
+
+bool ObjectMgr::AddGameTele(GameTele& tele)
+{
+    // find max id
+    uint32 new_id = 0;
+    for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr)
+        if(itr->first > new_id)
+            new_id = itr->first;
+    
+    // use next
+    ++new_id;
+
+    if(!Utf8toWStr(tele.name,tele.wnameLow))
+        return false;
+
+    wstrToLower( tele.wnameLow );
+
+    m_GameTeleMap[new_id] = tele;
+
+    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')",
+        new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str());
+}
+
+bool ObjectMgr::DeleteGameTele(std::string name)
+{
+    // explicit name case
+    std::wstring wname;
+    if(!Utf8toWStr(name,wname))
+        return false;
+
+    // converting string that we try to find to lower case
+    wstrToLower( wname );
+
+    for(GameTeleMap::iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr)
+    {
+        if(itr->second.wnameLow == wname)
+        {
+            WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",itr->second.name.c_str());
+            m_GameTeleMap.erase(itr);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void ObjectMgr::LoadTrainerSpell()
+{
+    // For reload case 
+    for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr)
+        itr->second.Clear();
+    m_mCacheTrainerSpellMap.clear();
+
+    QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer");
+
+    if( !result )
+    {
+        barGoLink bar( 1 );
+
+        bar.step();
+
+        sLog.outString();
+        sLog.outErrorDb(">> Loaded `npc_trainer`, table is empty!");
+        return;
+    }
+
+    barGoLink bar( result->GetRowCount() );
+
+    uint32 count = 0,entry,spell;
+    do
+    {
+        bar.step();
+
+        Field* fields = result->Fetch();
+
+        entry  = fields[0].GetUInt32();
+        spell  = fields[1].GetUInt32();
+
+        if(!GetCreatureTemplate(entry))
+        {
+            sLog.outErrorDb("Table `npc_trainer` have entry for not existed creature template (Entry: %u), ignore", entry);
+            continue;
+        }
+
+        SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell);
+        if(!spellinfo)
+        {
+            sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u ) has non existing spell %u, ignore", entry,spell);
+            continue;
+        }
+
+        if(!SpellMgr::IsSpellValid(spellinfo))
+        {
+            sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has broken learning spell %u, ignore", entry, spell);
+            continue;
+        }
+
+        TrainerSpell* pTrainerSpell = new TrainerSpell();
+        pTrainerSpell->spell         = spell;
+        pTrainerSpell->spellcost     = fields[2].GetUInt32();
+        pTrainerSpell->reqskill      = fields[3].GetUInt32();
+        pTrainerSpell->reqskillvalue = fields[4].GetUInt32();
+        pTrainerSpell->reqlevel      = fields[5].GetUInt32();
+
+        if(!pTrainerSpell->reqlevel)
+            pTrainerSpell->reqlevel = spellinfo->spellLevel;
+
+
+        TrainerSpellData& data = m_mCacheTrainerSpellMap[entry];
+
+        if(SpellMgr::IsProfessionSpell(spell))
+            data.trainerType = 2;
+
+        data.spellList.push_back(pTrainerSpell);
+        ++count;
+
+    } while (result->NextRow());
+    delete result;
+
+    sLog.outString();
+    sLog.outString( ">> Loaded Trainers %d", count );
+}
+
+void ObjectMgr::LoadVendors()
+{
+    // For reload case 
+    for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
+    {
+        for (VendorItemList::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
+            delete (*itr2);
+    }
+    m_mCacheVendorItemMap.clear();
+
+    QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor");
+    if( !result )
+    {
+        barGoLink bar( 1 );
+
+        bar.step();
+
+        sLog.outString();
+        sLog.outErrorDb(">> Loaded `npc_vendor`, table is empty!");
+        return;
+    }
+
+    barGoLink bar( result->GetRowCount() );
+
+    uint32 count = 0;
+    uint32 entry, item_id, ExtendedCost;
+    do
+    {
+        bar.step();
+        Field* fields = result->Fetch();
+
+        entry = fields[0].GetUInt32();
+        if(!GetCreatureTemplate(entry))
+        {
+            sLog.outErrorDb("Table `npc_vendor` have data for not existed creature template (Entry: %u), ignore", entry);
+            continue;
+        }
+
+        item_id  = fields[1].GetUInt32();
+        if(!GetItemPrototype(item_id))
+        {
+            sLog.outErrorDb("Table `npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore",entry,item_id);
+            continue;
+        }
+
+        ExtendedCost = fields[4].GetUInt32();
+        if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost))
+        {
+            sLog.outErrorDb("Table `npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore",item_id,ExtendedCost,entry);
+            continue;
+        }
+
+        VendorItemList& vList = m_mCacheVendorItemMap[entry];
+
+        if(vList.size() >= MAX_VENDOR_ITEMS)
+        {
+            sLog.outErrorDb( "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", vList.size(), MAX_VENDOR_ITEMS, entry);
+            continue;
+        }
+
+        VendorItem* pVendorItem = new VendorItem();
+        pVendorItem->item         = item_id;
+        pVendorItem->maxcount     = fields[2].GetUInt32();
+        pVendorItem->incrtime     = fields[3].GetUInt32();
+        pVendorItem->ExtendedCost = ExtendedCost;
+
+        vList.push_back(pVendorItem);
+        ++count;
+
+    } while (result->NextRow());
+    delete result;
+
+    sLog.outString();
+    sLog.outString( ">> Loaded %d Vendors ", count );
+}
+
+void ObjectMgr::LoadNpcTextId()
+{
+
+    m_mCacheNpcTextIdMap.clear();
+
+    QueryResult* result = WorldDatabase.PQuery("SELECT npc_guid, textid FROM npc_gossip");
+    if( !result )
+    {
+        barGoLink bar( 1 );
+
+        bar.step();
+
+        sLog.outString();
+        sLog.outErrorDb(">> Loaded `npc_gossip`, table is empty!");
+        return;
+    }
+
+    barGoLink bar( result->GetRowCount() );
+
+    uint32 count = 0;
+    uint32 guid,textid;
+    do
+    {
+        bar.step();
+
+        Field* fields = result->Fetch();
+
+        guid   = fields[0].GetUInt32();
+        textid = fields[1].GetUInt32();
+
+        if (!GetCreatureData(guid))
+        {
+            sLog.outErrorDb("Table `npc_gossip` have not existed creature (GUID: %u) entry, ignore. ",guid);
+            continue;
+        }
+        if (!GetGossipText(textid))
+        {
+            sLog.outErrorDb("Table `npc_gossip` for creature (GUID: %u) have wrong Textid (%u), ignore. ", guid, textid);
+            continue;
+        }
+
+        m_mCacheNpcTextIdMap[guid] = textid ;
+        ++count;
+
+    } while (result->NextRow());
+    delete result;
+
+    sLog.outString();
+    sLog.outString( ">> Loaded %d NpcTextId ", count );
+}
+
+// Functions for scripting access
 const char* GetAreaTriggerScriptNameById(uint32 id)
 {
@@ -6505,8 +6845,14 @@
 }
 
-
-bool LoadMangosStrings(DatabaseType& db, char const* table)
-{
+bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value)
+{
+    if(start_value >= 0 || start_value <= end_value)        // start/end reversed for negative values
+    {
+        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());
+        start_value = -1;
+        end_value = std::numeric_limits<int32>::min();
+    }
+
     // for scripting localized strings allowed use _only_ negative entries
-    return objmgr.LoadMangosStrings(db,table,false);
-}
+    return objmgr.LoadMangosStrings(db,table,end_value,start_value);
+}
Index: trunk/src/game/Language.h
===================================================================
--- trunk/src/game/Language.h (revision 2)
+++ trunk/src/game/Language.h (revision 6)
@@ -154,6 +154,6 @@
     LANG_COMMAND_TELE_NOTFOUND          = 164,
     LANG_COMMAND_TELE_PARAMETER         = 165,
-    LANG_COMMAND_TELE_NOREQUEST         = 166,
-    LANG_COMMAND_TELE_NOLOCATION        = 167,
+    LANG_COMMAND_TELE_NOLOCATION        = 166,
+    //                                    167               // not used
     LANG_COMMAND_TELE_LOCATION          = 168,
 
@@ -301,4 +301,7 @@
     LANG_COMMAND_FACTION_NOREP_ERROR    = 326,
     LANG_FACTION_NOREPUTATION           = 327,
+    LANG_LOOKUP_PLAYER_ACCOUNT          = 328,
+    LANG_LOOKUP_PLAYER_CHARACTER        = 329,
+    LANG_NO_PLAYERS_FOUND               = 330,
 
     // Room for more level 2
@@ -376,5 +379,5 @@
     LANG_COMMAND_TP_ADDEDERR            = 464,
     LANG_COMMAND_TP_DELETED             = 465,
-    LANG_COMMAND_TP_DELETEERR           = 466,
+    //                                    466,              // not used
 
     LANG_COMMAND_TARGET_LISTAURAS       = 467,
