QTalk technical documentation
=============================

QTalk is designed to connect to a specified quake server. Its purpose
once connected is to bypass all messages and talking from players
on the server to and from QServer. QTalk is designed so that a new
frontend can be designed for it without hassle. The frontend only
has to run QTalk ('filer_run <QTalk$Dir>.!run' should suffice) and
then comply with the message passing protocol described below to
interact with QTalk.

QTalk is a regular Quake protocol bot and will not connect to Quake
World servers (maybe ill implement it later on when Ive totally gone mad).
Calling it a bot is probably a bit of a lie because it doesnt do much. It does
enough to keep a client alive on a Quake server and communicate with QServer.

QTalk failings
==============

Well the main one is that it cannot join to a server that is full. So
trying to talk on one that is full will fail. Also there are many
servers that run different patches which may expect the full set of
Quakes console commands which QTalk doesn't implement. I have implemented
enough to get you onto a CTF server (i.e. doesn't chuck you off and
call you a cheating bastard!) without to much trouble but I can't guarantee
all servers. (apparently it still does though 8( )

QTalks wimp messages
====================

To interact with QServer, QTalk uses a set of wimp messages. Initially
QTalk was going to be implemented into the main QServer application
itself but this was decided against because of its complexity and
the probability of things going wrong during connection to the quake
server. With QTalk being a seperate task, in the event of unhappy goings
on with the server and QTalk, QTalk can exit quietly without bringing
down QServer. Also this enables us to forget Desklib to bring the code
size down.

For the wimp messages I have designated only one number which is &FEBFEB.
This is not an officially designated number from Acorn so it may clash
with another. In the event of this happening this number is configurable
within the QTalk.Config file.

qtalkmsg_header
---------------

All the different messages will have the same header determining what
they are and if they are complete:-

  struct {
    long int	message_length; (for simplicity, always 256)
    long int	message_ref[3]; (always all 0, hey I dont care!)
    long int	message_id; (i.e. &FEBFEB)
    char	message_type;
    char	message_complete;
    char	null[2];
  } qtalkmsg_header;

If message_complete is 1 then you must regard this message as complete.
If 0 then there is more to come in the next message. (unimplemented)

Values of message_type are listed below:-

VALUE NAME		SENT TO			EXTRA DATA

0x00  message_INIT	QTalk --> QServer       QTalk task handle
0x01  message_ACKINIT	QServer --> QTalk	QServer task handle
0x02  message_CLIENT	QServer --> QTalk	Client name, Client colours
0x03  message_CONNECT	QServer --> QTalk	IP address, Port number
0x04  message_CONNECTED QTalk --> QServer	Game port number
0x05  message_PRINT	QTalk --> QServer	Message string
0x06  message_DISCON	QServer --> QTalk	N/A
0x07  message_CHNGLVL	QTalk --> QServer	N/A
0x08  message_DYING	QTalk --> QServer	Error reason
0x09  message_SAY	QServer --> QTalk	Message string
0x0A  message_CONNFAIL	QTalk --> QServer	Failure reason
0x0B  message_ALIVE	QServer --> QTalk	N/A
0x0C  message_ACKALIVE	QTalk --> QServer	N/A

0x00 message_INIT
-----------------

struct {
  long int	handle;
} init;

This message is sent when QTalk is first started up. It informs QServer
of its task handle so messages do not have to be broadcast.

0x01 message_ACKINIT
--------------------

struct {
  long int	handle;
} ackinit;

Sent by QServer after it has received a message_INIT. Informs QTalk
of QServers task handle.

0x02 message_CLIENT
-------------------

struct {
  char		pants;
  char		shirt;
  char		name[16];
} client;

Sent to QTalk to inform it of the client details it should use to
connect to the Quake Server.

0x03 message_CONNECT
--------------------

struct {
  char		address[24];
  short int	port;
} connect;

Sent to QTalk when a connection is required to the Quake Server.
QTalk will then start to connect to the Quake server specified.

0x04 message_CONNECTED
----------------------

struct {
  short int	port;
} connected;

Sent by QTalk when it has successfully connected to the Quake Server.

0x05 message_PRINT
------------------

struct {
  char		print[232];
} print;

Sent when QTalk wants QServer to print something in its IRC box.
This could be a message about someone dying, someone saying something,
you saying something, or a message about the change of level.
Usually all these will be echoed into the QTalk.Log file for debugging.

The first character can be important. The character determines what
type of message is to be printed and how:-

  Char	|  Action
  ===============================
  *	|  When text is to be bold
  ~	|  Level name
  #	|  Someone saying something
  !	|  Error text
  N/A	|  Normal text

(tofix: hmmm. what if a server asks you to print !fenix was gibbed by me)

0x06 message_DISCON
-------------------

No struct

Sent when QServer wants QTalk to disconnect from the Quake server. This
will happen when the session is ended by the user, when QServer is
quit, or when a server is joined. Once QTalk has disconnected it will quit.

0x07 message_CHNGLVL
--------------------

No struct

Sent by QTalk to inform QServer that the Quake Server is changing maps
and that QTalk will have to go through the signon process again.
QServer should not allow the user to say anything until a message_CONNECTED
is received once again.

0x08 message_DYING
------------------

struct {
  char		reason[232];
} dying;

Sent to QServer when QTalk has come into a situation where it must quit.

0x09 message_SAY
----------------

struct {
  char		saymessage[232];
} say;

Sent to QTalk when user has something to say. saymessage is then broadcast
to all players on the Quake server. If saymessage is preceded by a '/'
character then the message is regarded as a special command. Special
commands are:-

  /ping		Will show pings of all players on the server
  /status	Displays a list of players on the server
  /name ....	Changes your name
  /color s p	Changes your colours to pants = p, shirt = s
  /impulse x	Calls a special impulse x (not implemented yet)
  
Anything else will be ignored by QTalk and passed onto the server.
(all the above are an example of this!)

0x0A message_CONNFAIL
---------------------

struct {
  char		reason[234];
} connfail;

Sent by QTalk when connection to the Quake server has failed in some
way.

0x0B message_ALIVE
------------------

No struct

This message is sent every 1 second by QServer. Its intention is to see
if QTalk had died and had not broadcast a message_DYING or message_CONNFAIL.
If no reply is received (with message_ACKALIVE) after two sends of this
message then QServer shuts down the talk session.

0x0C message_ACKALIVE
---------------------

No struct

Must be sent in reply to a message_ALIVE by QTalk to show that it is still
alive.

Example session between QTalk and QServer
=========================================

Heres an example session with QTalk. N.B. I havent included the message_ALIVE
and message_ACK messages and have also cut down on some of the messages cos
Im not insane.

--> QServer

Filer_Run <QTalk$Dir>.!Run

--> QTalk

message_INIT		&xxxxxxxx
message_PRINT		"*QTalk Client Bot 1.01 (12th Jan 1998)"

--> QServer

message_ACKINIT		&xxxxxxxx
message_CLIENT		"[IM] LiStA", 6, 11
message_CONNECT		"quake.dircon.co.uk", 26000

--> QTalk

message_PRINT		"*Connecting ..."
message_PRINT		"Trying ..."
message_PRINT		"Trying ..."
message_PRINT		"*Connection accepted ..."
message_PRINT		"VERSION 1.06 SERVER (CRC 5335)"
message_PRINT		"~Slipgate central"
message_PRINT		"*Connected ..."
message_CONNECTED	0 (<-- 0 cos I thought, whats the point!)
message_PRINT		"#Rimma: Hi!"
message_PRINT		"[IM] LiStA was gibbed by Rimma's rocket"

--> QServer

message_SAY		"Ouch. That hurt!"

--> QTalk

message_PRINT		"#[IM] LiStA: Ouch That hurt!"

--> QServer

message_SAY		"/ping"

--> QTalk

message_PRINT		"Client ping times:"
message_PRINT		"  Rimma      238"
message_PRINT		"  [IM] LiStA 0" (<-- Yes. You do get 0 pings!)

--> QServer

message_SAY		"bye!"

--> QTalk

message_PRINT		"#[IM] LiStA: bye!"
message_PRINT		"#Rimma: cya"

--> QServer

message_DISCON

...

Now from this point onwards, QTalk will still be running only until it
is sure that disconnection was successful. This ensures that QTalk
doesn't quit leaving the server trying to talk to you. If it did this
a couple of times from different servers it would muck your connection
up. (a la ping flooding)

QServer finally finds out when disconnection has been successful when
no more message_ACKALIVE's are received. So its up to QServer to know
that after it has sent a message_DISCON or received a message_CONNFAIL
or message_DYING it should not show the usual "QTalk has died for
some reason" error message.