Index: sql/MangChat.sql
===================================================================
--- sql/MangChat.sql (revision 0)
+++ sql/MangChat.sql (revision 0)
@@ -0,0 +1,46 @@
+-- MySQL dump 10.11
+--
+-- Host: localhost Database: mangos
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `irc_inchan`
+--
+
+DROP TABLE IF EXISTS `irc_inchan`;
+CREATE TABLE `irc_inchan` (
+ `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier',
+ `name` varchar(12) NOT NULL default '',
+ `team` smallint(3) unsigned NOT NULL default '0',
+ PRIMARY KEY (`guid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='IRC Module system';
+
+--
+-- Table structure for table `irc_logedin`
+--
+
+DROP TABLE IF EXISTS `irc_logedin`;
+CREATE TABLE `irc_logedin` (
+ `account` int(11) unsigned NOT NULL default '0' COMMENT 'Account Identifier',
+ `nick` varchar(50) NOT NULL default '',
+ `gmlevel` tinyint(3) unsigned NOT NULL default '0',
+ PRIMARY KEY (`account`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='IRC Module system';
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
Index: src/game/Channel.cpp
===================================================================
--- src/game/Channel.cpp (revision 3815)
+++ src/game/Channel.cpp (working copy)
@@ -16,9 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "Common.h"
#include "Channel.h"
#include "ObjectMgr.h"
#include "Chat.h"
+#include "IRCClient.h"
Channel::Channel(std::string _name)
: name(_name), announce(true), constant(false), moderate(false), m_ownerGUID(0), password("")
@@ -30,6 +32,13 @@
constant = true; // built-in channel
announce = false; // no join/leave announces
}
+ std::string tempname = _name;
+ std::transform(tempname.begin(), tempname.end(), tempname.begin(), towlower);
+ if (sIRC.WOW_CHAN == tempname)
+ {
+ constant = true; // built-in channel
+ announce = false; // no join/leave announces
+ }
}
void Channel::Join(uint64 p, const char *pass, uint32 unk1)
Index: src/game/CharacterHandler.cpp
===================================================================
--- src/game/CharacterHandler.cpp (revision 3815)
+++ src/game/CharacterHandler.cpp (working copy)
@@ -34,6 +34,8 @@
#include "ObjectAccessor.h"
#include "Transports.h"
#include "Group.h"
+#include "IRCClient.h"
+#include "Config/ConfigEnv.h"
// check used symbols in player name at creating and rename
std::string notAllowedChars = "\t\v\b\f\a\n\r\\\"\'\? <>[](){}_=+-|/!@#$%^&*~`.,0123456789\0";
@@ -563,8 +565,51 @@
if(sWorld.IsShutdowning())
sWorld.ShutdownMsg(true,pCurrChar);
+ bool announceallowed = true;
if(pCurrChar->isGameMaster())
+ {
SendNotification("GM mode is ON");
+ //retreive the toggle value from the conf
+ std::string GMLoginMessage = sConfig.GetStringDefault("GMAnnounceMessage","|cffff0000[$Rank $Name has come Online]|r");
+ std::string GMLoginIRCMessage = sConfig.GetStringDefault("GMAnnounceIRCMessage","12>>04 $Rank $Name has come Online");
+ std::string GMRankMod= sConfig.GetStringDefault("GMRankMod","Mod");
+ std::string GMRankGM= sConfig.GetStringDefault("GMRankGM","GM");
+ std::string GMRankAdmin= sConfig.GetStringDefault("GMRankAdmin","Admin");
+ //retreive the custom message from the conf
+
+ std::string GMRank;//String to store readable GM rank 1=mod 2=gm 3=admin
+
+ switch(GetSecurity())//switch case to determine what rank the "gm" is
+ {
+ case 1: GMRank = GMRankMod;break;
+ case 2: GMRank = GMRankGM;break;
+ case 3: GMRank = GMRankAdmin;break;
+ }
+
+ if((sIRC.BOTMASK & 32)!= 0)
+ {
+ announceallowed = false;
+ std::string str = sIRC.MakeMsg(sIRC.MakeMsg(GMLoginMessage, "$Name", pCurrChar->GetName()), "$Rank", GMRank);
+ sWorld.SendWorldText(str.c_str(), NULL);
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.MakeMsg(GMLoginIRCMessage, "$Name", pCurrChar->GetName()), "$Rank", GMRank));
+ sLog.outBasic("GM '%s' logged in and announced",pCurrChar->GetName());
+ }
+ else sLog.outBasic("Not announced xD");
+ }
+
+ if (announceallowed)
+ {
+ std::string pname = pCurrChar->GetName();
+ if ((sIRC.BOTMASK & 8)!= 0)
+ {
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(),sIRC.MakeMsg(sIRC.WoW_comeonline, "$Name", pname));
+ }
+ if ((sIRC.BOTMASK & 16)!= 0)
+ {
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_comeonline, "$Name", pname));
+ }
+ }
+
m_playerLoading = false;
pCurrChar->SendAllowMove();
Index: src/game/Chat.cpp
===================================================================
--- src/game/Chat.cpp (revision 3815)
+++ src/game/Chat.cpp (working copy)
@@ -175,6 +175,7 @@
{ "guid", 2, &ChatHandler::HandleGUIDCommand, "", NULL },
{ "help", 0, &ChatHandler::HandleHelpCommand, "", NULL },
{ "info", 0, &ChatHandler::HandleInfoCommand, "", NULL },
+ { "ircpm", 0, &ChatHandler::HandleIRCpmCommand, "", NULL },
{ "npcinfo", 3, &ChatHandler::HandleNpcInfoCommand, "", NULL },
{ "npcinfoset", 3, &ChatHandler::HandleNpcInfoSetCommand, "", NULL },
{ "addvendoritem",2,&ChatHandler::HandleAddVendorItemCommand, "", NULL },
Index: src/game/Chat.h
===================================================================
--- src/game/Chat.h (revision 3815)
+++ src/game/Chat.h (working copy)
@@ -136,6 +136,7 @@
bool HandleDismountCommand(const char* args);
bool HandleSaveCommand(const char* args);
bool HandleGMListCommand(const char* args);
+ bool HandleIRCpmCommand(const char* args);
bool HandleNamegoCommand(const char* args);
bool HandleGonameCommand(const char* args);
Index: src/game/ChatHandler.cpp
===================================================================
--- src/game/ChatHandler.cpp (revision 3815)
+++ src/game/ChatHandler.cpp (working copy)
@@ -31,6 +31,7 @@
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ScriptCalls.h"
+#include "IRCClient.h"
#include "Player.h"
#include "Language.h"
@@ -277,14 +278,24 @@
recv_data >> msg;
- if(ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
+ if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
+ break;
+
+ // if two side interraction is disabled and this is our channel, send to both channel manager instances, in LANG_UNIVERSAL.
+ if(sIRC.ChannelMsg(GetPlayer(), channel, msg) && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL))
{
- if(Channel *chn = cMgr->GetChannel(channel,_player))
- {
- chn->Say(_player->GetGUID(),msg.c_str(),lang);
- GetPlayer()->UpdateSpeakTime();
- }
+ sWorld.SendWorldMessage(channel.c_str(), msg, _player->GetGUID());
+ GetPlayer()->UpdateSpeakTime();
}
+ else // otherwise let mangos handle it normally.
+ {
+ if(ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
+ if(Channel *chn = cMgr->GetChannel(channel,_player))
+ {
+ chn->Say(_player->GetGUID(),msg.c_str(),lang);
+ GetPlayer()->UpdateSpeakTime();
+ }
+ }
} break;
case CHAT_MSG_AFK:
Index: src/game/IRCClient.cpp
===================================================================
--- src/game/IRCClient.cpp (revision 0)
+++ src/game/IRCClient.cpp (revision 0)
@@ -0,0 +1,1014 @@
+/*
+ * MangChat Enhanced v0.2
+ * Based on MANGCHAT a Threaded IRC Client for MaNGOS V0.1 by Cybrax
+ *
+ * MANGCHAT is a Internet Relay Chat client intergrated in mangos
+ * it allows you to have chat messages send from and to irc within
+ * the wow client. making it possible for players to get support
+ * from irc directly ingame or have several servers join the same
+ * irc channel and have "cross server chat". the client uses c
+ * sockets to send and receieve data from and to the irc server
+ *
+ * MangChat Enhanced aims to add many features to MangChat,
+ * including total "gm" control from irc, in channel and in game
+ * announces of level ups, deaths, resurrects, and so on.
+ * MangChat Enhanced features are designed to be fully integrated
+ * into the MaNGOS core system as well as be easly customised or
+ * disabled from the MaNGOS conf file.
+ *
+ * This software is currently still under development the client
+ * has been tested locally with 1 Windows XP server (Visual Studio)
+ * and 1 UNIX Debian 3.1 (g++) server.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * MANGCHAT is:
+ * Copyright (C) 2007 VisualDreams
+ * Written and Develloped by Cybrax. dev@visualdreams.nl
+ *
+ * MangChat was enhanced by Lice , Dj_baby & Sanaell
+ * with help and support from the MaNGOS project community.
+ *
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHOR.
+ *
+ */
+#include "IRCClient.h"
+#include "IRCCommands.h"
+#include "Common.h"
+#include "Database/DatabaseEnv.h"
+#include "Config/ConfigEnv.h"
+#include "Policies/SingletonImp.h"
+#include "ObjectAccessor.h"
+#include "WorldSession.h"
+#include "WorldPacket.h"
+#include "Log.h"
+#include "Chat.h"
+#include "ObjectMgr.h"
+#include "Guild.h"
+#include "MapManager.h"
+
+#include
+
+#pragma warning(disable:4305)
+INSTANTIATE_SINGLETON_1( IRCClient );
+
+/*------------------------------------------
+Threaded Function and declaration for the
+socket handler they are practicly simiair
+however the sockets and threading differs
+from win and unix. These functions are run
+on a seperate thread to "fake" asynchronus
+IO. the thread constantly listens on the
+socket for incomming data from IRC.
+------------------------------------------*/
+#ifdef _WIN32
+ #include
+
+ // Thread Declarations
+ // These comments apply to the unix part aswell
+ // they only slightly differ in names for some parts
+
+ DWORD nThreadID;
+ HANDLE hThread;
+ DWORD WINAPI SocketHandler(void* ptr);
+ // Thread Function
+ DWORD WINAPI SocketHandler(void* ptr)
+ {
+ char szBuffer[MAXDATASIZE];
+ // We want to constantly keep looking for data
+ // so we create a loop
+ while(sIRC.AcceptData == true)
+ {
+ // reset the buffer
+ ZeroMemory(szBuffer,MAXDATASIZE);
+
+ // check for incomming data on the socket
+ int nBytesRecv = recv(sIRC.sockfd, szBuffer, MAXDATASIZE - 1, 0 );
+ if ( nBytesRecv == -1 )
+ {
+ sLog.outError("Connection lost.");
+ // end the loop
+ sIRC.AcceptData = false;
+ }
+ else
+ {
+ if (-1 == nBytesRecv)
+ {
+ sLog.outError("Error occurred while receiving from socket.");
+ }
+ else
+ {
+ // Recieve was successfull send the data to RecvData function
+ sIRC.RecvData(szBuffer);
+ }
+ }
+ }
+ return 0;
+ }
+#else
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ pthread_t hThread;
+ int nThreadID;
+ void *SocketHandler( void *ptr );
+ void *SocketHandler( void *ptr )
+ {
+ char szBuffer[MAXDATASIZE];
+ while(sIRC.AcceptData == true)
+ {
+ memset ( szBuffer, 0, MAXDATASIZE + 1 );
+ int nBytesRecv = recv(sIRC.sockfd, szBuffer, MAXDATASIZE - 1, 0 );
+ if ( nBytesRecv == -1 )
+ {
+ sLog.outError("Connection lost.");
+ sIRC.AcceptData = false;
+ }
+ else
+ {
+ if (-1 == nBytesRecv)
+ {
+ // socket error
+ sLog.outError("Error occurred while receiving from socket.");
+ }
+ else
+ {
+ sIRC.RecvData(szBuffer);
+ }
+ }
+ }
+ return 0;
+ }
+#endif
+
+/*------------------------------------------
+IRCClient Constructor
+------------------------------------------*/
+IRCClient::IRCClient()
+{
+}
+
+/*------------------------------------------
+IRCClient Destructor
+------------------------------------------*/
+IRCClient::~IRCClient()
+{
+}
+
+/*------------------------------------------
+IRCClient::IRCcmd
+
+Checks in chan commands from irc
+------------------------------------------*/
+bool IRCClient::IRCcmd(std::string SndLine, std::string outputChan, std::string from, std::string type)
+{
+ std::size_t pos = SndLine.find(" ");
+ std::string cmd = SndLine.substr(0, pos);
+ std::transform(cmd.begin(), cmd.end(), cmd.begin(), towlower);
+ std::string param = "";
+ if (pos != std::string::npos)
+ param = SndLine.substr(pos + 1);
+ int level = 0;
+ std::string query = "SELECT * FROM `irc_logedin` WHERE `nick` = '" + from + "'";
+ QueryResult *result = sDatabase.Query(query.c_str());
+ if (result)
+ {
+ Field *fields = result->Fetch();
+ level = fields[2].GetInt32();
+ delete result;
+ }
+ if ((sIRC.IRC_CMDS_MASK & 1) != 0) // if level 0 commands are active
+ {
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "online")
+ {
+ IRCcommand::HandleOnlineIRCCommand(param, outputChan, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "inchan")
+ {
+ IRCcommand::HandleInChanIRCCommand(outputChan, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "player")
+ {
+ IRCcommand::HandlePlayerIRCCommand(param, outputChan, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "info")
+ {
+ IRCcommand::HandleInfoIRCCommand(outputChan, type);
+ return true;
+ }
+ }
+
+ if (((sIRC.IRC_CMDS_MASK & 2) != 0) && (cmd == sIRC.IRC_CMDS_PREFIX + "pm")) // if the pm system is active
+ {
+ IRCcommand::HandlePmIRCCommand(param, outputChan, level, from, type);
+ return true;
+ }
+
+ if ((sIRC.IRC_CMDS_MASK & 4) != 0) // if gm commands are active
+ {
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "kick")
+ {
+ IRCcommand::HandleKickIRCCommand(param, outputChan, level, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "saveall")
+ {
+ IRCcommand::HandleSaveAllIRCCommand(outputChan, level, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "tele")
+ {
+ IRCcommand::HandleTeleIRCCommand(param, outputChan, level, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "revive")
+ {
+ IRCcommand::HandleReviveIRCCommand(param, outputChan, level, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "kill")
+ {
+ IRCcommand::HandleKillIRCCommand(param, outputChan, level, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "announce")
+ {
+ IRCcommand::HandleAnnounceIRCCommand(param, outputChan, level, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "notify")
+ {
+ IRCcommand::HandleNotifyIRCCommand(param, outputChan, level, type);
+ return true;
+ }
+ }
+
+ if ((sIRC.IRC_CMDS_MASK & 6) != 0) // loging in and out will only be possible if the pm system or the gm commands are active.
+ {
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "login")
+ {
+ IRCcommand::HandleLoginIRCCommand(param, outputChan, from, type);
+ return true;
+ }
+
+ if (cmd == sIRC.IRC_CMDS_PREFIX + "logout")
+ {
+ IRCcommand::HandleLogoutIRCCommand(outputChan, from, type);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*------------------------------------------
+IRCClient::GetData
+
+Processes the lines from IRC
+IRC uses a verry simplt protocol where the
+data is split by spaces once we found the
+spaces we can split them up and use or
+analyze the variables
+------------------------------------------*/
+void IRCClient::GetData(std::string SndLine) {
+
+ if(SndLine.substr(0, 4) == "PING")
+ {
+ // we revceived a ping request
+ // we need to return pong + what the server sent us
+ std::string ret = "PONG " + SndLine.substr(4, SndLine.size() - 4);
+ sLog.outDebug("IRC: [PING] %s", ret.c_str());
+ SendData(ret.c_str());
+ }
+ else
+ {
+ // we receieved another type of message
+ sLog.outDebug("IRC: [IN] %s", SndLine.c_str());
+
+ // if the first character contains :
+ // we receievd a normal irc message
+ if(SndLine.substr(0,1)==":")
+ {
+ // find the spaces in the line
+ // and extract the values
+ int pos1 = SndLine.find(" ");
+ int pos2 = SndLine.find(" ", pos1 + 1);
+ std::string part1 = SndLine.substr(1, pos1 - 1);
+ std::string part2 = SndLine.substr(pos1 + 1, pos2 - pos1 - 1);
+ std::string rest = "", part3 = "";
+ // username contains nick and host adress extract it
+ std::string szUser = GetUser(part1);
+
+ // user ignore check
+ std::string ignorecheck = " " + szUser + " ";
+ std::transform(ignorecheck.begin(), ignorecheck.end(), ignorecheck.begin(), towlower);
+ if (sIRC.IGNORE_LIST.find(ignorecheck) != std::string::npos) return;
+
+ // make evrything lowercase to ensure compare matches
+ std::transform(part2.begin(), part2.end(), part2.begin(), towlower);
+
+ if(part2 == sIRC.IRC_CODE)
+ {
+ // we receieved the irc connectcode
+ sLog.outDebug("IRC: Connectcode received: %s", IRC_CODE.c_str());
+ /*
+ std::string modes = sConfig.GetStringDefault("IRCUSERMODES", "")
+ if (modes != "")
+ {
+ SendData("MODE " + sIRC.IRC_NICK + " :" + modes);
+ }
+ */
+ std::string ircpass = sConfig.GetStringDefault("IRCNICKPASS", "");
+ if(sConfig.GetIntDefault("IRCQUAKENET", 0) == 1)
+ {
+ // if we use quakenet authenticate now
+ if (ircpass != "")
+ SendData("PRIVMSG Q@CServe.quakenet.org :AUTH " + sIRC.IRC_NICK + " " + ircpass + "\n");
+ }
+ else
+ {
+ // if we use nickserv authenticate now
+ if (ircpass != "")
+ SendData("PRIVMSG nickserv :IDENTIFY " + ircpass + "\n");
+ }
+ // time to join the channel
+ SendData("JOIN #" + sIRC.IRC_CHAN + "\n");
+ }
+
+ if(part2 == "join")
+ {
+ int pos3 = SndLine.find(":", pos2);
+ part3 = SndLine.substr(pos3 + 1);
+ std::transform(part3.begin(), part3.end(), part3.begin(), towlower);
+ if ((szUser == sIRC.IRC_NICK) && (part3 == "#" + sIRC.IRC_CHAN))
+ {
+ if(sConfig.GetIntDefault("IRCSTARTMSGON", 0) == 1)
+ {
+ SendPMsg("#" + sIRC.IRC_CHAN, sConfig.GetStringDefault("IRCSTARTMSG", "Server Online"));
+ }
+ }
+ else if ((szUser == sIRC.IRC_NICK) && (sIRC.IRC_LDEF == 1) && (part3 == "#" + sIRC.IRC_DEF_CHAN))
+ {
+ // if we have to leave the default channel do this now
+ SendData("PART #" + sIRC.IRC_DEF_CHAN + "\n");
+ }
+ else if ((sIRC.BOTMASK & 1) != 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(), sIRC.MakeMsg(sIRC.WoW_joinedIRC, "$Name", szUser));
+ // someone joined the channel on irc
+ }
+
+ if ((part2 == "part") || (part2 == "quit"))
+ {
+ std::string query = "DELETE FROM `irc_logedin` WHERE `nick` = '" + szUser + "'";
+ sDatabase.PExecute(query.c_str());
+ if ((sIRC.BOTMASK & 1) != 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(), sIRC.MakeMsg(sIRC.WoW_leftIRC, "$Name", szUser));
+ }
+
+ if (part2 == "nick")
+ {
+ std::string query = "DELETE FROM `irc_logedin` WHERE `nick` = '" + szUser + "'";
+ sDatabase.PExecute(query.c_str());
+ int pos3 = SndLine.find(":", pos2);
+ part3 = SndLine.substr(pos3 + 1);
+ if ((sIRC.BOTMASK & 1) != 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(), sIRC.MakeMsg(sIRC.MakeMsg(sIRC.WoW_changedIRCnick, "$Name", szUser), "$NewName", part3));
+ }
+
+ if (part2 == "kick")
+ {
+ int pos3 = SndLine.find(" ", pos2 + 1);
+ int pos4 = SndLine.find(" ", pos3 + 1);
+ part3 = SndLine.substr(pos2 + 1, pos3 - pos2 - 1);
+ szUser = SndLine.substr(pos3 + 1, pos4 - pos3 -1);
+ std::transform(part3.begin(), part3.end(), part3.begin(), towlower);
+ std::string query = "DELETE FROM `irc_logedin` WHERE `nick` = '" + szUser + "'";
+ sDatabase.PExecute(query.c_str());
+ if(part3 == "#" + sIRC.IRC_CHAN)
+ {
+ if (((sIRC.BOTMASK & 1) != 0) && (szUser != sIRC.IRC_NICK)) //if someone is kicked from the chan
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(), sIRC.MakeMsg(sIRC.WoW_leftIRC, "$Name", szUser));
+ else if (sConfig.GetIntDefault("auto_rejoin_kick", 1) == 1) //If we are kicked and auto rejoin is 1 join channel back
+ {
+ SendData("JOIN #" + sIRC.IRC_CHAN + "\n");
+ }
+ }
+ }
+
+ if(part2 == "privmsg")
+ {
+ int pos3 = SndLine.find(" ", pos2 + 1);
+ part3 = SndLine.substr(pos2 + 1, pos3 - pos2 - 1);
+ rest = SndLine.substr(pos3 + 1, SndLine.size() - pos3 - 2);
+
+ std::transform(part3.begin(), part3.end(), part3.begin(), towlower);
+ std::string chat = rest.substr(1, rest.size());
+
+ // we receieved chat from the irc channel
+ if(part3 == "#" + sIRC.IRC_CHAN)
+ {
+ std::string WorldMsg = "[" + szUser + "]" + chat;
+ sLog.outDebug("IRC: [IN] %s", WorldMsg.c_str());
+
+ // check if its a command or not.
+ if (IRCcmd(chat, "#" + sIRC.IRC_CHAN, szUser)) return;
+
+ std::string str;
+ if (chat.substr(1, 7) == "ACTION ")
+ str = sIRC.MakeMsg(sIRC.MakeMsg(sIRC.WoW_IRCaction, "$Name", szUser), "$Msg", chat.substr(8, chat.length() - 9));
+ else
+ str = sIRC.MakeMsg(sIRC.MakeMsg(sIRC.WoW_IRCmsg, "$Name", szUser), "$Msg", chat);
+ // we use the custom made function here because we have to loop
+ // thry the player sessoins and check of they are on the channel
+ // i couldnt figure out how to make it work in this class
+ // so i had to use world
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str() , sIRC.IRCcol2WoW(str.c_str()));
+ //sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str() , sIRC.IRCcol2WoW(sIRC.Hybrid2UTF(str.c_str())));
+ }
+
+ // we received a PM
+ std::string ircnick = sIRC.IRC_NICK;
+ std::transform(ircnick.begin(), ircnick.end(), ircnick.begin(), towlower);
+ if(part3 == ircnick)
+ {
+ sLog.outDebug("IRC: Private message received: %s", szUser.c_str());
+ // check if its a command or not.
+ if (IRCcmd(chat, szUser, szUser, "NOTICE")) return;
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------------------
+IRCClient::ChannelBot
+
+Public function for announcing to the irc
+channel
+------------------------------------------*/
+void IRCClient::ChannelBot(std::string Msg)
+{
+ if(sIRC.Connected && sIRC.IRC_Login)
+ {
+ Msg = sIRC.Delink(Msg);
+ Msg = sIRC.WoWcol2IRC(Msg);
+ SendMsg(Msg);
+ }
+}
+
+void IRCClient::SendIRCData(std::string data)
+{
+ if(sIRC.Connected && sIRC.IRC_Login)
+ {
+ sLog.outDebug("IRC [OUT]: %s", data.c_str());
+ SendData(data.c_str());
+ }
+}
+
+void IRCClient::SendIRCpm(Player *From, std::string To, std::string Msg)
+{
+ if(sIRC.Connected && sIRC.IRC_Login)
+ {
+ char plevel [5];
+ sprintf(plevel, "%u", From->getLevel());
+ Msg = sIRC.Delink(Msg);
+ Msg = sIRC.WoWcol2IRC(Msg);
+ SendData("NOTICE " + To + " :13" + sIRC.MakeMsg(sIRC.MakeMsg(sIRC.MakeMsg(sIRC.IRC_WoWmsg, "$Name", From->GetName()), "$Msg", Msg), "$Lev", plevel) + "\n");
+ }
+}
+
+void IRCClient::HandleChannelJoin(Player *p)
+{
+ std::string pname = p->GetName();
+ std::string pteam = "12";
+ if (p->GetTeam() == 67)
+ pteam = "4";
+ sDatabase.PExecute("DELETE FROM `irc_inchan` WHERE `guid` = %d", p->GetGUID());
+ std::string query = "INSERT INTO `irc_inchan` VALUES(%d, '" + pname + "', " + pteam + ")";
+ sDatabase.PExecute(query.c_str(), p->GetGUID());
+ if ((sIRC.BOTMASK & 2)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_joinedWoWchan, "$Name", p->GetName()));
+ if ((sIRC.BOTMASK & 4)!= 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(), sIRC.MakeMsg(sIRC.WoW_joinedWoWchan, "$Name", p->GetName()), 0, p->GetSession());
+}
+
+void IRCClient::HandleChannelPart(Player *p)
+{
+ QueryResult *result = sDatabase.PQuery("SELECT * FROM `irc_inchan` WHERE `guid` = %d", p->GetGUID());
+ if (result)
+ {
+ delete result;
+ sDatabase.PExecute("DELETE FROM `irc_inchan` WHERE `guid` = %d", p->GetGUID());
+ if ((sIRC.BOTMASK & 2)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_leftWoWchan, "$Name", p->GetName()));
+ if ((sIRC.BOTMASK & 4)!= 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(), sIRC.MakeMsg(sIRC.WoW_leftWoWchan, "$Name", p->GetName()), 0, p->GetSession());
+ }
+}
+
+/*------------------------------------------
+IRCClient::ChannelMsg
+
+This function is called by the ChatHandler
+whenever a player talks on a channel the
+info is sent to this function. if the
+channel matches the one set in the config
+it will send the message to irc
+------------------------------------------*/
+bool IRCClient::ChannelMsg(Player *plr, std::string Channel, std::string Msg)
+{
+ std::transform(Channel.begin(), Channel.end(), Channel.begin(), towlower);
+ if(Channel == sIRC.WOW_CHAN)
+ {
+ if(sIRC.Connected && sIRC.IRC_Login)
+ {
+ char plevel [5];
+ sprintf(plevel, "%u", plr->getLevel());
+ Msg = sIRC.Delink(Msg);
+ Msg = sIRC.WoWcol2IRC(Msg);
+ SendMsg(sIRC.MakeMsg(sIRC.MakeMsg(sIRC.MakeMsg(sIRC.IRC_WoWmsg, "$Name", plr->GetName()), "$Msg", Msg), "$Lev", plevel));
+ }
+ return true;
+ }
+ return false;
+}
+
+/*------------------------------------------
+IRCClient::GetUser
+
+This extracts the username from the lines
+recieved from irc. because irc sends the
+username and hostinfo in one line.
+------------------------------------------*/
+std::string IRCClient::GetUser(std::string szU)
+{
+ // username and host are seperated by ! find the
+ // character and return the part before it
+ int pos = szU.find("!");
+ return szU.substr(0, pos);
+}
+
+std::string IRCClient::MakeMsg(std::string msg, std::string var, std::string val)
+{
+ std::size_t start = msg.find(var);
+ if (start != std::string::npos)
+ msg.replace(start, var.length(), val);
+ return msg;
+}
+
+std::string IRCClient::Delink(std::string msg)
+{
+ std::size_t pos;
+ while ((pos = msg.find("|Hitem")) != std::string::npos)
+ {
+ msg.replace(pos, msg.find("|h") - pos + 2, "\x2");
+ msg.replace(msg.find("|h"), 2, "\x2");
+ }
+ return msg;
+}
+
+std::string IRCClient::WoWcol2IRC(std::string msg)
+{
+ std::size_t pos;
+ char IRCCol[8][4] = { "\xF", "\xF", "\x3\x31\x34", "\x3\x30\x33", "\x3\x31\x32", "\x3\x30\x36", "\x3\x30\x37", "\x3\x30\x34"};
+ char WoWCol[8][12] = { "|r", "|cffffffff", "|cff9d9d9d", "|cff1eff00", "|cff0070dd", "|cffa335ee", "|cffff8000", "|cffe6cc80"};
+ for (int i=0; i<=7; i++)
+ {
+ while ((pos = msg.find(WoWCol[i])) != std::string::npos)
+ {
+ if (i == 0)
+ msg.replace(pos, 2, IRCCol[i]);
+ else
+ msg.replace(pos, 10, IRCCol[i]);
+ }
+ }
+ return msg;
+}
+
+std::string IRCClient::IRCcol2WoW(std::string msg)
+{
+ std::size_t pos;
+ char IRCCol[16][4] = { "\x3\x30", "\x3\x31", "\x3\x32", "\x3\x33", "\x3\x34", "\x3\x35", "\x3\x36", "\x3\x37", "\x3\x38", "\x3\x39", "\x3\x31\x30", "\x3\x31\x31", "\x3\x31\x32", "\x3\x31\x33", "\x3\x31\x34", "\x3\x31\x35"};
+ char IRCCol2[10][4] = { "\x3\x30\x30", "\x3\x30\x31", "\x3\x30\x32", "\x3\x30\x33", "\x3\x30\x34", "\x3\x30\x35", "\x3\x30\x36", "\x3\x30\x37", "\x3\x30\x38", "\x3\x30\x39"};
+ char WoWcol[16][12] = { "|cffffffff", "|cff000000", "|cff00007f", "|cff009300", "|cffff0000", "|cff7f0000", "|cff9c009c", "|cfffc9300", "|cffffff00", "|cff00fc00", "|cff009393", "|cff00ffff", "|cff0000fc", "|cffff00ff", "|cff7f7f7f", "|cffd2d2d2"};
+ for (int i=15; i>=0; i--)
+ {
+ if (i<10)
+ {
+ while ((pos = msg.find(IRCCol2[i])) != std::string::npos)
+ {
+ msg.replace(pos, 3, WoWcol[i]);
+ }
+ while ((pos = msg.find(IRCCol[i])) != std::string::npos)
+ {
+ msg.replace(pos, 2, WoWcol[i]);
+ }
+
+ }
+ else
+ {
+ while ((pos = msg.find(IRCCol[i])) != std::string::npos)
+ {
+ msg.replace(pos, 3, WoWcol[i]);
+ }
+ }
+ }
+
+ while ((pos = msg.find("\x3")) != std::string::npos)
+ {
+ msg.replace(pos, 1, "|r");
+ }
+ while ((pos = msg.find("\xF")) != std::string::npos)
+ {
+ msg.replace(pos, 1, "|r");
+ }
+
+ return msg;
+}
+
+std::string IRCClient::Hybrid2UTF(std::string Msg)
+{
+ /*char * tempchar = NULL;
+
+ tempchar = (char*)malloc(strlen(Msg.c_str())+1);
+
+ strcpy(tempchar,Msg.c_str());
+
+ BSTR in_text;
+ int nLen = MultiByteToWideChar(28591, 0, tempchar, lstrlen(tempchar), NULL, NULL);
+ in_text = SysAllocStringLen(NULL, nLen);
+ MultiByteToWideChar(28591, 0, tempchar, lstrlen(tempchar), in_text, nLen);
+
+ //change to UTF..
+ char *out_text = NULL;
+ int nLen2 = WideCharToMultiByte(65001, 0, in_text, -1, out_text, 0, NULL, NULL);
+ out_text = (char*)malloc(nLen2+1);
+ WideCharToMultiByte(65001, 0, in_text, -1, out_text, nLen2, NULL, NULL);
+
+ Msg = out_text;
+
+ free(tempchar);
+ SysFreeString(in_text);
+ free(out_text);*/
+
+ return Msg;
+}
+/*------------------------------------------
+IRCClient::LoadConfig
+
+Loads the configuration set in mangosd.conf
+------------------------------------------*/
+bool IRCClient::LoadConfig()
+{
+ int ConfCnt = 0;
+ sLog.outBasic("Loading IRC Configuration\n");
+
+ IRC_HOST = sConfig.GetStringDefault("IRCHost", "");
+ if(IRC_HOST.size() != 0) { ConfCnt++; }
+
+ IRC_Port = sConfig.GetIntDefault("IRCPort", 0);
+ if(IRC_Port != 0) { ConfCnt++; }
+
+ sIRC.IRC_CODE = sConfig.GetStringDefault("IRCCONNECTCODE", "001");
+ sIRC.IRC_LDEF = sConfig.GetIntDefault("IRCLeaveDefChannel", 0);
+ sIRC.IRC_NICK = sConfig.GetStringDefault("IRCNICK", "mangosirc");
+ sIRC.IRC_DEF_CHAN = sConfig.GetStringDefault("IRCDEFCHAN", "lobby");
+ sIRC.IRC_CHAN = sConfig.GetStringDefault("IRCCHAN", "world");
+ sIRC.WOW_CHAN = sConfig.GetStringDefault("WOWCHAN", "world");
+ sIRC.BOTMASK = sConfig.GetIntDefault("BotMask", 0);
+ sIRC.IRC_CMDS_MASK = sConfig.GetIntDefault("IRC_Cmds_Mask", 0);
+ sIRC.IRC_CMDS_PREFIX = sConfig.GetStringDefault("IRC_Cmds_Prefix", ".");
+ sIRC.IGNORE_LIST = " " + sConfig.GetStringDefault("IRCIgnorList", "") + " ";
+
+ // IRC Text Varriables:
+ sIRC.WoW_joinedIRC = sConfig.GetStringDefault("WoW_joinedIRC", ">> $Name joined IRC.");
+ sIRC.WoW_leftIRC = sConfig.GetStringDefault("WoW_leftIRC", "<< $Name left IRC.");
+ sIRC.WoW_changedIRCnick = sConfig.GetStringDefault("WoW_changedIRCnick", "<> $Name is now known as $NewName.");
+ sIRC.IRC_joinedWoWchan = sConfig.GetStringDefault("IRC_joinedWoWchan", "12>>04 $Name Joined The Channel");
+ sIRC.WoW_joinedWoWchan = sConfig.GetStringDefault("WoW_joinedWoWchan", ">> $Name Joined The Channel");
+ sIRC.IRC_leftWoWchan = sConfig.GetStringDefault("IRC_leftWoWchan", "12<<04 $Name Left The Channel");
+ sIRC.WoW_leftWoWchan = sConfig.GetStringDefault("WoW_leftWoWchan", "<< $Name Left The Channel");
+ sIRC.IRC_comeonline = sConfig.GetStringDefault("IRC_comeonline", "12>>04 $Name has come Online");
+ sIRC.WoW_comeonline = sConfig.GetStringDefault("WoW_comeonline", ">> $Name has come Online");
+ sIRC.IRC_goneoffline = sConfig.GetStringDefault("IRC_goneoffline", "12<<04 $Name has gone Offline");
+ sIRC.WoW_goneoffline = sConfig.GetStringDefault("WoW_goneoffline", "<< $Name has gone Offline");
+ sIRC.IRC_died = sConfig.GetStringDefault("IRC_died", "12<>04 $Name has joined the Spirits!");
+ sIRC.WoW_died = sConfig.GetStringDefault("WoW_died", "<> $Name has joined the Spirits!");
+ sIRC.IRC_revive = sConfig.GetStringDefault("IRC_revive", "12<>04 $Name has rejoined the Living!");
+ sIRC.WoW_revive = sConfig.GetStringDefault("WoW_revive", "<> $Name has rejoined the Living!");
+ sIRC.IRC_levelup = sConfig.GetStringDefault("IRC_levelup", "12<>04 $Name has gained Level $Lev!");
+ sIRC.WoW_levelup = sConfig.GetStringDefault("WoW_levelup", "<> $Name has gained Level $Lev!");
+ sIRC.IRC_WoWmsg = sConfig.GetStringDefault("IRC_WoWmsg", "[$Name] $Msg");
+ sIRC.WoW_IRCmsg = sConfig.GetStringDefault("WoW_IRCmsg", "[$Name]: $Msg");
+ sIRC.WoW_IRCaction = sConfig.GetStringDefault("WoW_IRCaction", "*$Name $Msg");
+ sIRC.IRC_sysmsg = sConfig.GetStringDefault("IRC_sysmsg", "04,08/!\\System Message/!\\ $Msg 04,08/!\\System Message/!\\");
+ sIRC.IRC_sysnotice = sConfig.GetStringDefault("IRC_sysnotice", "04,08/!\\System Notice/!\\ $Msg 04,08/!\\System Notice/!\\");
+
+ if(ConfCnt == 2)
+ {
+ // make sure we have at least a host and port
+ // or we cant connect
+ return true;
+ }
+ else
+ {
+ // config missing
+ sLog.outError("ERROR MISSING CONFIGURATION FOR HOST AND OR PORT AND OR GMPASS\n");
+ return false;
+ }
+}
+
+/*------------------------------------------
+IRCClient::run
+
+function called by ZThread
+when we create the thread
+------------------------------------------*/
+void IRCClient::run()
+{
+ sLog.outBasic("\n%s\n%s\n%s\n%s\n%s\n%s\n",
+ "***************************************",
+ "# MANGCHAT Threaded IRC CLient #",
+ "# (C) 2007 VisuaDreams #",
+ "# Written by Cybrax #",
+ "# Enhanced by Lice, Dj_baby & Sanaell #",
+ "***************************************");
+
+ // Thread started load config
+ if(!LoadConfig())
+ {
+ return;
+ }
+ // clear irc tables
+ sDatabase.PExecute("DELETE FROM `irc_inchan`");
+ sDatabase.PExecute("DELETE FROM `irc_logedin`");
+
+ sIRC.IRC_Login = false;
+ sIRC.Connected = false;
+
+ if(sConfig.GetIntDefault("IRCON", 0))
+ {
+ if(Connect(IRC_HOST.c_str(), IRC_Port))
+ {
+ // If connections success
+ sLog.outBasic("IRC: Connected");
+ // send hello to let the server know were here
+ if(SendData("HELLO\n"))
+ {
+ // begin with password first
+ std::string ircpass = sConfig.GetStringDefault("IRCSERVERPASS", "mangosirc");
+ if(SendData("PASS " + ircpass + "\n"))
+ {
+ // send nickname
+ if(SendData("NICK " + sIRC.IRC_NICK + "\n"))
+ {
+ // send username and some required info
+ char hostname[128];
+ gethostname(hostname, sizeof(hostname));
+ if(SendData("USER " + sConfig.GetStringDefault("IRCUSER", "mangosirc") + " " + (std::string)hostname + " " + " MaNGOS :MaNGOS IRC 0.2\n"))
+ {
+ // login was a success
+ sLog.outBasic("IRC: Login succeeded\n");
+ sIRC.IRC_Login = true;
+ }// send username
+ }// send nickname
+ } // password
+ } // send hello
+
+ if(sIRC.IRC_Login == true)
+ {
+ sIRC.AcceptData = true;
+ // if we are logged in we need to start the listener thread and keep them alive
+ char *tmsg = ""; // bogus message to be passed to prevent errors
+ #ifdef _WIN32
+ // create the thread
+ hThread = CreateThread(0, 0, SocketHandler, (void*)tmsg, 0, &nThreadID);
+ //wait for it to finish
+ WaitForSingleObject(hThread, INFINITE);
+ #else
+ // create the thread
+ nThreadID = pthread_create( &hThread, NULL, &SocketHandler, (void*)tmsg);
+ //wait for it to finish
+ pthread_join( hThread, NULL);
+ #endif
+ }
+ // The thread ended connection lost
+ sLog.outError("Connection died\n");
+ Disconnect();
+ }
+ else
+ {
+ // unable to login
+ sLog.outError("Unable to connect to %s\n", IRC_HOST.c_str());
+ }
+ }
+ // close and cloeanup the socket
+ return;
+}
+
+/*------------------------------------------
+IRCClient::Connect
+
+Initiate the connection to the irc server
+returns true on success
+returns false on error
+------------------------------------------*/
+bool IRCClient::Connect(const char *host, int port)
+{
+ sLog.outBasic("***** Attempting IRC Connection *\n");
+
+ #ifdef _WIN32
+ // if we use WIN32 we must initialize the winsock library
+ WSADATA wsaData; //WSAData
+ if(WSAStartup(MAKEWORD(2,0),&wsaData) != 0)
+ {
+ sLog.outError("IRC Error: Winsock Initialization Error");
+ return false;
+ }
+ #endif
+
+ struct hostent *he;
+ struct sockaddr_in their_addr;
+
+ // get the hostname
+ if ((he=gethostbyname(host)) == NULL)
+ {
+ sLog.outError("IRC Error: Host Resolve Error");
+ return false;
+ }
+
+ // Create the socket
+ if ((sIRC.sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ {
+ sLog.outError("IRC Error: Socket Error");
+ return false;
+ }
+
+ int on = 1;
+ if ( setsockopt ( sIRC.sockfd, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
+ {
+ sLog.outError("IRC Error: Invalid Socket");
+ return false;
+ }
+
+ // set the socket to asynchronous IO and NON Blocking
+ #ifdef _WIN32
+ u_long iMode = 0;
+ ioctlsocket(sIRC.sockfd, FIONBIO, &iMode);
+ #else
+ fcntl(sIRC.sockfd, F_SETFL, O_NONBLOCK); // set to non-blocking
+ fcntl(sIRC.sockfd, F_SETFL, O_ASYNC); // set to asynchronous I/O
+ #endif
+
+ // construct data to be passed to the socket connect function
+ // this is port and host
+
+ their_addr.sin_family = AF_INET; // host byte order
+ their_addr.sin_port = htons(port); // short, network byte order
+ their_addr.sin_addr = *((struct in_addr *)he->h_addr);
+ memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct
+
+ // attempt a connection to the server
+ if (connect(sIRC.sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
+ {
+ sLog.outError("IRC Error: Cannot connect to %s", host);
+ return false;
+ }
+ // Connection success
+ sIRC.Connected = true;
+ return true;
+}
+
+/*------------------------------------------
+IRCClient::RecvData
+
+this function takes the data from the
+socket and puts it in a stringstream
+we do this because the data can contain
+more then 1 line and we need to process
+each line seperately
+------------------------------------------*/
+void IRCClient::RecvData(std::string SockData)
+{
+ // the data receieved in the socket can have more then 1 line
+ // put the data into a stringstream and send each line
+ // to the GetData function
+ std::string reply;
+ std::istringstream iss(SockData);
+ while(getline(iss, reply))
+ {
+ GetData(reply);
+ }
+}
+
+/*------------------------------------------
+IRCClient::SendMsg
+
+This function constructs a message a
+channel on the IRC server
+------------------------------------------*/
+bool IRCClient::SendMsg(std::string SndLine) {
+ sLog.outDebug("IRC [OUT]: %s", SndLine.c_str());
+ return SendData("PRIVMSG #" + sIRC.IRC_CHAN + " :" + SndLine + "\n");
+}
+
+/*------------------------------------------
+IRCClient::SendPMsg
+
+This function constructs a message for
+a user on the IRC server
+------------------------------------------*/
+bool IRCClient::SendPMsg(std::string user, std::string SndLine) {
+ sLog.outDebug("IRC [OUT]: %s", SndLine.c_str());
+ return SendData("PRIVMSG " + user + " :" + SndLine + "\n");
+}
+
+/*------------------------------------------
+IRCClient::SendData
+
+This function sends the data passed to the
+socket its similair to the previous function
+however excepts a string as argument
+
+Note that we use the same function name
+twice however the argument is different this
+is called Function Overloading C++ will
+automaticly detect the argument type passed
+and select the right function
+------------------------------------------*/
+bool IRCClient::SendData(const char *data) {
+ // send data on the socket
+ if (send(sIRC.sockfd, data, strlen(data), 0) == -1)
+ {
+ sLog.outError("IRC Error: Socket Receieve ** \n");
+ Disconnect();
+ return false;
+ }
+ return true;
+}
+
+bool IRCClient::SendData(std::string data)
+{
+ // send data on the socket
+ // function overloaded
+ return SendData(data.c_str());
+}
+
+/*------------------------------------------
+IRCClient::Disconnect
+
+Function to close and cleanup the socket
+------------------------------------------*/
+void IRCClient::Disconnect()
+{
+ close(sIRC.sockfd);
+ #ifdef _WIN32
+ WSACleanup();
+ #endif
+}
+
+/*------------------------------------------
+IRCSocket Constructor
+------------------------------------------*/
+IRCSocket::IRCSocket()
+{
+}
+
+/*------------------------------------------
+IRCSocket Destructor
+------------------------------------------*/
+IRCSocket::~IRCSocket()
+{
+}
Index: src/game/IRCClient.h
===================================================================
--- src/game/IRCClient.h (revision 0)
+++ src/game/IRCClient.h (revision 0)
@@ -0,0 +1,155 @@
+/*
+ * MangChat Enhanced v0.2
+ * Based on MANGCHAT a Threaded IRC Client for MaNGOS V0.1 by Cybrax
+ *
+ * MANGCHAT is a Internet Relay Chat client intergrated in mangos
+ * it allows you to have chat messages send from and to irc within
+ * the wow client. making it possible for players to get support
+ * from irc directly ingame or have several servers join the same
+ * irc channel and have "cross server chat". the client uses c
+ * sockets to send and receieve data from and to the irc server
+ *
+ * MangChat Enhanced aims to add many features to MangChat,
+ * including total "gm" control from irc, in channel and in game
+ * announces of level ups, deaths, resurrects, and so on.
+ * MangChat Enhanced features are designed to be fully integrated
+ * into the MaNGOS core system as well as be easly customised or
+ * disabled from the MaNGOS conf file.
+ *
+ * This software is currently still under development the client
+ * has been tested locally with 1 Windows XP server (Visual Studio)
+ * and 1 UNIX Debian 3.1 (g++) server.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * MANGCHAT is:
+ * Copyright (C) 2007 VisualDreams
+ * Written and Develloped by Cybrax. dev@visualdreams.nl
+ *
+ * MangChat was enhanced by Lice , Dj_baby & Sanaell
+ * with help and support from the MaNGOS project community.
+ *
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHOR.
+ *
+ */
+
+#ifndef _IRC_CLIENT_H
+#define _IRC_CLIENT_H
+
+#include "Policies/Singleton.h"
+#include "Player.h"
+
+#define MAXDATASIZE 512
+#define IRC_CHANNEL_JOIN 0
+#define IRC_CHANNEL_LEAVE 1
+
+class IRCClient : public ZThread::Runnable
+{
+public:
+ IRCClient();
+ ~IRCClient();
+ void run();
+ void RecvData(std::string SockData);
+ void SendIRCpm(Player *From, std::string To, std::string Msg);
+ void ChannelBot(std::string Msg);
+ void SendIRCData(std::string data);
+ void HandleChannelJoin(Player *p);
+ void HandleChannelPart(Player *p);
+
+public:
+ bool Connected;
+ bool IRC_Login;
+ bool AcceptData;
+ bool ChannelMsg(Player *plr, std::string Channel, std::string Msg);
+
+public:
+ int sockfd;
+ int IRC_LDEF;
+ int BOTMASK;
+ int IRC_CMDS_MASK;
+
+public:
+ std::string MakeMsg(std::string msg, std::string var, std::string val);
+ std::string Delink(std::string msg);
+ std::string WoWcol2IRC(std::string msg);
+ std::string IRCcol2WoW(std::string msg);
+ std::string Hybrid2UTF(std::string Msg);
+
+ std::string IRC_NICK;
+ std::string IRC_CMDS_PREFIX;
+ std::string IGNORE_LIST;
+ std::string IRC_CODE;
+ std::string IRC_DEF_CHAN;
+ std::string IRC_CHAN;
+ std::string WOW_CHAN;
+
+ // IRC Text Variables
+ std::string WoW_joinedIRC;
+ std::string WoW_leftIRC;
+ std::string WoW_changedIRCnick;
+ std::string IRC_joinedWoWchan;
+ std::string WoW_joinedWoWchan;
+ std::string IRC_leftWoWchan;
+ std::string WoW_leftWoWchan;
+ std::string IRC_comeonline;
+ std::string WoW_comeonline;
+ std::string IRC_goneoffline;
+ std::string WoW_goneoffline;
+ std::string IRC_died;
+ std::string WoW_died;
+ std::string IRC_revive;
+ std::string WoW_revive;
+ std::string IRC_levelup;
+ std::string WoW_levelup;
+ std::string IRC_WoWmsg;
+ std::string WoW_IRCmsg;
+ std::string WoW_IRCaction;
+ std::string IRC_sysmsg;
+ std::string IRC_sysnotice;
+
+private:
+ void Disconnect();
+ void GetData(std::string SndLine);
+
+private:
+ bool LoadConfig();
+ bool Connect(const char *host, int port);
+ bool SendMsg(std::string SndLine);
+ bool SendPMsg(std::string user, std::string SndLine);
+ bool SendData(const char *data);
+ bool SendData(std::string data);
+ bool IRCcmd(std::string SndLine, std::string outputChan, std::string from, std::string type="PRIVMSG");
+
+private:
+ std::string GetUser(std::string szU);
+
+private:
+ int IRC_Port;
+
+private:
+ std::string IRC_HOST;
+};
+
+#define sIRC MaNGOS::Singleton::Instance()
+
+
+class IRCSocket
+{
+public:
+ IRCSocket();
+ ~IRCSocket();
+};
+
+#endif
Index: src/game/IRCCommands.cpp
===================================================================
--- src/game/IRCCommands.cpp (revision 0)
+++ src/game/IRCCommands.cpp (revision 0)
@@ -0,0 +1,483 @@
+/*
+ * MangChat Enhanced v0.2
+ * Based on MANGCHAT a Threaded IRC Client for MaNGOS V0.1 by Cybrax
+ *
+ * MANGCHAT is a Internet Relay Chat client intergrated in mangos
+ * it allows you to have chat messages send from and to irc within
+ * the wow client. making it possible for players to get support
+ * from irc directly ingame or have several servers join the same
+ * irc channel and have "cross server chat". the client uses c
+ * sockets to send and receieve data from and to the irc server
+ *
+ * MangChat Enhanced aims to add many features to MangChat,
+ * including total "gm" control from irc, in channel and in game
+ * announces of level ups, deaths, resurrects, and so on.
+ * MangChat Enhanced features are designed to be fully integrated
+ * into the MaNGOS core system as well as be easly customised or
+ * disabled from the MaNGOS conf file.
+ *
+ * This software is currently still under development the client
+ * has been tested locally with 1 Windows XP server (Visual Studio)
+ * and 1 UNIX Debian 3.1 (g++) server.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * MANGCHAT is:
+ * Copyright (C) 2007 VisualDreams
+ * Written and Develloped by Cybrax. dev@visualdreams.nl
+ *
+ * MangChat was enhanced by Lice , Dj_baby & Sanaell
+ * with help and support from the MaNGOS project community.
+ *
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHOR.
+ *
+ */
+
+#include "IRCCommands.h"
+#include "IRCClient.h"
+#include "Common.h"
+#include "Language.h"
+#include "Database/DatabaseEnv.h"
+#include "Config/ConfigEnv.h"
+#include "Policies/SingletonImp.h"
+#include "ObjectAccessor.h"
+#include "WorldSession.h"
+#include "WorldPacket.h"
+#include "Log.h"
+#include "Chat.h"
+#include "ObjectMgr.h"
+#include "Guild.h"
+#include "MapManager.h"
+
+void IRCcommand::HandlePlayerIRCCommand(std::string param, std::string outputChan,std::string type)
+{
+ int pos = param.find(" ");
+ if (param == "")
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :" + "Syntax: " + sIRC.IRC_CMDS_PREFIX + "player playername" + "\n");
+ return;
+ }
+ std::string pname = param.substr(0, pos);
+ normalizePlayerName(pname);
+ sDatabase.escape_string(pname);
+ std::string sqlquery = "SELECT `guid`, `name`, `race`, `class`, `online`, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 35), ' ' , -1) AS `level`, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 230), ' ' , -1) AS `guildid`, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 231), ' ' , -1) AS `guildrank`, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 859), ' ' , -1) AS `xp`, SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ' , 860), ' ' , -1) AS `maxxp`, SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ' , 1327), ' ' , -1) AS `gold` FROM `character` WHERE `name` LIKE '" + pname + "';";
+ QueryResult *result = sDatabase.Query(sqlquery.c_str());
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ std::string pguid = fields[0].GetCppString();
+ pname = fields[1].GetCppString();
+ uint32 praceid = fields[2].GetUInt32();
+ uint32 pclassid = fields[3].GetUInt32();
+ std::string ponline = (fields[4].GetInt32() == 1 ? "\x3\x30\x33Online" : "\x3\x30\x34Offline\xF");
+ std::string plevel = fields[5].GetCppString();
+ uint32 pguildid = fields[6].GetUInt32();
+ uint32 pguildrank = fields[7].GetUInt32();
+ std::string pxp = fields[8].GetCppString();
+ std::string pmaxxp = fields[9].GetCppString();
+ unsigned int money = fields[10].GetInt32();
+ delete result;
+
+ std::string guildinfo = "";
+ if (pguildid != 0)
+ {
+ Guild* guild = objmgr.GetGuildById(pguildid);
+ if (guild)
+ {
+ guildinfo = ", " + guild->GetRankName(pguildrank) + " of " + guild->GetName();
+ }
+ }
+
+ ChrRacesEntry const* prace = sChrRacesStore.LookupEntry(praceid);
+ ChrClassesEntry const* pclass = sChrClassesStore.LookupEntry(pclassid);
+
+ if (atoi(plevel.c_str()) < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ plevel += " (" + pxp + "/" + pmaxxp + ")";
+
+ unsigned int gold = money / 10000;
+ unsigned int silv = (money % 10000) / 100;
+ unsigned int cop = (money % 10000) % 100;
+ char tempgold [100];
+ sprintf(tempgold, "\x2\x3\x30\x37%ug \x3\x31\x34%us \x3\x30\x35%uc\xF", gold, silv, cop);
+
+ if (ponline == "\x3\x30\x33Online")
+ {
+ Player * player = ObjectAccessor::Instance().FindPlayerByName(pname.c_str());
+ if (player)
+ {
+ AreaTableEntry const* area = GetAreaEntryByAreaID(player->GetAreaId());
+ ponline += " in " + (std::string) area->area_name[sWorld.GetDBClang()];
+ if (area->zone != 0)
+ {
+ AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
+ ponline += " (" + (std::string)zone->area_name[sWorld.GetDBClang()] + ")";
+ }
+ }
+ }
+
+ sIRC.SendIRCData(type + " " + outputChan + " :" + "About " + pname + guildinfo + "\n");
+ sIRC.SendIRCData(type + " " + outputChan + " :" + "\x2Race:\x2\x3\x31\x30 " + (std::string)prace->name[sWorld.GetDBClang()] + "\xF |\x2 Class:\x2\x3\x31\x30 " + (std::string)pclass->name[sWorld.GetDBClang()] + "\xF |\x2 Level:\x2\x3\x31\x30 " + plevel + "\xF |\x2 Money:\x2 " + tempgold + "\xF |\x2 Status:\x2 " + ponline + "\n");
+
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + "Unknown Player: " + pname + "\n");
+
+}
+
+void IRCcommand::HandleOnlineIRCCommand(std::string param, std::string outputChan,std::string type)
+{
+ std::transform(param.begin(), param.end(), param.begin(), towlower);
+ bool showHorde = false;
+ bool showAlli = false;
+ if (param.length() > 0)
+ {
+ if (param.substr(0, 3) == "all")
+ {
+ showHorde = true;
+ showAlli = true;
+ }
+ else if (param.at(0) == 'h')
+ showHorde = true;
+ else if (param.at(0) == 'a')
+ showAlli = true;
+ }
+ uint32 playersonline = 0;
+ std::string output = ":";
+ char buffer[80];
+ ObjectAccessor::PlayersMapType& m = ObjectAccessor::Instance().GetPlayers();
+ for(ObjectAccessor::PlayersMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ {
+ if (((itr->second->GetTeam() == 67) && showHorde) || ((itr->second->GetTeam() == 469) && showAlli))
+ {
+ std::string pname = itr->second->GetName();
+ if (itr->second->GetSession()->GetSecurity() > 0)
+ {
+ sprintf(buffer, "%c%s%c", 31, pname.c_str(), 31);
+ pname = buffer;
+ }
+ if (itr->second->GetSession()->GetPlayer()->isGameMaster())
+ {
+ sprintf(buffer, "%c03%s%c", 3, pname.c_str(), 3);
+ pname = buffer;
+ }
+ switch (itr->second->GetTeam())
+ {
+ case 67: //horde
+ sprintf (buffer, "%c04%s%c", 3, pname.c_str(), 3);
+ pname = buffer;
+ break;
+
+ case 469: //alliance
+ sprintf (buffer, "%c12%s%c", 3, pname.c_str(), 3);
+ pname = buffer;
+ break;
+ default:
+ break;
+ }
+
+ sprintf (buffer, " %s(%d)", pname.c_str(), itr->second->getLevel());
+
+ output += buffer;
+ playersonline++;
+ }
+ if (!showHorde && !showAlli)
+ playersonline++;
+ }
+ sprintf (buffer, "%c%d Player(s) Online", 2, playersonline);
+ output = (output == ":" ? buffer : buffer + output);
+ sIRC.SendIRCData(type + " " + outputChan + " :" + output + "\n");
+}
+
+void IRCcommand::HandleInChanIRCCommand(std::string outputChan,std::string type)
+{
+ QueryResult *result = sDatabase.Query("SELECT * FROM irc_inchan ORDER BY `name`");
+ if (!result)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :No Players are in the Channel\n");
+ return;
+ }
+ std::string output = "\x02Players in the Channel:";
+ for (uint64 i=0; i < result->GetRowCount(); i++)
+ {
+ Field *fields = result->Fetch();
+ output += " \x03" + fields[2].GetCppString() + fields[1].GetCppString() + "\x03";
+ result->NextRow();
+ }
+ delete result;
+ sIRC.SendIRCData(type + " " + outputChan + " :" + output + "\n");
+}
+
+void IRCcommand::HandleInfoIRCCommand(std::string outputChan,std::string type)
+{
+ char clientsNum [50];
+ sprintf(clientsNum, "%u", sWorld.GetSessionCount());
+ char maxClientsNum [50];
+ sprintf(maxClientsNum, "%u", sWorld.GetMaxSessionCount());
+ std::string str = secsToTimeString(sWorld.GetUptime());
+
+ sIRC.SendIRCData(type + " " + outputChan + " :Number of Players Online: " + (std::string)clientsNum + " (Max since last restart: " + (std::string)maxClientsNum + ")" + " Uptime: " + str + "\n");
+}
+
+void IRCcommand::HandleKickIRCCommand(std::string param, std::string outputChan, int level, std::string type)
+{
+ if (level < 2)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ int pos = param.find(" ");
+ param = param.substr(0, pos);
+ normalizePlayerName(param);
+ Player* chr = ObjectAccessor::Instance().FindPlayerByName( param.c_str() );
+ if (chr)
+ {
+ chr->GetSession()->KickPlayer();
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " was kicked.\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " was not online.\n");
+}
+
+void IRCcommand::HandleSaveAllIRCCommand(std::string outputChan, int level, std::string type)
+{
+ if (level < 1)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ ObjectAccessor::Instance().SaveAllPlayers();
+ sIRC.SendIRCData(type + " " + outputChan + " :All Players Saved\n");
+}
+
+void IRCcommand::HandleTeleIRCCommand(std::string param, std::string outputChan, int level, std::string type)
+{
+ if (level < 1)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ int pos = param.find(" ");
+ std::string player = param.substr(0, pos);
+ normalizePlayerName(player);
+ Player* chr = ObjectAccessor::Instance().FindPlayerByName( player.c_str() );
+ if (chr)
+ {
+ if(chr->isInFlight())
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :4[ERROR]: " + player + " is flying and cannot be transported\n");
+ }
+ else
+ {
+ std::string location = param.substr(pos + 1, param.size() - pos - 1);
+ if(location != "")
+ {
+ sDatabase.escape_string(location);
+ std::string sqlquery = "SELECT `position_x`,`position_y`,`position_z`,`orientation`,`map` FROM `game_tele` WHERE `name` = '" + location + "';";
+ QueryResult *result = sDatabase.Query(sqlquery.c_str());
+ if (!result)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :4[ERROR]: Tele location not found: " + location + "\n");
+ }
+ else
+ {
+ 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))
+ sIRC.SendIRCData(type + " " + outputChan + " :4[ERROR]: Invalid tele location: " + location + "\n");
+ else
+ {
+ chr->SetRecallPosition(chr->GetMapId(),chr->GetPositionX(),chr->GetPositionY(),chr->GetPositionZ(),chr->GetOrientation());
+ chr->TeleportTo(mapid, x, y, z, ort);
+ sIRC.SendIRCData(type + " " + outputChan + " :13[" + player + "]: teleported to " + location + "\n");
+ }
+ }
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :4[ERROR]: Please Suply tele location\n");
+ }
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :4[ERROR]: " + player + " is not online\n");
+}
+
+void IRCcommand::HandleReviveIRCCommand(std::string param, std::string outputChan, int level, std::string type)
+{
+ if (level < 3)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ int pos = param.find(" ");
+ param = param.substr(0, pos);
+ normalizePlayerName(param);
+ Player* chr = ObjectAccessor::Instance().FindPlayerByName( param.c_str() );
+ if (chr)
+ {
+ if(chr->isDead())
+ {
+ chr->ResurrectPlayer(0.5f);
+ chr->SpawnCorpseBones();
+ chr->SaveToDB();
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " resurrected\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " is not Dead\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " Is not online\n");
+}
+
+void IRCcommand::HandleKillIRCCommand(std::string param, std::string outputChan, int level, std::string type)
+{
+ if (level < 3)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ int pos = param.find(" ");
+ param = param.substr(0, pos);
+ normalizePlayerName(param);
+ Player* chr = ObjectAccessor::Instance().FindPlayerByName( param.c_str() );
+ if (chr)
+ {
+ if(chr->isAlive())
+ {
+ chr->DealDamage(chr, chr->GetHealth(), DIRECT_DAMAGE, 0, NULL, 0, false);
+ chr->SaveToDB();
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " killed\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " is already Dead\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + param + " Is not online\n");
+}
+
+void IRCcommand::HandleAnnounceIRCCommand(std::string param, std::string outputChan, int level, std::string type)
+{
+ if (level < 1)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ std::string str = LANG_SYSTEMMESSAGE + sIRC.IRCcol2WoW(param);
+ sWorld.SendWorldText(str.c_str(), NULL);
+
+ if ((sIRC.BOTMASK & 1024)!= 0)
+ {
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_sysmsg, "$Msg", param));
+ }
+}
+
+void IRCcommand::HandleNotifyIRCCommand(std::string param, std::string outputChan, int level, std::string type)
+{
+ if (level < 1)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You Dont Have Access To That Command\n");
+ return;
+ }
+ std::string str = LANG_GLOBAL_NOTIFY + sIRC.IRCcol2WoW(param);
+
+ WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
+ data << str;
+ sWorld.SendGlobalMessage(&data);
+
+ if ((sIRC.BOTMASK & 1024)!= 0)
+ {
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_sysnotice, "$Msg", str.substr(15)));
+ }
+}
+
+void IRCcommand::HandlePmIRCCommand(std::string param, std::string outputChan, int level, std::string from, std::string type)
+{
+ int pos = param.find(" ");
+ std::string player = param.substr(0, pos);
+ normalizePlayerName(player);
+ Player* chr = ObjectAccessor::Instance().FindPlayerByName( player.c_str() );
+ if (chr)
+ {
+ if(chr->isAcceptWhispers() || chr->GetSession()->GetSecurity() <= level)
+ {
+ std::string msg = param.substr(pos + 1, param.size() - pos - 1);
+
+ std::string chat = "|cffCC4ACC" + sIRC.IRCcol2WoW(sIRC.MakeMsg(sIRC.MakeMsg(sIRC.WoW_IRCmsg, "$Name", from), "$Msg", msg)) + "|r";
+ // construct a packet
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+ data << (uint8)CHAT_MSG_SYSTEM;
+ data << (uint32)LANG_UNIVERSAL;
+ data << chr->GetSession()->GetPlayer()->GetGUID();
+ data << (uint32) strlen(chat.c_str()) + 1;
+ data << chat.c_str();
+ data << (uint8)0;
+
+ // send the packet to the player
+ chr->GetSession()->SendPacket(&data);
+ sIRC.SendIRCData(type + " " + outputChan + " :13To [" + player + "]: " + msg + "\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + player + " is not accepting private messages\n");
+ }
+ else
+ sIRC.SendIRCData(type + " " + outputChan + " :" + player + " is not online\n");
+}
+
+void IRCcommand::HandleLoginIRCCommand(std::string param, std::string outputChan, std::string from, std::string type)
+{
+ std::string query = "DELETE FROM `irc_logedin` WHERE `nick` = '" + from + "'";
+ sDatabase.PExecute(query.c_str());
+ std::size_t pos = param.find(" ");
+ std::string user = param.substr(0, pos);
+ if (pos == std::string::npos)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You must specify a username and password\n");
+ return;
+ }
+ std::string pass = param.substr(pos + 1);
+ loginDatabase.escape_string(user);
+ loginDatabase.escape_string(pass);
+ query = "SELECT id, gmlevel FROM `account` WHERE `username` LIKE '" + user + "' AND `password` = '" + pass + "'";
+ QueryResult *result = loginDatabase.Query(query.c_str());
+ if (!result)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :Wrong User or Pass\n");
+ return;
+ }
+ Field *fields = result->Fetch();
+ query = "DELETE FROM `irc_logedin` WHERE `account` = " + fields[0].GetCppString();
+ sDatabase.PExecute(query.c_str());
+ query = "INSERT INTO `irc_logedin` VALUES(" + fields[0].GetCppString() + ", '" + from + "', " + fields[1].GetCppString() + ")";
+ sDatabase.PExecute(query.c_str());
+ delete result;
+ sIRC.SendIRCData(type + " " + outputChan + " :You are now loged in as " + user + "\n");
+}
+void IRCcommand::HandleLogoutIRCCommand(std::string outputChan, std::string from, std::string type)
+{
+ std::string query = "SELECT * FROM `irc_logedin` WHERE `nick` = '" + from + "'";
+ QueryResult *result = sDatabase.Query(query.c_str());
+ if (!result)
+ {
+ sIRC.SendIRCData(type + " " + outputChan + " :You are not loged in.\n");
+ return;
+ }
+ delete result;
+ query = "DELETE FROM `irc_logedin` WHERE `nick` = '" + from + "'";
+ sDatabase.PExecute(query.c_str());
+ sIRC.SendIRCData(type + " " + outputChan + " :You are now loged out.\n");
+}
\ No newline at end of file
Index: src/game/IRCCommands.h
===================================================================
--- src/game/IRCCommands.h (revision 0)
+++ src/game/IRCCommands.h (revision 0)
@@ -0,0 +1,69 @@
+/*
+ * MangChat Enhanced v0.2
+ * Based on MANGCHAT a Threaded IRC Client for MaNGOS V0.1 by Cybrax
+ *
+ * MANGCHAT is a Internet Relay Chat client intergrated in mangos
+ * it allows you to have chat messages send from and to irc within
+ * the wow client. making it possible for players to get support
+ * from irc directly ingame or have several servers join the same
+ * irc channel and have "cross server chat". the client uses c
+ * sockets to send and receieve data from and to the irc server
+ *
+ * MangChat Enhanced aims to add many features to MangChat,
+ * including total "gm" control from irc, in channel and in game
+ * announces of level ups, deaths, resurrects, and so on.
+ * MangChat Enhanced features are designed to be fully integrated
+ * into the MaNGOS core system as well as be easly customised or
+ * disabled from the MaNGOS conf file.
+ *
+ * This software is currently still under development the client
+ * has been tested locally with 1 Windows XP server (Visual Studio)
+ * and 1 UNIX Debian 3.1 (g++) server.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * MANGCHAT is:
+ * Copyright (C) 2007 VisualDreams
+ * Written and Develloped by Cybrax. dev@visualdreams.nl
+ *
+ * MangChat was enhanced by Lice , Dj_baby & Sanaell
+ * with help and support from the MaNGOS project community.
+ *
+ * PLEASE RETAIN THE COPYRIGHT OF THE AUTHOR.
+ *
+ */
+
+#include "Common.h"
+
+namespace IRCcommand
+{
+ // chan commands, default return type == PRIVMSG
+ void HandlePlayerIRCCommand(std::string param, std::string outputChan, std::string type="PRIVMSG");
+ void HandleOnlineIRCCommand(std::string param, std::string outputChan, std::string type="PRIVMSG");
+ void HandleInChanIRCCommand(std::string outputChan, std::string type="PRIVMSG");
+ void HandleInfoIRCCommand(std::string outputChan, std::string type="PRIVMSG");
+
+ // priv commands, default return type == NOTICE
+ void HandleKickIRCCommand(std::string param, std::string outputChan, int level, std::string type="NOTICE");
+ void HandleSaveAllIRCCommand(std::string outputChan, int level, std::string type="NOTICE");
+ void HandleTeleIRCCommand(std::string param, std::string outputChan, int level, std::string type="NOTICE");
+ void HandleReviveIRCCommand(std::string param, std::string outputChan, int level, std::string type="NOTICE");
+ void HandleKillIRCCommand(std::string param, std::string outputChan, int level, std::string type="NOTICE");
+ void HandleAnnounceIRCCommand(std::string param, std::string outputChan, int level, std::string type="NOTICE");
+ void HandleNotifyIRCCommand(std::string param, std::string outputChan, int level, std::string type="NOTICE");
+ void HandlePmIRCCommand(std::string param, std::string outputChan, int level, std::string from, std::string type="NOTICE");
+ void HandleLoginIRCCommand(std::string param, std::string outputChan, std::string from, std::string type="NOTICE");
+ void HandleLogoutIRCCommand(std::string outputChan, std::string from, std::string type="NOTICE");
+}
Index: src/game/Level0.cpp
===================================================================
--- src/game/Level0.cpp (revision 3815)
+++ src/game/Level0.cpp (working copy)
@@ -29,6 +29,7 @@
#include "ObjectAccessor.h"
#include "Language.h"
#include "SpellAuras.h"
+#include "IRCClient.h"
bool ChatHandler::ShowHelpForCommand(ChatCommand *table, const char* cmd)
{
@@ -365,3 +366,22 @@
SendSysMessage(LANG_BAD_VALUE);
return true;
}
+
+bool ChatHandler::HandleIRCpmCommand(const char* args)
+{
+ std::string Msg = args;
+ if ((sIRC.IRC_CMDS_MASK & 2) == 0)
+ {
+ Msg = "WoW <-> iRC pm system disabled";
+ PSendSysMessage(Msg.c_str());
+ return true;
+ }
+ if (Msg.find(" ") == std::string::npos)
+ return false;
+ std::string To = Msg.substr(0, Msg.find(" "));
+ Msg = Msg.substr(Msg.find(" ") + 1);
+ sIRC.SendIRCpm(m_session->GetPlayer(), To, Msg);
+ Msg = "|cffCC4ACCTo [" + To + "]: " + Msg + "|r";
+ PSendSysMessage(Msg.c_str());
+ return true;
+}
Index: src/game/Level1.cpp
===================================================================
--- src/game/Level1.cpp (revision 3815)
+++ src/game/Level1.cpp (working copy)
@@ -31,6 +31,7 @@
#include "Language.h"
#include "RedZoneDistrict.h"
#include "Transports.h"
+#include "IRCClient.h"
bool ChatHandler::HandleSayCommand(const char* args)
{
@@ -107,7 +108,8 @@
std::string str = LANG_SYSTEMMESSAGE;
str += args;
sWorld.SendWorldText(str.c_str(), NULL);
-
+ if ((sIRC.BOTMASK & 1024)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_sysmsg, "$Msg", args));
return true;
}
@@ -122,7 +124,8 @@
WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
data << str;
sWorld.SendGlobalMessage(&data);
-
+ if ((sIRC.BOTMASK & 1024)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_sysnotice, "$Msg", args));
return true;
}
Index: src/game/Makefile.am
===================================================================
--- src/game/Makefile.am (revision 3815)
+++ src/game/Makefile.am (working copy)
@@ -115,6 +115,10 @@
HomeMovementGenerator.h \
IdleMovementGenerator.cpp \
IdleMovementGenerator.h \
+ IRCClient.cpp \
+ IRCClient.h \
+ IRCCommands.cpp \
+ IRCCommands.h \
Item.cpp \
Item.h \
ItemHandler.cpp \
Index: src/game/Player.cpp
===================================================================
--- src/game/Player.cpp (revision 3815)
+++ src/game/Player.cpp (working copy)
@@ -33,6 +33,7 @@
#include "UpdateData.h"
#include "Channel.h"
#include "Chat.h"
+#include "IRCClient.h"
#include "MapManager.h"
#include "MapInstanced.h"
#include "ObjectMgr.h"
@@ -1904,6 +1905,15 @@
level += 1;
+ std::string pname = GetName();
+ char temp [5];
+ sprintf(temp, "%u", level);
+ std::string plevel = temp;
+ if ((sIRC.BOTMASK & 256)!= 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(),sIRC.MakeMsg(sIRC.MakeMsg(sIRC.WoW_levelup, "$Name", pname), "$Lev", plevel));
+ if ((sIRC.BOTMASK & 512)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.MakeMsg(sIRC.IRC_levelup, "$Name", pname), "$Lev", plevel));
+
InitStatsForLevel(level);
InitTalentForLevel();
@@ -3144,6 +3154,12 @@
void Player::ResurrectPlayer(float restore_percent, bool updateToWorld)
{
+ std::string pname = GetName();
+ if ((sIRC.BOTMASK & 64)!= 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(),sIRC.MakeMsg(sIRC.WoW_revive, "$Name", pname));
+ if ((sIRC.BOTMASK & 128)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_revive, "$Name", pname));
+
WorldPacket data(SMSG_SH_POSITION, 4*4); // remove spirit healer position
data << uint32(-1);
data << uint32(0);
@@ -3237,6 +3253,12 @@
void Player::KillPlayer()
{
+ std::string pname = GetName();
+ if ((sIRC.BOTMASK & 64)!= 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(),sIRC.MakeMsg(sIRC.WoW_died, "$Name", pname));
+ if ((sIRC.BOTMASK & 128)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_died, "$Name", pname));
+
if(InBattleGround())
{
BattleGround* bg = sBattleGroundMgr.GetBattleGround(GetBattleGroundId());
@@ -3483,12 +3505,25 @@
void Player::JoinedChannel(Channel *c)
{
+ std::string channame = c->GetName();
+ std::transform(channame.begin(), channame.end(), channame.begin(), towlower);
+ if (channame == sIRC.WOW_CHAN)
+ {
+ sIRC.HandleChannelJoin(this);
+ }
m_channels.push_back(c);
}
void Player::LeftChannel(Channel *c)
{
m_channels.remove(c);
+
+ std::string channame = c->GetName();
+ std::transform(channame.begin(), channame.end(), channame.begin(), towlower);
+ if (channame == sIRC.WOW_CHAN)
+ {
+ sIRC.HandleChannelPart(this);
+ }
}
void Player::CleanupChannels()
Index: src/game/World.cpp
===================================================================
--- src/game/World.cpp (revision 3815)
+++ src/game/World.cpp (working copy)
@@ -46,6 +46,7 @@
#include "TargetedMovementGenerator.h"
#include "RedZoneDistrict.h"
#include "WaypointMovementGenerator.h"
+#include "ChannelMgr.h"
INSTANTIATE_SINGLETON_1( World );
@@ -879,6 +880,48 @@
return;
}
+void World::SendWorldMessage(const char *channel, std::string chat, uint64 guid, WorldSession *self)
+{
+ /*
+ Why is this function needed?
+ tobe able to send a message you need a valid ingame GUID
+ snce the IRC client isnt logged in we cant properly send message
+ or it would result in non existing players
+ also i didnt manage to figure out how to get the sessions in my own clas
+ so this function was born
+ */
+ SessionMap::iterator itr;
+ for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++)
+ {
+ // Loop thru all online sessions
+ if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld() && itr->second != self)
+ {
+ // check if the player is in the world
+ if(ChannelMgr* cMgr = channelMgr(itr->second->GetPlayer()->GetTeam()))
+ {
+ // check if the player is grouped
+ if(Channel *chn = cMgr->GetChannel(channel, itr->second->GetPlayer()))
+ {
+ // if the player is on our channel
+
+ WorldPacket data;
+
+ data.Initialize(SMSG_MESSAGECHAT);
+ data << (uint8)14;
+ data << (uint32)0;
+ data << channel;
+ data << guid;
+ data << (uint32) (strlen(chat.c_str()) + 1);
+ data << chat.c_str();
+ data << (uint8)0;
+
+ itr->second->SendPacket(&data);
+ }
+ }
+ }
+ }
+}
+
/// Send a packet to all players (except self if mentionned)
void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team)
{
Index: src/game/World.h
===================================================================
--- src/game/World.h (revision 3815)
+++ src/game/World.h (working copy)
@@ -206,6 +206,7 @@
void SendWorldText(const char *text, WorldSession *self = 0);
void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
+ void SendWorldMessage(const char *channel, std::string chat, uint64 guid = 0, WorldSession *self = 0);
void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0);
void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0);
void SendServerMessage(uint32 type, const char *text = "", Player* player = NULL);
Index: src/game/WorldSession.cpp
===================================================================
--- src/game/WorldSession.cpp (revision 3815)
+++ src/game/WorldSession.cpp (working copy)
@@ -37,6 +37,8 @@
#include "ObjectAccessor.h"
#include "BattleGroundMgr.h"
#include "Language.h" // for CMSG_DISMOUNT handler
+#include "IRCClient.h"
+#include "ChannelMgr.h"
/// WorldSession constructor
WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec) : _player(NULL), _socket(sock),
@@ -647,6 +649,15 @@
data<<_player->GetGUID();
_player->BroadcastPacketToFriendListers(&data);
+ std::string pname = _player->GetName();
+
+ sIRC.HandleChannelPart(_player);
+
+ if ((sIRC.BOTMASK & 8)!= 0)
+ sWorld.SendWorldMessage(sIRC.WOW_CHAN.c_str(),sIRC.MakeMsg(sIRC.WoW_goneoffline, "$Name", pname));
+ if ((sIRC.BOTMASK & 16)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_goneoffline, "$Name", pname));
+
///- Delete the player object
delete _player;
_player = 0;
Index: src/mangosd/CliRunnable.cpp
===================================================================
--- src/mangosd/CliRunnable.cpp (revision 3815)
+++ src/mangosd/CliRunnable.cpp (working copy)
@@ -31,6 +31,7 @@
#include "SystemConfig.h"
#include "Config/ConfigEnv.h"
#include "Util.h"
+#include "../game/IRCClient.h"
#include "CliRunnable.h"
@@ -217,6 +218,8 @@
str += text;
sWorld.SendWorldText(str.c_str(), NULL);
zprintf("Broadcasting to the world:%s\r\n",str.c_str());
+ if ((sIRC.BOTMASK & 1024)!= 0)
+ sIRC.ChannelBot(sIRC.MakeMsg(sIRC.IRC_sysmsg, "$Msg", text));
}
/// Print the list of commands and associated description
Index: src/mangosd/mangosd.conf.in
===================================================================
--- src/mangosd/mangosd.conf.in (revision 3815)
+++ src/mangosd/mangosd.conf.in (working copy)
@@ -338,3 +338,122 @@
# Beep at mangosd start finished (mostly work only at Unix/Linux systems)
# Default: 1
BeepAtStart = 1
+
+#####################
+# IRC Configuration #
+#####################
+
+# IRCON - enable (1) or disable (0) the IRC extension.
+IRCON = 1
+
+# IRCCONNECTCODE - what code to wait for before starting to identify / join channels
+# 001 == Welcome to Network msg
+# 375 == Beginning of MOTD
+# 376 == End of MOTD
+IRCCONNECTCODE = "001"
+
+# IRCPort - irc server port to connect to
+IRCPort = 6667
+
+# IRCHost - irc server's host / ip
+IRCHost = "irc.station51.net"
+
+# IRCSERVERPASS - the pass requierd to connect to the server
+IRCSERVERPASS = "MyServerPass"
+
+# IRCNICK - the bots nick on irc
+IRCNICK = "MaNGOServ"
+
+# IRCUSER - the irc username
+IRCUSER = "MaNGOS"
+
+# IRCNICKPASS - the pass for identifying to nickserv or quakenet
+IRCNICKPASS = "MyDumbPass"
+
+# IRCQUAKENET - 0 == identify to nickserv, 1 == identify to quakenet
+IRCQUAKENET = 0
+
+# IRCDEFCHAN - channel to leave if IRCLeaveDefChannel == 1, must be lowercase
+IRCDEFCHAN = "lobby"
+IRCLeaveDefChannel = 0
+
+# IRCCHAN - the linked IRC channel, lowercase, no hash
+IRCCHAN = "mangostest"
+
+# WOWCHAN - the linked ingame channel, lowercase
+WOWCHAN = "mangostest"
+
+# IRCIgnorList - irc nicks to ignonre, use this if you dont want other channel bots to be echoed to the wow channel, seperate with spaces.
+IRCIgnorList = ""
+
+# IRCSTARTMSG - Msg to display in the irc channel when the bot comes online if IRCSTARTMSGON == 1
+IRCSTARTMSG = "Server Online"
+IRCSTARTMSGON = 1
+
+# BotMask - This mask defines what the bot announces. if its 0 everything is disabled... simply add the values of the elements you want to create this mask.
+# eg: irc join/leaves are 1 and wow join/leaves are 2, if you want both of these active and nothing else, the the mode is 3.
+# display irc joins/leaves/nickchanges ingame: 1
+# display wow chan join/leaves in irc: 2
+# display wow chan join/leaves in wow: 4
+# display wow come online/gone offline ingame: 8
+# display wow come online/gone offline in irc: 16
+# Announce gm logons ingame and irc (when the gm is in gmmode): 32
+# display death/resurrects ingame: 64
+# display death/resurrects in irc: 128
+# display level ups ingame: 256
+# display level ups in irc: 512
+# display system msgs and notices in irc: 1024
+BotMask = 2047
+
+# IRC_Cmds_Mask - this defines which commands will be active, IRC_Cmds_Prefix defines the command prefix.
+# level 0 commands (.online, .info ....): 1
+# irc <-> wow pms: 2
+# gm commands: 4
+IRC_Cmds_Mask = 7
+IRC_Cmds_Prefix = "."
+
+# rejoin channel on kick
+# 0 = disable
+# 1 = enable
+auto_rejoin_kick = 1
+
+####################################################
+# IRC Text Variables:
+# anything here with its name starting with WoW is displayed ingame, anything starting with IRC is displayed in the irc channel.
+# $Name == Player Name or IRC Nick
+# $Lev == Level
+# $Msg == Message
+# $Rank == GM Rank
+WoW_joinedIRC = ">> $Name joined IRC."
+WoW_leftIRC = "<< $Name left IRC."
+WoW_changedIRCnick = "<> $Name is now known as $NewName."
+IRC_joinedWoWchan = "12>>04 $Name Joined The Channel"
+WoW_joinedWoWchan = ">> $Name Joined The Channel"
+IRC_leftWoWchan = "12<<04 $Name Left The Channel"
+WoW_leftWoWchan = "<< $Name Left The Channel"
+IRC_comeonline = "12>>04 $Name has come Online"
+WoW_comeonline = ">> $Name has come Online"
+IRC_goneoffline = "12<<04 $Name has gone Offline"
+WoW_goneoffline = "<< $Name has gone Offline"
+IRC_died = "12<>04 $Name has joined the Spirits!"
+WoW_died = "<> $Name has joined the Spirits!"
+IRC_revive = "12<>04 $Name has rejoined the Living!"
+WoW_revive = "<> $Name has rejoined the Living!"
+IRC_levelup = "12<>04 $Name has gained Level $Lev!"
+WoW_levelup = "<> $Name has gained Level $Lev!"
+IRC_WoWmsg = "[$Name] $Msg"
+WoW_IRCmsg = "[$Name]: $Msg"
+WoW_IRCaction = "*$Name $Msg"
+IRC_sysmsg = "04,08/!\System Message/!\ $Msg 04,08/!\System Message/!\"
+IRC_sysnotice = "04,08/!\System Notice/!\ $Msg 04,08/!\System Notice/!\"
+GMAnnounceMessage = "|cffff0000[$Rank $Name has come Online]|r"
+GMAnnounceIRCMessage = "12>>04 $Rank $Name has come Online"
+GMRankMod = "Mod"
+GMRankGM = "GM"
+GMRankAdmin = "Admin"
+# IRC Text Variables End
+####################################################
+
+#########################
+# IRC Configuration End #
+#########################
Index: src/mangosd/Master.cpp
===================================================================
--- src/mangosd/Master.cpp (revision 3815)
+++ src/mangosd/Master.cpp (working copy)
@@ -34,6 +34,7 @@
#include "SystemConfig.h"
#include "Config/ConfigEnv.h"
#include "Database/DatabaseEnv.h"
+#include "../game/IRCClient.h"
#include "CliRunnable.h"
#include "RASocket.h"
#include "ScriptCalls.h"
@@ -178,6 +179,9 @@
uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / socketSelecttime));
uint32 loopCounter = 0;
+ ZThread::Thread irc(new IRCClient);
+ irc.setPriority ((ZThread::Priority )2);
+
///- Wait for termination signal
while (!World::m_stopEvent)
{
Index: src/realmd/Makefile.am
===================================================================
--- src/realmd/Makefile.am (revision 3815)
+++ src/realmd/Makefile.am (working copy)
@@ -30,7 +30,7 @@
RealmList.h
## Link realm list daemon against the shared library
-mangos_realmd_LDADD = ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zthread/libZThread.la
+mangos_realmd_LDADD = ../shared/libmangosdatabase.a ../shared/libmangosconfig.a ../shared/libmangosauth.a ../shared/libmangosshared.a ../shared/libmangosnetwork.a ../framework/libmangosframework.a ../../dep/src/zlib/libzlib.a ../../dep/src/zthread/libZThread.la
mangos_realmd_LDFLAGS = -L../../dep/src/zthread $(MYSQL_LIBS) -L$(libdir) $(ZLIB) $(COMPATLIB) $(SSLLIB)
## Additional files to include when running 'make dist'
Index: src/shared/Database/DBCfmt.cpp
===================================================================
--- src/shared/Database/DBCfmt.cpp (revision 3815)
+++ src/shared/Database/DBCfmt.cpp (working copy)
@@ -16,11 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-const char AreaTableEntryfmt[]="iiinixxxxxixxxxxxxxxixxxxxx";
+const char AreaTableEntryfmt[]="iiinixxxxxissssssssxixxxxxx";
const char BankBagSlotPricesEntryfmt[]="ni";
const char BattlemasterListEntryfmt[]="niixxxxxxiiiixxssssssssx";
const char ChatChannelsEntryfmt[]="iixssssssssxxxxxxxxxx"; // data not sorted (more compact store)
-const char ChrClassesEntryfmt[]="nxxixxxxxxxxxxxxxx";
+const char ChrClassesEntryfmt[]="nxxixssssssssxxxxx";
const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssxxxxx";
const char CreatureFamilyfmt[]="nxxxxxiissssssssxx";
const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx";
Index: src/shared/Database/DBCStructure.h
===================================================================
--- src/shared/Database/DBCStructure.h (revision 3815)
+++ src/shared/Database/DBCStructure.h (working copy)
@@ -41,7 +41,7 @@
uint32 flags; // 4, unknown value but 312 for all cities
// 5-9 unused
int32 area_level; //10
- //char* area_name[8]; //11-18, unused
+ char* area_name[8]; //11-18, unused
//19, string flags, unused
uint32 team; //20,
};
@@ -84,7 +84,7 @@
// 1-2, unused
uint32 powerType; // 3
// 4, unused
- //char* name[8]; // 5-12, unused
+ char* name[8]; // 5-12, unused
// 13 string flags, unused
};
Index: win/mangosdVC71.sln
===================================================================
--- win/mangosdVC71.sln (revision 3815)
+++ win/mangosdVC71.sln (working copy)
@@ -34,6 +34,7 @@
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "realmd", "VC71\realmd.vcproj", "{563E9905-3657-460C-AE63-0AC39D162E23}"
ProjectSection(ProjectDependencies) = postProject
{BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
+ {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} = {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}
{90297C34-F231-4DF4-848E-A74BCC0E40ED} = {90297C34-F231-4DF4-848E-A74BCC0E40ED}
{1DC6C4DA-A028-41F3-877D-D5400C594F88} = {1DC6C4DA-A028-41F3-877D-D5400C594F88}
{262199E8-EEDF-4700-A1D1-E9CC901CF480} = {262199E8-EEDF-4700-A1D1-E9CC901CF480}
Index: win/mangosdVC80.sln
===================================================================
--- win/mangosdVC80.sln (revision 3815)
+++ win/mangosdVC80.sln (working copy)
@@ -1,9 +1,9 @@
Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual C++ Express 2005
+# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "game", "VC80\game.vcproj", "{1DC6C4DA-A028-41F3-877D-D5400C594F88}"
ProjectSection(ProjectDependencies) = postProject
+ {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
{90297C34-F231-4DF4-848E-A74BCC0E40ED} = {90297C34-F231-4DF4-848E-A74BCC0E40ED}
- {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "VC80\shared.vcproj", "{90297C34-F231-4DF4-848E-A74BCC0E40ED}"
@@ -13,11 +13,11 @@
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mangosd", "VC80\mangosd.vcproj", "{A3A04E47-43A2-4C08-90B3-029CEF558594}"
ProjectSection(ProjectDependencies) = postProject
+ {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
+ {90297C34-F231-4DF4-848E-A74BCC0E40ED} = {90297C34-F231-4DF4-848E-A74BCC0E40ED}
+ {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
+ {1DC6C4DA-A028-41F3-877D-D5400C594F88} = {1DC6C4DA-A028-41F3-877D-D5400C594F88}
{262199E8-EEDF-4700-A1D1-E9CC901CF480} = {262199E8-EEDF-4700-A1D1-E9CC901CF480}
- {1DC6C4DA-A028-41F3-877D-D5400C594F88} = {1DC6C4DA-A028-41F3-877D-D5400C594F88}
- {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
- {90297C34-F231-4DF4-848E-A74BCC0E40ED} = {90297C34-F231-4DF4-848E-A74BCC0E40ED}
- {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zthread", "VC80\zthread.vcproj", "{262199E8-EEDF-4700-A1D1-E9CC901CF480}"
@@ -28,11 +28,12 @@
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "realmd", "VC80\realmd.vcproj", "{563E9905-3657-460C-AE63-0AC39D162E23}"
ProjectSection(ProjectDependencies) = postProject
+ {A3A04E47-43A2-4C08-90B3-029CEF558594} = {A3A04E47-43A2-4C08-90B3-029CEF558594}
{BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
+ {90297C34-F231-4DF4-848E-A74BCC0E40ED} = {90297C34-F231-4DF4-848E-A74BCC0E40ED}
+ {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
+ {1DC6C4DA-A028-41F3-877D-D5400C594F88} = {1DC6C4DA-A028-41F3-877D-D5400C594F88}
{262199E8-EEDF-4700-A1D1-E9CC901CF480} = {262199E8-EEDF-4700-A1D1-E9CC901CF480}
- {1DC6C4DA-A028-41F3-877D-D5400C594F88} = {1DC6C4DA-A028-41F3-877D-D5400C594F88}
- {A3A04E47-43A2-4C08-90B3-029CEF558594} = {A3A04E47-43A2-4C08-90B3-029CEF558594}
- {90297C34-F231-4DF4-848E-A74BCC0E40ED} = {90297C34-F231-4DF4-848E-A74BCC0E40ED}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "script", "VC80\script.vcproj", "{4205C8A9-79B7-4354-8064-F05FB9CA0C96}"
Index: win/VC71/game.vcproj
===================================================================
--- win/VC71/game.vcproj (revision 3815)
+++ win/VC71/game.vcproj (working copy)
@@ -709,6 +709,21 @@
+
+
+
+
+
+
+
+
+
+
Index: win/VC80/game.vcproj
===================================================================
--- win/VC80/game.vcproj (revision 3815)
+++ win/VC80/game.vcproj (working copy)
@@ -968,6 +968,26 @@
>
+
+
+
+
+
+
+
+
+
+
Index: win/VC80/mangosd.vcproj
===================================================================
--- win/VC80/mangosd.vcproj (revision 3815)
+++ win/VC80/mangosd.vcproj (working copy)
@@ -1,7 +1,7 @@