Descent3/legacy/mtclient/mtpilottracker.cpp
Louis Gombert 31b63bb79f Add license to legacy utilities
Generated using script:
for file in \$(find ./legacy -type f | \grep -E "\.cpp|\.h")
do
  mv $file temp.xxx
  cp gplheader $file
  cat temp.xxx >> $file
done
2024-04-20 18:33:12 +02:00

904 lines
20 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
* $Logfile: /DescentIII/Main/mtclient/mtpilottracker.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003-08-26 03:58:40 $
* $Author: kevinb $
*
* Pilot tracker client code
*
* $Log: not supported by cvs2svn $
*
* 15 10/28/99 3:13p Kevin
* fixed major badness with byte ordering 'fix'
*
* 14 9/02/99 3:16p Kevin
* Macintosh byte ordering fixes
*
* 13 9/01/99 5:24p Kevin
* Macintosh byte ordering problems
*
* 12 7/21/99 9:11a Kevin
* bandwidth reduction act #1
*
* 11 4/21/99 11:15a Kevin
* sectret code to tell the differences between oem, demo and retail
* builds on the tracker
*
* 10 4/19/99 8:36p Jeff
* Compile under Linux
*
* 9 3/02/99 5:50p Kevin
* Ouch. Duplicate structures existed and were conflicting.
*
* 8 1/11/99 6:02p Kevin
* Fixed warning
*
* 7 12/23/98 6:38p Kevin
* All UDP data (except gamespy) now uses one (registered) port number
*
* 6 11/03/98 9:27a Kevin
* Added PXO message of the day
*
* 5 10/30/98 11:25a Kevin
* Message of the day for PXO
*
* 4 8/31/98 10:14a Kevin
* Misc. multi-UI fixes
*
* 3 8/25/98 6:33p Kevin
* PXO screens
*
* 2 6/01/98 10:10a Kevin
* Added DLL connection interface and auto update DLL
*
* 1 5/25/98 4:12p Kevin
*
* 10 5/14/98 6:08p Kevin
* fixed encryption bug
*
* 9 5/14/98 5:19p Kevin
* Encrypted pilot data
*
* 8 5/07/98 9:47a Kevin
* Made pilot reading more robust
*
* 7 5/04/98 1:22p Kevin
* Mastertracker
*
* 6 5/04/98 12:53p Kevin
* Fixed mastertracker resend stuff
*
* 5 5/01/98 12:28p Kevin
* Added new user registration button for MT
*
* 4 4/30/98 3:50p Kevin
* Mastertracker pilot stats
*
* 3 4/28/98 12:51p Kevin
* Master tracker login
*
* 2 4/27/98 7:12p Kevin
* Mastertracker pilot tracker
*
* 1 4/27/98 5:29p Kevin
* Initial Version
*
* $NoKeywords: $
*/
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "game.h"
#include "ddio.h"
#include "descent.h"
#include "pstypes.h"
#include "pserror.h"
#include "mem.h"
#include "mono.h"
#include "networking.h"
#include "mt_net.h"
#include "byteswap.h"
#define LOGIN_LEN 33
#define REAL_NAME_LEN 66
#define PASSWORD_LEN 17
#define EMAIL_LEN 100
#define TRACKER_ID_LEN 10
#define PILOT_NAME_LEN 20
#ifdef WIN32
#pragma pack(push,pxo)
#endif
#pragma pack(1)
typedef struct vmt_descent3_struct {
char tracker_id[TRACKER_ID_LEN];
char pilot_name[PILOT_NAME_LEN];
int rank;
int kills;
int deaths;
int suicides;
int online_time;
int games_played;
unsigned int security;
unsigned char virgin_pilot; //This pilot was just created if TRUE
unsigned int lateral_thrust;
unsigned int rotational_thrust;
unsigned int sliding_pct; //Percentage of the time you were sliding
unsigned long checksum; //This value needs to be equal to whatever the checksum is once the packet is decoded
unsigned long pad; //just to provide room for out 4 byte encryption boundry only needed on the client side for now
} vmt_descent3_struct;
#define DESCENT3_BLOCK_SIZE (sizeof(vmt_descent3_struct)-4)
#ifdef WIN32
#pragma pack(pop,pxo)
#else
#pragma pack()
#endif
#include "mtpilottrack.h"
#define DLLmprintf(args) DLLDebug_ConsolePrintf args
typedef void( *Debug_ConsolePrintf_fp ) (int n, char *format, ... );
extern Debug_ConsolePrintf_fp DLLDebug_ConsolePrintf;
typedef float( *timer_GetTime_fp) (void);
extern timer_GetTime_fp DLLtimer_GetTime;
typedef int (*nw_RegisterCallback_fp) (void * nfp, ubyte id);
extern nw_RegisterCallback_fp DLLnw_RegisterCallback;
typedef int (*nw_DoReceiveCallbacks_fp)(void);
extern nw_DoReceiveCallbacks_fp DLLnw_DoReceiveCallbacks;
#define VALID_STATE_IDLE 1
#define VALID_STATE_WAITING 2
#define VALID_STATE_VALID 3
#define VALID_STATE_INVALID 4
#define VALID_STATE_TIMEOUT 5
#define VERSION_STATE_IDLE 1
#define VERSION_STATE_WAITING 2
#define VERSION_STATE_RECEIVED 3
#define VERSION_STATE_TIMEOUT 5
#define STATE_WAITING_MOTD 8
#define STATE_HAVE_MOTD 9
#define MAX_MOTDLEN 1000
//Variables
int D3WriteState;
int D3ReadState;
float D3LastSent;
float D3FirstSent;
float D3LastSentWrite;
float D3FirstSentWrite;
udp_packet_header d3_pilot_req,d3_pilot_write,motd_req;
pilot_request *d3_pr;
vmt_descent3_struct *ReadD3Pilot;
vmt_descent3_struct WriteD3Pilot;
udp_packet_header PacketHeader,VersionPacketHeader;
validate_id_request *ValidIDReq;
int MOTDState;
float MOTDFirstSent;
float MOTDLastSent;
char *Motdptr;
unsigned int Motd_maxlen;
int ValidState;
float ValidFirstSent;
float ValidLastSent;
int VersionState;
float VersionFirstSent;
float VersionLastSent;
char *VersionURL;
unsigned int ValidSecurity;
char *Psztracker_id;
char ProccesingPilot[PILOT_NAME_LEN];
typedef int (*PollUI_fp) (void);
extern PollUI_fp DLLPollUI;
int InitPilotTrackerClient()
{
D3WriteState = STATE_IDLE;
D3ReadState = STATE_IDLE;
ReadD3Pilot = NULL;
ValidState=VALID_STATE_IDLE;
VersionState = VERSION_STATE_IDLE;
srand(DLLtimer_GetTime());
ValidSecurity = (unsigned int)rand();
//Build the request packet
PacketHeader.type = UNT_LOGIN_AUTH_REQUEST;//UNT_VALIDAT_ID_REQUEST;
PacketHeader.len = INTEL_SHORT(PACKED_HEADER_ONLY_SIZE+sizeof(validate_id_request));
ValidIDReq=(validate_id_request *)&PacketHeader.data;
d3_pr = (pilot_request *)&d3_pilot_req.data;
DLLnw_RegisterCallback(HandlePilotData,PXO_NETID_USER_TRACKER);
return 1;
}
//Returns:
//-3 Error -- Called with NULL, but no request is waiting
//-2 Error -- Already sending data (hasn't timed out yet)
//-1 Timeout trying to send pilot data
// 0 Sending
// 1 Data succesfully sent
//Call with NULL to poll
//Call with valid pointer to a vmt_descent3_struct to initiate send
int SendD3PilotData(vmt_descent3_struct *d3_pilot)
{
//First check the network
PollPTrackNet();
if(d3_pilot == NULL)
{
if(D3WriteState == STATE_IDLE)
{
return -3;
}
if(D3WriteState == STATE_SENDING_PILOT)
{
return 0;
}
if(D3WriteState == STATE_WROTE_PILOT)
{
//We wrote this pilot, and now we are about to inform the app, so back to idle
D3WriteState = STATE_IDLE;
return 1;
}
if(D3WriteState == STATE_TIMED_OUT)
{
//We gave up on sending this pilot, and now we are about to inform the app, so back to idle
D3WriteState = STATE_IDLE;
return -1;
}
if(D3WriteState == STATE_WRITE_PILOT_FAILED)
{
//The tracker said this dude couldn't be written
D3WriteState = STATE_IDLE;
return 3;
}
}
else if((int)d3_pilot == -1)
{
if(D3WriteState == STATE_IDLE)
{
return -3;
}
else
{
//Cancel this baby
D3WriteState = STATE_IDLE;
return 2;
}
}
else if(D3WriteState == STATE_IDLE)
{
//New request, send out the req, and go for it.
D3WriteState = STATE_SENDING_PILOT;
D3LastSentWrite = DLLtimer_GetTime();
D3FirstSentWrite = DLLtimer_GetTime();
d3_pilot_write.len = INTEL_SHORT(PACKED_HEADER_ONLY_SIZE+DESCENT3_BLOCK_SIZE);
d3_pilot_write.type = UNT_PILOT_DATA_WRITE;
d3_pilot_write.code = INTEL_INT(CMD_GAME_DESCENT3);
d3_pilot_write.security = d3_pilot->security;
d3_pilot->deaths = INTEL_INT(d3_pilot->deaths);
d3_pilot->kills = INTEL_INT(d3_pilot->kills);
d3_pilot->online_time = INTEL_INT(d3_pilot->online_time);
d3_pilot->games_played = INTEL_INT(d3_pilot->games_played);
d3_pilot->lateral_thrust = INTEL_INT(d3_pilot->lateral_thrust);
d3_pilot->rank = INTEL_INT(d3_pilot->rank);
d3_pilot->rotational_thrust = INTEL_INT(d3_pilot->rotational_thrust);
d3_pilot->sliding_pct = INTEL_INT(d3_pilot->sliding_pct);
d3_pilot->suicides = INTEL_INT(d3_pilot->suicides);
#if (!(defined(OEM) || defined(DEMO)))
//This is the secret number we will use to determine if it's
//a game where we want to update the player's rank or not.
d3_pilot->lateral_thrust = INTEL_INT(0x142);
#endif
memcpy(&d3_pilot_write.data,d3_pilot,DESCENT3_BLOCK_SIZE);
return 0;
}
return -2;
}
//Returns:
//-3 Error -- Called with NULL, but no request is waiting
//-2 Error -- Already waiting on data (hasn't timed out yet)
//-1 Timeout waiting for pilot data
// 0 Waiting for data
// 1 Data received
// 2 Get Cancelled
//Call with NULL to poll
//Call with -1 to cancel wait
//Call with valid pointer to a vmt_descent3_struct to get a response
int GetD3PilotData(vmt_descent3_struct *d3_pilot,char *pilot_name,char *tracker_id)
{
//First check the network
PollPTrackNet();
if(d3_pilot == NULL)
{
if(D3ReadState == STATE_IDLE)
{
return -3;
}
if(D3ReadState == STATE_READING_PILOT)
{
return 0;
}
if(D3ReadState == STATE_RECEIVED_PILOT)
{
//We got this pilot, and now we are about to inform the app, so back to idle
D3ReadState = STATE_IDLE;
ReadD3Pilot = NULL;
return 1;
}
if(D3ReadState == STATE_TIMED_OUT)
{
//We gave up on this pilot, and now we are about to inform the app, so back to idle
D3ReadState = STATE_IDLE;
ReadD3Pilot = NULL;
return -1;
}
if(D3ReadState == STATE_PILOT_NOT_FOUND)
{
//The tracker said this dude is not found.
D3ReadState = STATE_IDLE;
ReadD3Pilot = NULL;
return 3;
}
}
else if((int)d3_pilot == -1)
{
if(D3ReadState == STATE_IDLE)
{
return -3;
}
else
{
//Cancel this baby
D3ReadState = STATE_IDLE;
ReadD3Pilot = NULL;
return 2;
}
}
else if(D3ReadState == STATE_IDLE)
{
//New request, send out the req, and go for it.
D3ReadState = STATE_READING_PILOT;
ReadD3Pilot = d3_pilot;
D3LastSent = DLLtimer_GetTime();
D3FirstSent = DLLtimer_GetTime();//DLLtimer_GetTime();
d3_pilot_req.len = INTEL_SHORT(PACKED_HEADER_ONLY_SIZE+sizeof(pilot_request));
d3_pilot_req.type = UNT_PILOT_DATA_READ;
d3_pilot_req.code = INTEL_INT(CMD_GAME_DESCENT3);
strcpy(d3_pr->pilot_name,pilot_name);
strcpy(d3_pr->tracker_id,tracker_id);
strcpy(ProccesingPilot,pilot_name);
return 0;
}
return -2;
}
//Send an ACK to the server
void AckServer(unsigned int sig)
{
udp_packet_header ack_pack;
ack_pack.type = UNT_CONTROL;
ack_pack.sig = sig;
ack_pack.code = INTEL_INT(CMD_CLIENT_RECEIVED);
ack_pack.len = INTEL_SHORT(PACKED_HEADER_ONLY_SIZE);
SendPilotTrackerPacket(&ack_pack);
//sendto(pilotsock,(char *)&ack_pack,PACKED_HEADER_ONLY_SIZE,0,(SOCKADDR *)&ptrackaddr,sizeof(SOCKADDR_IN));
}
void IdlePTrack()
{
//socket
if(D3ReadState == STATE_READING_PILOT)
{
if((DLLtimer_GetTime()-D3FirstSent)>=PILOT_REQ_TIMEOUT)
{
D3ReadState = STATE_TIMED_OUT;
}
else if((DLLtimer_GetTime()-D3LastSent)>=PILOT_REQ_RESEND_TIME)
{
//Send 'da packet
//sendto(pilotsock,(char *)&d3_pilot_req,d3_pilot_req.len,0,(SOCKADDR *)&ptrackaddr,sizeof(SOCKADDR_IN));
SendPilotTrackerPacket(&d3_pilot_req);
D3LastSent = DLLtimer_GetTime();
}
}
if(D3WriteState == STATE_SENDING_PILOT)
{
if((DLLtimer_GetTime()-D3FirstSentWrite)>=PILOT_REQ_TIMEOUT)
{
D3WriteState = STATE_TIMED_OUT;
}
else if((DLLtimer_GetTime()-D3LastSentWrite)>=PILOT_REQ_RESEND_TIME)
{
//Send 'da packet
SendPilotTrackerPacket(&d3_pilot_write);
//sendto(pilotsock,(char *)&d3_pilot_write,d3_pilot_write.len,0,(SOCKADDR *)&ptrackaddr,sizeof(SOCKADDR_IN));
D3LastSentWrite = DLLtimer_GetTime();
}
}
if(MOTDState == STATE_WAITING_MOTD)
{
if((DLLtimer_GetTime()-MOTDFirstSent)>=PILOT_REQ_TIMEOUT)
{
MOTDState = STATE_TIMED_OUT;
}
else if((DLLtimer_GetTime()-MOTDLastSent)>=PILOT_REQ_RESEND_TIME)
{
//Send 'da packet
SendPilotTrackerPacket(&motd_req);
MOTDLastSent = DLLtimer_GetTime();
}
}
}
void PollPTrackNet()
{
IdlePTrack();
DLLnw_DoReceiveCallbacks();
}
int Motd_version = 0;
void HandlePilotData(ubyte *data,int len, network_address *from)
{
udp_packet_header inpacket;
vmt_descent3_struct *d3_pilot;
memcpy(&inpacket,data,sizeof(inpacket));
inpacket.len = INTEL_SHORT(inpacket.len)-1;
if(len)
{
switch(inpacket.type)
{
case UNT_MOTD_RESPONSE:
if(MOTDState == STATE_WAITING_MOTD)
{
if(Motdptr)
{
if((inpacket.len-PACKED_HEADER_ONLY_SIZE) > Motd_maxlen)
inpacket.len = PACKED_HEADER_ONLY_SIZE+Motd_maxlen-1;
strncpy(Motdptr,(char *)inpacket.data,inpacket.len-PACKED_HEADER_ONLY_SIZE);
Motdptr[inpacket.len-PACKED_HEADER_ONLY_SIZE] = NULL;
}
MOTDState = STATE_HAVE_MOTD;
}
break;
case UNT_PILOT_DATA_RESPONSE:
if(inpacket.code == CMD_GAME_DESCENT3)
{
if(D3ReadState == STATE_READING_PILOT)
{
d3_pilot = (vmt_descent3_struct *)&inpacket.data;
xorcode(d3_pilot,DESCENT3_BLOCK_SIZE,inpacket.security);
if(strcmpi(ProccesingPilot,d3_pilot->pilot_name)==0)
{
//Copy the data
memcpy(ReadD3Pilot,&inpacket.data,DESCENT3_BLOCK_SIZE);
//Set the state
D3ReadState = STATE_RECEIVED_PILOT;
}
}
}
break;
case UNT_PILOT_READ_FAILED:
if(inpacket.code == CMD_GAME_DESCENT3)
{
if(D3ReadState == STATE_READING_PILOT)
{
D3ReadState = STATE_PILOT_NOT_FOUND;
}
}
break;
case UNT_PILOT_WRITE_SUCCESS:
if(inpacket.code == CMD_GAME_DESCENT3)
{
if(D3WriteState == STATE_SENDING_PILOT)
{
D3WriteState = STATE_WROTE_PILOT;
}
}
break;
case UNT_PILOT_WRITE_FAILED:
if(inpacket.code == CMD_GAME_DESCENT3)
{
if(D3WriteState == STATE_SENDING_PILOT)
{
D3WriteState = STATE_WRITE_PILOT_FAILED;
}
}
break;
case UNT_CONTROL:
switch(INTEL_INT(inpacket.code))
{
case CMD_VALIDATED_USER_ACK:
if(ValidState == VALID_STATE_WAITING)
{
ValidState = VALID_STATE_VALID;
}
break;
case CMD_VALIDATED_USER_NAK:
if(ValidState == VALID_STATE_WAITING)
{
ValidState = VALID_STATE_INVALID;
}
break;
}
case UNT_LOGIN_NO_AUTH:
if(ValidState == VALID_STATE_WAITING)
{
ValidState = VALID_STATE_INVALID;
}
break;
case UNT_LOGIN_AUTHENTICATED:
if(ValidState == VALID_STATE_WAITING)
{
ValidState = VALID_STATE_VALID;
strcpy(Psztracker_id,(const char *)&inpacket.data);
//memcpy(&Motd_version,inpacket.data[strlen(Psztracker_id)+1],sizeof(int));
Motd_version = inpacket.xcode;
}
break;
case UNT_TRACKER_VERSION_RSP:
if(VersionState == VERSION_STATE_WAITING)
{
//This is a version response possibly with the URL to download a file at the end.
strcpy(VersionURL,(const char *)&inpacket.data);
VersionState = VERSION_STATE_RECEIVED;
}
break;
default:
break;
}
}
AckServer(inpacket.sig);
}
//Call with a valid struct to validate a user
//Call with NULL to poll
//Return codes:
// -3 Still waiting (returned if we were waiting for a tracker response and ValidateUser was called with a non-NULL value
// -2 Timeout waiting for tracker to respond
// -1 User invalid
// 0 Still waiting for response from tracker/Idle
// 1 User valid
int ValidateUser(validate_id_request *valid_id, char *trackerid)
{
ValidIdle();
if(valid_id==NULL)
{
switch(ValidState)
{
case VALID_STATE_IDLE:
return 0;
break;
case VALID_STATE_WAITING:
return 0;
break;
case VALID_STATE_VALID:
ValidState = VALID_STATE_IDLE;
return 1;
break;
case VALID_STATE_INVALID:
ValidState = VALID_STATE_IDLE;
return -1;
case VALID_STATE_TIMEOUT:
ValidState = VALID_STATE_IDLE;
return -2;
}
return 0;
}
else
{
//if(ValidState==VALID_STATE_IDLE)
{
/*
//First, flush the input buffer for the socket
unsigned int bytesin;
udp_packet_header inpacket;
do
{
bytesin = ReceivePilotTracker(&inpacket);
}while(bytesin && (bytesin!=-1));
*/
Psztracker_id = trackerid;
ValidSecurity = (unsigned int)rand();
PacketHeader.security = ValidSecurity;
//strcpy(ValidIDReq->tracker_id,valid_id->tracker_id);
strcpy(ValidIDReq->login,valid_id->login);
strcpy(ValidIDReq->password,valid_id->password);
SendPilotTrackerPacket(&PacketHeader);
ValidState = VALID_STATE_WAITING;
ValidFirstSent = DLLtimer_GetTime();
ValidLastSent = DLLtimer_GetTime();
return 0;
}
// else
// {
// return -3;
// }
}
}
void ValidIdle()
{
PollPTrackNet();
if(ValidState == VALID_STATE_WAITING)
{
if((DLLtimer_GetTime()-ValidFirstSent)>=PILOT_REQ_TIMEOUT)
{
ValidState = VALID_STATE_TIMEOUT;
}
else if((DLLtimer_GetTime()-ValidLastSent)>=PILOT_REQ_RESEND_TIME)
{
//Send 'da packet
SendPilotTrackerPacket(&PacketHeader);
ValidLastSent = DLLtimer_GetTime();
}
}
}
//This code will modify 4 bytes at a time, so make sure to pad it!!!
void xorcode(void *data,unsigned int len,unsigned long hash)
{
return;
unsigned int i=0;
unsigned long *src = (unsigned long *)&data;
while(i<len)
{
*src = *src ^ hash;
src++;
i += sizeof(unsigned long);
}
}
void VersionIdle()
{
PollPTrackNet();
if(VersionState == VERSION_STATE_WAITING)
{
if((DLLtimer_GetTime()-VersionFirstSent)>=PILOT_REQ_TIMEOUT)
{
VersionState = VERSION_STATE_TIMEOUT;
}
else if((DLLtimer_GetTime()-VersionLastSent)>=PILOT_REQ_RESEND_TIME)
{
//Send 'da packet
SendPilotTrackerPacket(&VersionPacketHeader);
VersionLastSent = DLLtimer_GetTime();
}
}
}
//Return codes:
// -3 Still waiting (returned if we were waiting for a tracker response and VersionCheck was called with a non-NULL value
// -2 Timeout waiting for tracker to respond
// 0 Still waiting for response from tracker/Idle
// 1 Version received (URL[0] will not be NULL if we have the URL which means we need a newer version)
//Call once with the real version, then poll with the version set to 0 URL is a pointer to a char buff(max size == 200) that will be filled if/when we get a URL response
int MTAVersionCheck(unsigned int oldver, char *URL)
{
int res = DLLPollUI();
if(res==99)
{
VersionState = VERSION_STATE_TIMEOUT;
}
VersionIdle();
if(oldver==0)
{
switch(VersionState)
{
case VERSION_STATE_IDLE:
return 0;
break;
case VERSION_STATE_WAITING:
return 0;
break;
case VERSION_STATE_RECEIVED:
VersionState = VERSION_STATE_IDLE;
return 1;
case VERSION_STATE_TIMEOUT:
VersionState = VERSION_STATE_IDLE;
return -2;
}
return 0;
}
else
{
if(VersionState==VERSION_STATE_IDLE)
{
/*
//First, flush the input buffer for the socket
unsigned int bytesin;
udp_packet_header inpacket;
do
{
bytesin = ReceivePilotTracker(&inpacket);
}while(bytesin && (bytesin!=-1));
*/
VersionURL = URL;
VersionPacketHeader.len = INTEL_SHORT(PACKED_HEADER_ONLY_SIZE);
VersionPacketHeader.type = UNT_TRACKER_VERSION_REQ;
VersionPacketHeader.xcode = INTEL_SHORT(CMD_GAME_DESCENT3);
VersionPacketHeader.code = INTEL_INT(oldver);
SendPilotTrackerPacket(&VersionPacketHeader);
VersionState = VERSION_STATE_WAITING;
VersionFirstSent = DLLtimer_GetTime();
VersionLastSent = DLLtimer_GetTime();
return 0;
}
else
{
return -3;
}
}
}
//Returns:
//-3 Error -- Called with NULL, but no request is waiting
//-2 Error -- Already waiting on message of the day (hasn't timed out yet)
//-1 Timeout waiting for message of the day
// 0 Waiting for data
// 1 Data received
// 2 Get Cancelled
//Call with NULL to poll
//Call with -1 to cancel wait
//Call with valid pointer and maxlen to get the message of the day
int GetD3MOTD(char *szmotd,int maxlen)
{
//First check the network
PollPTrackNet();
if(szmotd == NULL)
{
if(MOTDState == STATE_WAITING_MOTD)
{
return 0;
}
if(MOTDState == STATE_TIMED_OUT)
{
MOTDState = STATE_IDLE;
return -1;
}
if(MOTDState == STATE_HAVE_MOTD)
{
MOTDState = STATE_IDLE;
return 1;
}
return -3;
}
else if((int)szmotd == -1)
{
if(MOTDState == STATE_IDLE)
{
return -3;
}
else
{
//Cancel this baby
MOTDState = STATE_IDLE;
Motdptr = NULL;
ReadD3Pilot = NULL;
return 2;
}
}
else if(MOTDState == STATE_IDLE)
{
//New request, send out the req, and go for it.
MOTDState = STATE_WAITING_MOTD;
Motdptr = szmotd;
Motd_maxlen = maxlen;
MOTDFirstSent = DLLtimer_GetTime();
MOTDLastSent = DLLtimer_GetTime();
motd_req.len = INTEL_SHORT(PACKED_HEADER_ONLY_SIZE);
motd_req.type = UNT_MOTD_REQUEST;
motd_req.code = INTEL_INT(CMD_GAME_DESCENT3);
return 0;
}
return -2;
}