To put the UDP Functions in your game, you could either use the UDP_Chat
code as a base for your game, as you've already got the basic login window
there- the GUI just needs some tidying up. You could have the window open
on Workbench as it does already, and just leave it open while your game is
running, or have it open on your game screen, from a user selecting a menu
item etc. Note: You'd want to put all the UDP Functions together in one
include as below.
   Or you could cut the UDP Funcs out of UDP_Chat and put them all in the
UDPFuncs.bb2 include, along with the UDPHeader.bb2, and the
Net_protocol_header.bb2, so all you have is one include (which has to be
included before your own functions) in your code. The reason I've left
them in UDP_Chat, is for debugging purposes. I intend to make the UDP
Functions into a share lib, but this shouldn't really effect your code.
   Note: You have to insert the includes where they're included in the
UDP_Chat code ie: UDPHeader.bb2 under .Dims, and UDPFuncs.bb2 above
.Dim_Message_Arrays. Then cut out the entire code from where it's labeled
at the top of UDP_Chat down to the bottom of Comms_Housekeeping, then
put this into an include like UDP_Funcs.bb2. You may want to keep some
of the constants and variables at the top of your code (ie: not in the
include), if you want to tweak them- note that the ones you can adjust
are marked; you shouldn't touch the others, if you don't know what you're
doing!
   As for implementing multi-player ability into your game, read everything in these docs from top to bottom, especially the Theory section and the link web sites on the subject. These Funcs provide the basic communication and login routines, and time sync, but you'll have to do the multi-player game strategies yourself, as you can't write universal code for that, as each game is different. For example, if you're sending out any speed and direction changes for a player, then working out where the player should be on another machine, is going to depend entirely on how the game is set up (how big the player is, what walls they could collide into, wether it's 2D/3D, etc, etc).
   There's a player information array `player_info.info', which
you can load your player preferences into ie: player's colour(s), player's
name (nick), etc. Currently this info will be sent to all other players on
login, but I'll change that to an optional Function call to send the info, to
allow for more flexibility.
   Here's the Newtype for the player info. To load it, just use each
element in the array, with first the info_type (the constants are below), and then
fill in appropriate variable- ie:
   player_info(0)\info_type=#NUMBERW ; this element is a word
   player_info(0)\numberw=6 ; whose value is 6
Or the element could be a byte, long, string, or a memory block (fill in the
start of the block and the length of the block). Also it could be a disk file
(fill in the path and name of file, and it's type so your program knows what
to do with it). I haven't implemented the sending of a disk file yet.
   Finish the array with player_info(0)\info_type=0, or
#END_OF_CRITICAL_DATA with player_info(0)\info_type=0 at the end. Everything
up to #END_OF_CRITICAL_DATA will be sent in the player data packet (later I'll
allow bigger files/data to be sent before the game starts, so you could send
data critical to the game, like Player Skins etc. Anything after (say sound
samples, other files or large memory blocks), can be trickle fed after the
game has started, so as not to delay the game start. Again I haven't
implemented the trickle feed yet either.
NEWTYPE .info ; player info newtype
  info_type.w
  numberb.b
  numberw.w
  numberl.l
  string.s
  file_type.w
  filename.s
  memory_start.l
  memory_length.l
End NEWTYPE
Player Info Type Constants
#NUMBERB    ; - byte
#NUMBERW    ; - word
#NUMBERL    ; - long
#STRING    ; - string
#FILENAME    ; - disk file
#MEMORY_BLOCK    ; - memory block
#END_OF_CRITICAL_DATA    ; end of data essential for the game to start
   For examples on how to load up the array, see the bottom of .Init_Gui and to then read other player's info see `Case #NEW_PLAYER' in the Case-Select in .Main, as the info is stored in a memory block. Note: that this may moved to "Get Incoming Game Data" in .Main (along with the others like #CONNECTED moved to Process_Comms_Information{}, to tidy the API up.
   To send information to another computer you can do it Reliably or Unreliably. Reliably, the computer at the other end sends a message acknowledging that it has received the message. If the sending computer hasn't received the acknowledgment in a certain time it will resend the packet; if it takes more than a defined number of resends it assumes the link has been lost, and disconnects that machine from the game. This is necessary for important messages, like control messages (new player info, game end etc), and power-up messages etc, and any message that is a once off message.
   If it gets sent Unreliably, it just gets sent out once to the other machine, and no checks are made if it gets there or not. This is good for changes in player speed/direction messages, as you'll may be sending out a min of two per second anyway (as a heartbeat in case of a lag spike, so you stop the player's movement if no packet is received for half a second- to prevent the player going into lava, traps etc accidentally), so it doesn't matter if you lose the odd packet anyway. This has the benefit of halving the bandwidth needed, because you don't need to send the acknowledgements.
   You can send it Client-Server (CS) or Peer-To-Peer (PTP) - with Client-Server all data from Clients (Players), goes through the Server first, and then out to other Clients. With Peer-To-Peer, you can send data from any Client to any Client (including the Server). So game data could be sent by CS, and say personal chat data, could be sent out PTP at the same time. Check out `Get Incoming Game Data' in .Main (in Case #REL_UNOR_CS_PACKET, and Case #UNREL_CS_PACKET) for an example of passing on Client data through the Server, as it's not done automatically by my functions (so you can check for collisions, cheating etc first). Note: you can send game data #PEER_TO_PEER if you want, even if the game's #CLIENT_SERVER (and vice-versa)- the `protocol' variable set on login, is a guide only on the protocol used by the game- it doesn't force data to be sent any way.
   Also it can be sent Ordered or Unordered; Ordered is if you want the packet to arrive in order or not (with other ordered packets). This is only for Reliable packets, as it wouldn't make any sense to have Ordered Unreliable packets! Ordered, is important if you are sending keyboard presses instead of player speeds/directions for example (or large files that have to be split over several packets (packets usually hold about 1.5k each)). Unordered is faster, as your packets aren't delayed if an earlier packet is delayed or lost. Currently, only Unordered is supported.
   To send messages Reliably you just call the function: Send_Reliable_Message(address.l,data_length.w,player.w,gathered.w)
   The address is the starting address of your data, data_length is the length of your data, player is which player number you want to send it to, gathered is wether you want the packet gathered into one big one at the Server or not -currently not supported- just set to #UNGATHERED for the present.
   So data can be sent four different ways at present:
   #REL_UNOR_PTP_PACKET ; Reliably and Peer-To-Peer
   #REL_UNOR_CS_PACKET ; Reliably and Client-Server
   #UNREL_PTP_PACKET ; Unreliably and Peer-To-Peer
   #UNREL_CS_PACKET ; Unreliably and Client-Server
   To send messages unreliably call the function: Send_Unreliable_Message(address.l,data_length.w,player,protocol.w,gathered.w)
   The parameters are the same as above (Protocol can be either #CLIENT_SERVER or #PEER_TO_PEER), but packets are only sent as unordered, as there's no point sending ordered unreliable packets.
   For examples see the `Send string to other players' (Case 64 in the gadgets Case-Select) Case, in the Window_Events() Function. It shows how to send a string, but any block of memory can be sent.
   To get data sent by another program, check out `Get Incoming Game Data' in Main:. The Function Get_Game_Data() returns a pointer to a buffer which contains the data from the incoming packet. The first word (.w) contains the size of the data, and the second word contains wether the packet was Reliable or Unreliable. The actual data starts on the next byte (5th byte).
   You can get system information from the Get_Comms_System_Information{}
function. This gives back information that can be printed out, or reacted to
by your program. It gives back a pointer to the current message in the
information buffer, or zero if there are no more messages. The data it
points to is a long int, which is a code for the information given. Depending
on the information, it can have up to five bits of information (long ints)
that go with the type of information, so more detail can be given.
   The function Process_Comms_Information{} is set up to deal with
all messages- also see General_Housekeeping{} to see how
Process_Comms_Information{} is called. You can add in your own messages
to the buffer with Add_Comms_System_Information{} (and add in how they're
handled in Process_Comms_Information{}), so your custom messages can be
handled by the main system, saving you having to create an extra system. Also,
you could easily add in localisation, for the language the messages are
printed out in.
   You will have to regularly clear the messages (I suggest once per
frame), or the buffer will overflow and you will lose messages- you will get
a message informing you of this. You can increase the size of the buffer with
the #INTERNAL_MESSAGE_SIZE constant at the top of the program.
   To have Debug information printed out you have to have the constant #COMMS_DEBUG=1 (at the top of the UDP stuff, at the top of the page). To test the time sync routines set #TEST_TIME_SYNC=1, just below it- note, it only works if #COMMS_DEBUG=1. If you don't want them, set them to 0.