External GM Chat
You sure did read the title right!
I am releasing an addon that lets you talk to other game masters on other servers!
Still confused?
Ex: You are the owner of a private server with four realms... you install my add-on to all four realms and now game masters can talk to each other regardless of their realm!
Ex: You and your friend are messing around on your own personal private servers, you both have the add-on installed and configured, you can talk to each other on separate realms!
Information
I have made a video on how to add this into your core and get everything working.
**Note the sound did cut out toward the end of the video when I was explaining the config files
Most of the info on the config files are self explanatory, but you do need to make sure that the port and auth_code match up in both the main server's config file and the other config file.
(You also need to move the config file from
\External_GM_Chat\External_GM_Chat\Files\Config
to where your private server's config files are located
Enjoy!!
P.S. The command is
.global text
ex: .global hello my name is pwntzyou!
How to install(video):
ScreenToaster - HowToCompile External GM Chat Screencast Video
Download:
Filebeam - Beam up that File Scottie!
Preview:
External_GM_Chat.cpp
Code:
/* Pwntzyou's Cross server GM chat
* Copyright(C) 2009 Pwntzyou
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
#include <winsock.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
//Stuff//////
const int kBufferSize = 1024;
SOCKET ChatServer;
u_long nRemoteAddress;
/////////////
//Data///////
string keyword[] = {"server_ip: ", "server_port: ", "auth_code: ", "server_nick: "};
string server_ip;
int server_port;
string auth_code;
string server_nick;
/////////////
////////////////////////////////////////////////////////////////////////
// Prototypes
SOCKET EstablishConnection(u_long nRemoteAddr, u_short nPort);
int ReadReply();
int SendGlobalChat(string message);
int StartConnection();
int StartExternalChatThread();
void parse_line(char line_text[200]);
////////////////////////////////////////////////////////////////////////
int StartConnection()
{
/////////////////////////////
//Find the server's address//
nRemoteAddress = inet_addr(server_ip.c_str());
/////////////////////////////
// Connect to the server/////
cout << endl << "[ExtChat]: Attempting to connect to the chat server..." << flush;
ChatServer = EstablishConnection(nRemoteAddress, htons(server_port));
while(ChatServer == INVALID_SOCKET)
{
//cout << endl << "[ExtChat]:! n n
//Connection to server failed, retrying in 10 seconds..." << endl;
Sleep(10000);
ChatServer = EstablishConnection(nRemoteAddress, htons(server_port));
}
/////////////////////////////
//We have connected... yay!//
cout << endl << "[ExtChat]: Successfully connected to the external chat server!" << endl;
//Server will deny our connection if this is not right
SendGlobalChat(auth_code);
bool connected = true;
while(connected)
{
if(ReadReply() == -1)
{
//Server most likely went boom... try to reconnect!
connected = false;
StartConnection();
}
}
return 0;
}
DWORD WINAPI ThreadStart(void* data)
{
char line_text[200];
fstream text;
text.open("configs/GM_Chat.ini");
if(text)
{
while(!text.eof())
{
text.getline(line_text,200);
parse_line(line_text);
}
if(server_ip != "" && server_port != NULL && auth_code != "" && server_nick != "")
StartConnection();
else
cout << endl << "[ExtChat]: One or more options was wrong in the config file" << endl;
}
else
{
//We could not open the config file
cout << endl << "[ExtChat]: Could not find the config file" << endl;
}
return 0;
}
void parse_line(char line_text[200])
{
//convert line_text to a string
string temp = line_text;
//Determans if we find our text or not
size_t found;
int i;
for(i = 0; i < 4; i++)
{
//Search for the string
found = temp.find(keyword[i]);
//If the string exists and does not start with #
if(found != string::npos && temp.at(0) != '#')
{
temp.erase(0, (int)found + keyword[i].size());
if(i == 0)
server_ip = temp;
if(i == 1)
server_port = atoi(temp.c_str());
if(i == 2)
auth_code = temp;
if(i == 3)
server_nick = temp;
}
}
return;
}
int StartExternalChatThread() //Starter for this is in Master.cpp
{
Sleep(3000); // Simple sleep for a bit before we start
int null_int;
DWORD nThreadID;
CreateThread(0, 0, ThreadStart, (void*)null_int, 0, &nThreadID);
return 0;
}
SOCKET EstablishConnection(u_long Address, u_short Port)
{
ChatServer = socket(AF_INET, SOCK_STREAM, 0);
if (ChatServer != INVALID_SOCKET)
{
sockaddr_in sinRemote;
sinRemote.sin_family = AF_INET;
sinRemote.sin_addr.s_addr = Address;
sinRemote.sin_port = Port;
if (connect(ChatServer, (sockaddr*)&sinRemote, sizeof(sockaddr_in)) == SOCKET_ERROR)
ChatServer = INVALID_SOCKET;
}
return ChatServer;
}
int SendGlobalChat(string message)
{
// Send the string to the server...
//if something went wrong return true... otherwise return false
if (send(ChatServer, message.c_str(), message.size() + 1, 0) != SOCKET_ERROR)
{
return true;
}
else
{
return false;
}
}
int ReadReply()
{
// Read reply from server
int nTotalBytes = 0;
char acReadBuffer[kBufferSize];
int nNewBytes = recv(ChatServer, acReadBuffer, kBufferSize, 0);
if (nNewBytes == SOCKET_ERROR)
{
//something bad happened :(
return -1;
}
else if (nNewBytes == 0)
{
//Our server sent a shut down message to us!
cerr << "Connection closed by peer." << endl;
return 0;
}
PlayerStorageMap::const_iterator itr;
objmgr._playerslock.AcquireReadLock();
for (itr = objmgr._players.begin(); itr != objmgr._players.end(); itr++)
{
if(itr->second->GetSession()->GetPermissionCount())
{
Player* gmplayer = objmgr.GetPlayer(itr->second->GetName(), true);
if(gmplayer)
gmplayer->BroadcastMessage(acReadBuffer);
}
}
objmgr._playerslock.ReleaseReadLock();
return nNewBytes;
}
Other.cpp
Code:
/* Pwntzyou's Cross server GM chat
* Copyright(C) 2009 Pwntzyou
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//THIS IS NOT A COMPLETE C++ SCRIPT
//YOU NEED TO ADD DIFFERENT PARTS TO DIFFERENT SECTIONS
//ADD TO MASTER.CPP
extern int StartExternalChatThread();
StartExternalChatThread();
//ADD TO LEVEL1.CPP
bool ChatHandler::HandleCrossServerCommand(const char* args, WorldSession *m_session)
{
extern int SendGlobalChat(string message);
extern string server_nick;
if(args == "")
return false;
string message = "[";
message += m_session->GetPlayer()->GetName();
message += " - ";
message += server_nick;
message += "]: ";
message += args;
SendGlobalChat(message);
return true;
}
//ADD TO CHAT.CPP
{ "global", 'u', &ChatHandler::HandleCrossServerCommand, "If the external chat-server is started, this command is used to talk across servers between GMs", NULL, 0, 0, 0 },
//ADD TO CHAT.H
bool HandleCrossServerCommand(const char* args, WorldSession *m_session);