mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-29 22:27:57 +03:00
552 lines
14 KiB
C
552 lines
14 KiB
C
// GameSpy Chat SDK C Test App
|
|
// Dan "Mr. Pants" Schoenblum
|
|
// dan@gamespy.com
|
|
|
|
/*************
|
|
** INCLUDES **
|
|
*************/
|
|
#include "../chat.h"
|
|
#include "../../common/gsStringUtil.h"
|
|
|
|
#ifdef UNDER_CE
|
|
void RetailOutputA(CHAR *tszErr, ...);
|
|
#define printf RetailOutputA
|
|
#elif defined(_NITRO)
|
|
#include "../../common/nitro/screen.h"
|
|
#define printf Printf
|
|
#define vprintf VPrintf
|
|
#endif
|
|
|
|
#define MAX_MESSAGE_SIZE 200
|
|
#define CHAT_NICK_SIZE 128
|
|
|
|
/************
|
|
** GLOBALS **
|
|
************/
|
|
// mj Nov 7th, zero out to known state globals.
|
|
int port = 0;
|
|
CHAT chat = {0};
|
|
gsi_char serverAddress[128] = {0};
|
|
gsi_char chatNick[128] = {0};
|
|
gsi_char chatUser[128] = {0};
|
|
gsi_char chatName[128] = {0};
|
|
gsi_char chatChannel[128] = {0};
|
|
gsi_char gamename[128] = {0};
|
|
gsi_char secretKey[128] = {0};
|
|
CHATBool quit = CHATFalse;
|
|
|
|
#ifdef __MWERKS__ // CodeWarrior will warn if functions not prototyped
|
|
/***************
|
|
** PROTOTYPES **
|
|
***************/
|
|
int test_main(int argc, char **argv);
|
|
#endif
|
|
|
|
/**************
|
|
** FUNCTIONS **
|
|
**************/
|
|
#ifdef GSI_UNICODE
|
|
#define _tstrcasecmp WideCaseCompare
|
|
#define _tstrncasecmp WideCaseNCompare
|
|
#else
|
|
#define _tstrcasecmp strcasecmp
|
|
#define _tstrncasecmp strncasecmp
|
|
#endif
|
|
|
|
// Simulate case insensitive compare functions
|
|
#if defined(GSI_UNICODE)
|
|
int WideCaseCompare(const unsigned short* s1, const unsigned short* s2);
|
|
int WideCaseNCompare(const unsigned short* s1, const unsigned short* s2, size_t count);
|
|
|
|
int WideCaseCompare(const unsigned short* s1, const unsigned short* s2)
|
|
{
|
|
char s1_A[512];
|
|
char s2_A[512];
|
|
UCS2ToAsciiString(s1, s1_A);
|
|
UCS2ToAsciiString(s2, s2_A);
|
|
return strcasecmp(s1_A, s2_A);
|
|
}
|
|
|
|
int WideCaseNCompare(const unsigned short* s1, const unsigned short* s2, size_t count)
|
|
{
|
|
char s1_A[512];
|
|
char s2_A[512];
|
|
unsigned short temp[512];
|
|
|
|
// null terminate
|
|
temp[count+1] = 0;
|
|
|
|
// Copy to temp buffer, then convert to ascii
|
|
memcpy(temp, s1, count * sizeof(unsigned short));
|
|
UCS2ToAsciiString(temp, s1_A);
|
|
|
|
memcpy(temp, s2, count * sizeof(unsigned short));
|
|
UCS2ToAsciiString(temp, s2_A);
|
|
|
|
return strncasecmp(s1_A, s2_A, count);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
static void Raw(CHAT chat, const gsi_char * raw, void * param)
|
|
{
|
|
_tprintf(_T("RAW: %s\n"), raw);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void Disconnected(CHAT chat, const gsi_char * reason, void * param)
|
|
{
|
|
_tprintf(_T("Disconnected: %s\n"), reason);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void ChangedNickCallback(CHAT chat, CHATBool success, const gsi_char * oldNick, const gsi_char * newNick, void * param)
|
|
{
|
|
if(success)
|
|
{
|
|
_tprintf(_T("Successfully changed"));
|
|
_tcscpy(chatNick, newNick);
|
|
}
|
|
else
|
|
_tprintf(_T("Failed to change"));
|
|
_tprintf(_T(" nick from %s to %s\n"), oldNick, newNick);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void PrivateMessage(CHAT chat, const gsi_char * user, const gsi_char * message, int type, void * param)
|
|
{
|
|
_tprintf(_T("Private message from %s: %s\n"), user, message);
|
|
|
|
// Nick change?
|
|
///////////////
|
|
if(_tstrncasecmp(_T("nick"), message, 4) == 0)
|
|
{
|
|
chatChangeNick(chat, &message[5], ChangedNickCallback, NULL, CHATFalse);
|
|
}
|
|
|
|
GSI_UNUSED(type);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void Invited(CHAT chat, const gsi_char * channel, const gsi_char * user, void * param)
|
|
{
|
|
_tprintf(_T("Invited by %s to %s\n"), user, channel);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void ChannelMessage(CHAT chat, const gsi_char * channel, const gsi_char * user, const gsi_char * message, int type, void * param)
|
|
{
|
|
gsi_char buffer[MAX_MESSAGE_SIZE];
|
|
|
|
_tprintf(_T("%s, in %s, said \"%s\"\n"), user, channel, message);
|
|
|
|
// Is this from us?
|
|
///////////////////
|
|
if(_tstrcasecmp(user, chatNick) == 0)
|
|
return;
|
|
|
|
// Is it a command?
|
|
///////////////////
|
|
if(message[0] == '!')
|
|
{
|
|
message++;
|
|
if(!_tstrcasecmp(message, _T("quit")) || !_tstrcasecmp(message, _T("exit")))
|
|
quit = CHATTrue;
|
|
return;
|
|
}
|
|
_tsnprintf(buffer, MAX_MESSAGE_SIZE, _T("%s: I agree"), user);
|
|
buffer[MAX_MESSAGE_SIZE - 1] = '\0';
|
|
chatSendChannelMessage(chat, channel, buffer, CHAT_MESSAGE);
|
|
|
|
GSI_UNUSED(type);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void Kicked(CHAT chat, const gsi_char * channel, const gsi_char * user, const gsi_char * reason, void * param)
|
|
{
|
|
_tprintf(_T("Kicked from %s by %s: %s\n"), channel, user, reason);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void UserJoined(CHAT chat, const gsi_char * channel, const gsi_char * user, int mode, void * param)
|
|
{
|
|
_tprintf(_T("%s joined %s"), user, channel);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
GSI_UNUSED(mode);
|
|
}
|
|
|
|
static void UserParted(CHAT chat, const gsi_char * channel, const gsi_char * user, int why, const gsi_char * reason, const gsi_char * kicker, void * param)
|
|
{
|
|
if(why == CHAT_LEFT)
|
|
_tprintf(_T("%s left %s\n"), user, channel);
|
|
else if(why == CHAT_QUIT)
|
|
_tprintf(_T("%s quit: %s\n"), user, reason);
|
|
else if(why == CHAT_KICKED)
|
|
_tprintf(_T("%s was kicked from %s by %s: %s"), user, channel, kicker, reason);
|
|
else if(why == CHAT_KILLED)
|
|
_tprintf(_T("%s was killed: %s\n"), user, reason);
|
|
else
|
|
_tprintf(_T("UserParted() called with unknown part-type\n"));
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void UserChangedNick(CHAT chat, const gsi_char * channel, const gsi_char * oldNick, const gsi_char * newNick, void * param)
|
|
{
|
|
_tprintf(_T("%s changed nicks to %s\n"), oldNick, newNick);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(channel);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void UserModeChanged(CHAT chat, const gsi_char * channel, const gsi_char * user, int mode, void * param)
|
|
{
|
|
_tprintf(_T("%s's new mode in %s is "), user, channel);;
|
|
if(mode == CHAT_VOICE)
|
|
_tprintf(_T("voice\n"));
|
|
else if(mode == CHAT_OP)
|
|
_tprintf(_T("ops\n"));
|
|
else if(mode == (CHAT_VOICE | CHAT_OP))
|
|
_tprintf(_T("voice+ops\n"));
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void TopicChanged(CHAT chat, const gsi_char * channel, const gsi_char * topic, void * param)
|
|
{
|
|
_tprintf(_T("The topic in %s changed to %s\n"), channel, topic);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void ChannelModeChanged(CHAT chat, const gsi_char * channel, CHATChannelMode * mode, void * param)
|
|
{
|
|
_tprintf(_T("The mode in %s has changed:\n"), channel);
|
|
_tprintf(_T(" InviteOnly: %d\n"), mode->InviteOnly);
|
|
_tprintf(_T(" Private: %d\n"), mode->Private);
|
|
_tprintf(_T(" Secret: %d\n"), mode->Secret);
|
|
_tprintf(_T(" Moderated: %d\n"), mode->Moderated);
|
|
_tprintf(_T(" NoExternalMessages: %d\n"), mode->NoExternalMessages);
|
|
_tprintf(_T(" OnlyOpsChangeTopic: %d\n"), mode->OnlyOpsChangeTopic);
|
|
_tprintf(_T(" Limit: "));
|
|
if(mode->Limit == 0)
|
|
_tprintf(_T("N/A\n"));
|
|
else
|
|
_tprintf(_T("%d\n"), mode->Limit);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void UserListUpdated(CHAT chat, const gsi_char * channel, void * param)
|
|
{
|
|
_tprintf(_T("User list updated\n"));
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(channel);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void ConnectCallback(CHAT chat, CHATBool success, int failureReason, void * param)
|
|
{
|
|
if (success == CHATFalse)
|
|
_tprintf(_T("Failed to connect (%d)\n"), failureReason);
|
|
else
|
|
_tprintf(_T("Connected\n"));
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(success);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
|
|
static void FillInUserCallback(CHAT chat, unsigned int IP, gsi_char user[128], void * param)
|
|
{
|
|
_tcscpy(user, chatUser);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(IP);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void NickErrorCallback(CHAT chat, int type, const gsi_char * nick, int numSuggestedNicks, const gsi_char ** suggestedNicks, void * param)
|
|
{
|
|
if(type == CHAT_IN_USE)
|
|
{
|
|
_tprintf(_T("The nick %s is already being used.\n"), nick);
|
|
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time());
|
|
chatNick[CHAT_NICK_SIZE - 1] = '\0';
|
|
chatRetryWithNick(chat, chatNick);
|
|
}
|
|
else if(type == CHAT_INVALID)
|
|
{
|
|
_tprintf(_T("The nick %s is invalid!\n"), nick);
|
|
// chatDisconnect(chat); THIS CRASHES
|
|
|
|
// 10-14-2004: Added By Saad Nader
|
|
// this is necessary as the function will fail if a new nick is not retries.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time());
|
|
chatNick[CHAT_NICK_SIZE - 1] = '\0';
|
|
chatRetryWithNick(chat, chatNick);
|
|
}
|
|
else if((type == CHAT_UNIQUENICK_EXPIRED) || (type == CHAT_NO_UNIQUENICK))
|
|
{
|
|
_tprintf(_T("This account has no uniquenick or an expired uniquenick!\n"));
|
|
|
|
chatRegisterUniqueNick(chat, 2, _T("MrPants"), _T(""));
|
|
}
|
|
else if(type == CHAT_INVALID_UNIQUENICK)
|
|
{
|
|
int i;
|
|
|
|
_tprintf(_T("The uniquenick %s is invalid or in use\n"), nick);
|
|
_tprintf(_T("There are %d suggested nicks:\n"), numSuggestedNicks);
|
|
|
|
for(i = 0 ; i < numSuggestedNicks ; i++)
|
|
_tprintf(_T(" %s\n"), suggestedNicks[i]);
|
|
}
|
|
|
|
// 10-14-2004: Added By Saad Nader
|
|
// added for the addition of a new error code.
|
|
////////////////////////////////////////////////////////////////////////////
|
|
else if(type == CHAT_NICK_TOO_LONG)
|
|
{
|
|
_tprintf(_T("The nick %s is too long.\n"), nick);
|
|
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time());
|
|
chatNick[CHAT_NICK_SIZE - 1] = '\0';
|
|
chatRetryWithNick(chat, chatNick);
|
|
}
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
CHATBool enterChannelSuccess;
|
|
static void EnterChannelCallback(CHAT chat, CHATBool success, CHATEnterResult result, const gsi_char * channel, void * param)
|
|
{
|
|
enterChannelSuccess = success;
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(result);
|
|
GSI_UNUSED(channel);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
static void GetUserInfoCallback(CHAT chat, CHATBool success, const gsi_char * nick, const gsi_char * user, const gsi_char * name, const gsi_char * address, int numChannels, const gsi_char ** channels, void * param)
|
|
{
|
|
int i;
|
|
|
|
if(!success)
|
|
{
|
|
_tprintf(_T("GetUserInfo failed\n"));
|
|
return;
|
|
}
|
|
|
|
_tprintf(_T("%s's Info:\n"), nick);
|
|
_tprintf(_T(" User: %s\n"), user);
|
|
_tprintf(_T(" Name: %s\n"), name);
|
|
_tprintf(_T(" Address: %s\n"), address);
|
|
_tprintf(_T(" Channels (%d):\n"), numChannels);
|
|
for(i = 0 ; i < numChannels ; i++)
|
|
_tprintf(_T(" %s\n"), channels[i]);
|
|
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(param);
|
|
}
|
|
/*
|
|
static void EnumChannelsAllCallback(CHAT chat, CHATBool success, int numChannels, const gsi_char ** channel, const gsi_char ** topic, int* numUsers, void * param)
|
|
{
|
|
GSI_UNUSED(chat);
|
|
GSI_UNUSED(success);
|
|
GSI_UNUSED(numChannels);
|
|
GSI_UNUSED(channel);
|
|
GSI_UNUSED(topic);
|
|
GSI_UNUSED(numUsers);
|
|
GSI_UNUSED(param);
|
|
}
|
|
*/
|
|
static void EnumUsersCallback(CHAT chat, CHATBool success, const gsi_char * channel, int numUsers, const gsi_char ** users, int * modes, void * param)
|
|
{
|
|
int i;
|
|
|
|
if(!success)
|
|
{
|
|
_tprintf(_T("EnumUsers failed\n"));
|
|
return;
|
|
}
|
|
|
|
for(i = 0 ; i < numUsers ; i++)
|
|
chatGetUserInfo(chat, users[i], GetUserInfoCallback, NULL, CHATFalse);
|
|
|
|
GSI_UNUSED(channel);
|
|
GSI_UNUSED(modes);
|
|
GSI_UNUSED(param);
|
|
}
|
|
|
|
int test_main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
chatGlobalCallbacks globalCallbacks;
|
|
chatChannelCallbacks channelCallbacks;
|
|
unsigned long stopTime;
|
|
|
|
|
|
// Set default options.
|
|
///////////////////////
|
|
// SDK takes care of default server address and port now
|
|
//_tcscpy(serverAddress, _T("peerchat." GSI_DOMAIN_NAME));
|
|
//port = 6667;
|
|
_tsnprintf(chatNick,CHAT_NICK_SIZE,_T("ChatC%lu"),(unsigned long)current_time() % 1000);
|
|
chatNick[CHAT_NICK_SIZE - 1] = '\0';
|
|
_tcscpy(chatUser, _T("ChatCUser"));
|
|
_tcscpy(chatName, _T("ChatCName"));
|
|
_tcscpy(chatChannel, _T("#GSP!gmtest"));
|
|
_tcscpy(gamename, _T("gmtest"));
|
|
secretKey[0] = 'H';
|
|
secretKey[1] = 'A';
|
|
secretKey[2] = '6';
|
|
secretKey[3] = 'z';
|
|
secretKey[4] = 'k';
|
|
secretKey[5] = 'S';
|
|
secretKey[6] = '\0';
|
|
|
|
// Go through command-line options.
|
|
///////////////////////////////////
|
|
for(i = 1 ; i < argc ; i++)
|
|
{
|
|
if((argv[i][0] == '-') && ((i + 1) < argc))
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 's':
|
|
#ifndef GSI_UNICODE
|
|
strcpy(serverAddress, argv[++i]);
|
|
#else
|
|
AsciiToUCS2String(argv[++i], serverAddress);
|
|
#endif
|
|
break;
|
|
case 'p':
|
|
port = atoi(argv[++i]);
|
|
break;
|
|
case 'n':
|
|
#ifndef GSI_UNICODE
|
|
strcpy(chatNick, argv[++i]);
|
|
#else
|
|
AsciiToUCS2String(argv[++i], chatNick);
|
|
#endif
|
|
break;
|
|
case 'u':
|
|
#ifndef GSI_UNICODE
|
|
strcpy(chatUser, argv[++i]);
|
|
#else
|
|
AsciiToUCS2String(argv[++i], chatUser);
|
|
#endif
|
|
break;
|
|
case 'c':
|
|
#ifndef GSI_UNICODE
|
|
strcpy(chatChannel, argv[++i]);
|
|
#else
|
|
AsciiToUCS2String(argv[++i], chatChannel);
|
|
#endif
|
|
break;
|
|
default:
|
|
_tprintf(_T("Error parsing command-line: %s\n"), argv[i]);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_tprintf(_T("Error parsing command-line: %s\n"), argv[i]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Set global callbacks.
|
|
////////////////////////
|
|
memset(&globalCallbacks, 0, sizeof(chatGlobalCallbacks));
|
|
globalCallbacks.raw = Raw;
|
|
globalCallbacks.disconnected = Disconnected;
|
|
globalCallbacks.privateMessage = PrivateMessage;
|
|
globalCallbacks.invited = Invited;
|
|
globalCallbacks.param = NULL;
|
|
|
|
// Connect.
|
|
///////////
|
|
chat = chatConnectSecure(serverAddress[0]?serverAddress:NULL, port, chatNick, chatName, gamename, secretKey, &globalCallbacks, NickErrorCallback, FillInUserCallback, ConnectCallback, NULL, CHATTrue);
|
|
if(!chat)
|
|
{
|
|
_tprintf(_T("Connect failed\n"));
|
|
return 1;
|
|
}
|
|
|
|
// Set channel callbacks.
|
|
/////////////////////////
|
|
memset(&channelCallbacks, 0, sizeof(chatChannelCallbacks));
|
|
channelCallbacks.channelMessage = ChannelMessage;
|
|
channelCallbacks.channelModeChanged = ChannelModeChanged;
|
|
channelCallbacks.kicked = Kicked;
|
|
channelCallbacks.topicChanged = TopicChanged;
|
|
channelCallbacks.userParted = UserParted;
|
|
channelCallbacks.userJoined = UserJoined;
|
|
channelCallbacks.userListUpdated = UserListUpdated;
|
|
channelCallbacks.userModeChanged = UserModeChanged;
|
|
channelCallbacks.userChangedNick = UserChangedNick;
|
|
channelCallbacks.param = NULL;
|
|
|
|
// Join.
|
|
////////
|
|
chatEnterChannel(chat, chatChannel, NULL, &channelCallbacks, EnterChannelCallback, NULL, CHATTrue);
|
|
if(!enterChannelSuccess)
|
|
{
|
|
_tprintf(_T("Enter Channel failed\n"));
|
|
return 1;
|
|
}
|
|
|
|
// Say hi.
|
|
//////////
|
|
chatSendChannelMessage(chat, chatChannel, _T("Hi"), CHAT_MESSAGE);
|
|
|
|
|
|
// Enum through the players.
|
|
////////////////////////////
|
|
chatEnumUsers(chat, chatChannel, EnumUsersCallback, NULL, CHATFalse);
|
|
|
|
// Stay for a while.
|
|
////////////////////
|
|
stopTime = (current_time() + 60000);
|
|
do
|
|
{
|
|
chatThink(chat);
|
|
msleep(50);
|
|
}
|
|
while(!quit && (current_time() < stopTime));
|
|
|
|
// Say bye.
|
|
///////////
|
|
chatSendChannelMessage(chat, chatChannel, _T("Bye"), CHAT_MESSAGE);
|
|
|
|
// Leave.
|
|
/////////
|
|
chatLeaveChannel(chat, chatChannel, NULL);
|
|
|
|
// Disconnect.
|
|
//////////////
|
|
chatDisconnect(chat);
|
|
_tprintf(_T("All Done!\n"));
|
|
return 0;
|
|
}
|