/* EQ2Emulator: Everquest II Server Emulator Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) This file is part of EQ2Emulator. */ #ifndef LWORLD_H #define LWORLD_H #include "../common/Mutex.h" #define ERROR_BADPASSWORD "Bad password" #define INVALID_ACCOUNT "Invalid Server Account. Make sure you put in the account information in your LoginServer.ini file." #define ERROR_BADVERSION "Incorrect version" #define ERROR_UNNAMED "Unnamed servers not allowed to connect to full login servers" #define ERROR_NOTMASTER "Not a master server" #define ERROR_NOTMESH "Not a mesh server" #define ERROR_GHOST "Ghost kick" #define ERROR_UnknownServerType "Unknown Server Type" #define ERROR_BADNAME_SERVER "Bad server name, name may not contain the word \"Server\" (case sensitive)" #define ERROR_BADNAME "Bad server name. Unknown reason." #define WORLD_NAME_SUFFIX " Server" #include "../common/linked_list.h" #include "../WorldServer/MutexList.h" #include "../WorldServer/MutexMap.h" #include "../common/timer.h" #include "../common/types.h" #include "../common/queue.h" #include "../common/servertalk.h" #include "../common/TCPConnection.h" #include "client.h" #define MAX_UPDATE_COUNT 20 #ifdef WIN32 void ServerUpdateLoop(void* tmp); #else void* ServerUpdateLoop(void* tmp); #endif enum ConType { UnknownW, World, Chat, Login }; class LWorld { public: LWorld(TCPConnection* in_con, bool OutgoingLoginUplink = false, int32 iIP = 0, int16 iPort = 0, bool iNeverKick = false); LWorld(int32 in_accountid, char* in_accountname, char* in_worldname, int32 in_admin_id); LWorld(TCPConnection* in_RemoteLink, int32 in_ip, int32 in_RemoteID, int32 in_accountid, char* in_accountname, char* in_worldname, char* in_address, sint32 in_status, int32 in_adminid, bool in_showdown, int8 in_authlevel, bool in_placeholder, int32 iLinkWorldID); ~LWorld(); static bool CheckServerName(const char* name); bool Process(); void SendPacket(ServerPacket* pack); void Message(const char* to, const char* message, ...); bool SetupWorld(char* in_worldname, char* in_worldaddress, char* in_account, char* in_password, char* in_version); void UpdateStatus(sint32 in_status, sint32 in_players, sint32 in_zones) { // we don't want the server list to update unless something has changed if(status != in_status || num_players != in_players || num_zones != in_zones) { status = in_status; num_players = in_players; num_zones = in_zones; UpdateWorldList(); } } void UpdateWorldList(LWorld* to = 0); void SetRemoteInfo(int32 in_ip, int32 in_accountid, char* in_account, char* in_name, char* in_address, int32 in_status, int32 in_adminid, sint32 in_players, sint32 in_zones); inline bool IsPlaceholder() { return pPlaceholder; } inline int32 GetAccountID() { return accountid; } inline char* GetAccount() { return account; } inline char* GetAddress() { return address; } inline int16 GetClientPort() { return pClientPort; } inline bool IsAddressIP() { return isaddressip; } inline char* GetName() { return worldname; } inline sint32 GetStatus() { return status; } bool IsLocked() { return status==-2; } inline int32 GetIP() { return ip; } inline int16 GetPort() { return port; } inline int32 GetID() { return ID; } inline int32 GetAdmin() { return admin_id; } inline bool ShowDown() { return pshowdown; } inline bool ShowDownActive(){ return show_down_active; } void ShowDownActive(bool show){ show_down_active = show; } void ShowDown(bool show){ pshowdown = show; } inline bool Connected() { return pConnected; } int8 GetWorldStatus(); void ChangeToPlaceholder(); void Kick(const char* message = ERROR_GHOST, bool iSetKickedFlag = true); inline bool IsKicked() { return kicked; } inline bool IsNeverKick() { return pNeverKick; } inline ConType GetType() { return ptype; } inline bool IsOutgoingUplink() { return OutgoingUplink; } inline TCPConnection* GetLink() { return Link; } inline int32 GetRemoteID() { return RemoteID; } inline int32 GetLinkWorldID() { return LinkWorldID; } inline sint32 GetZoneNum() { return num_zones; } inline sint32 GetPlayerNum() { return num_players; } void SetID(int32 new_id) { ID = new_id; } void SendDeleteCharacter( int32 char_id, int32 account_id ); bool IsDevelServer(){ return devel_server; } bool IsInit; protected: friend class LWorldList; TCPConnection* Link; Timer* pReconnectTimer; Timer* pStatsTimer; private: int32 ID; int32 ip; int16 port; bool kicked; bool pNeverKick; bool pPlaceholder; bool devel_server; int32 accountid; char account[30]; char address[250]; bool isAuthenticated; int16 pClientPort; bool isaddressip; char worldname[200]; sint32 status; int32 admin_id; bool pshowdown; bool show_down_active; ConType ptype; bool OutgoingUplink; bool pConnected; sint32 num_players; sint32 num_zones; int32 RemoteID; int32 LinkWorldID; }; class LWorldList { public: LWorldList(); ~LWorldList(); LWorld* FindByID(int32 WorldID); LWorld* FindByIP(int32 ip); LWorld* FindByAddress(char* address); LWorld* FindByLink(TCPConnection* in_link, int32 in_id); LWorld* FindByAccount(int32 in_accountid, ConType in_type = World); void Add(LWorld* worldserver); void AddInitiateWorld ( LWorld* world ); void Process(); void ReceiveData(); void SendPacket(ServerPacket* pack, LWorld* butnotme = 0); void SendPacketLocal(ServerPacket* pack, LWorld* butnotme = 0); void SendPacketLogin(ServerPacket* pack, LWorld* butnotme = 0); void SendWorldChanged(int32 server_id, bool sendtoallclients=false, Client* sendto = 0); vector* GetServerListUpdate(int16 version); EQ2Packet* MakeServerListPacket(int8 lsadmin, int16 version); void UpdateWorldList(LWorld* to = 0); void UpdateWorldStats(); void KickGhost(ConType in_type, int32 in_accountid = 0, LWorld* ButNotMe = 0); void KickGhostIP(int32 ip, LWorld* NotMe = 0, int16 iClientPort = 0); void RemoveByLink(TCPConnection* in_link, int32 in_id = 0, LWorld* ButNotMe = 0); void RemoveByID(int32 in_id); void SendWorldStatus(LWorld* chat, char* adminname); void ConnectUplink(); bool Init(); void InitWorlds(); void Shutdown(); bool WriteXML(); void ListWorldsToConsole(); void SetUpdateServerList ( bool var ) { UpdateServerList = var; } bool ContinueServerUpdates(){ return server_update_thread; } void ResetServerUpdates(){server_update_thread = true;} void ProcessServerUpdates(); void RequestServerUpdates(LWorld* world); void AddServerZoneUpdates(LWorld* world, map updates); protected: friend class LWorld; int32 GetNextID() { return NextID++; } private: Mutex MWorldMap; map > zone_updates_already_used; //used to determine if someone is trying to DOS us MutexMap zone_update_timeouts; MutexMap awaiting_zone_update; MutexMap last_updated; MutexMap > server_zone_updates; bool server_update_thread; int32 NextID; LinkedList list; map worldmap; TCPServer* tcplistener; TCPConnection* OutLink; // holds the world server list so we don't have to create it for every character // logging in map ServerListData; bool UpdateServerList; }; #endif