ugBASIC User Manual

DOJO support

The ugBASIC language is equipped with primitives capable of communicating with an external server, called DOJO, which is a system for creating virtual "game rooms" online. This guide contains information and tutorials to make the best use of this feature, as well as a description of the DOJO protocol

Preparation Services Message Ports

Preparatory activities

In order to use the DOJO protocol features, it is necessary to connect the retrocomputer to a server that implements the protocol. Here you will find some summary instructions on how to do it.

Available services

The DOJO protocol provides a set of commands that are implemented as statements and functions on ugBASIC, and serve to model a set of services.

MESSAGE PORTS

A mechanism for managing ports and messages is set up, and it can be used as elements of asynchronous communication between programs. They are very useful for allowing the management of multiplayer games. The instructions that are available in this mode are:

  • = PING(...) - check if the connection is alive;
  • = CREATE PORT() - it allows to create a port;
  • = [OPEN] PORT(...) - it allows to open an existing port (or to create one);
  • PUT [MESSAGE] ... - it allows to send a message to a port;
  • = PEEK [MESSAGE](...) - it allows to check if a message is available;
  • = GET [MESSAGE](...) - it allows to retrieve any available message;

MESSAGE PORTS FOR BEGINNERS

CREATE A COMMUNICATION PORT


A message port can be thought of as a mailbox. When someone (a program or a user that uses a program) sends a message to a port, it is as if we were asking a postal system to deliver a letter to the mailbox (of another program). The postal service guarantees that the message will be delivered, but of course it cannot guarantee when this will happen. Therefore, the order in which messages arrive may not be the same as the order in which they are sent.

To create a message port simply you have various ways:
  • use the CREATE PORT() function
  • use the OPEN PORT("") function, with an empty string.
This is an example:
portId = CREATE PORT( )

The return value of this instruction is a unique code, which can be used to uniquely identify the specific communication, i.e. the port.

The message port (mailbox) is owned by who knows this specific identifier. Therefore, it is possible to define more than one mailbox (i.e., a port), as long as each of them is identified by a different unique id.

FIND OUT THE PORT


To send a message, we need to know the address of that message port. In DOJO protocol jargon, a message box is identified by a unique identifier, called "port id". So the first useful operation is to find out the port id to use to send the message. The identifier of any created port can be printed with a simple PRINT, to make it clear to the user. It is normally an 8 hexadecimal digit number:

42abc000

So basically just one information is needed to identify that mailbox. To open a message port knowing the unique id, use the [OPEN] PORT(...) function, whose syntax is as follows:

portId = OPEN PORT("unique id")

or
portId = PORT("unique id")



As we mentioned before, it is possible to have multiple channels assigned to a single port: infact, each port "maps" up to 256 independent channels. We will go into this in more detail later, but the important thing to know is that the management of these channels is the responsibility of the ugBASIC program, since in terms of the language and protocol they are all equivalent. A typical solution is to use one channel (e.g. 0) for one direction of communication and another (e.g. 1) for the other.

PUT A MESSAGE TO A PORT

To put a message we can use the PUT [MESSAGE] statement, with the following syntaxes:

PUT [MESSAGE] portId[, channel], message

= PUT [MESSAGE]( portId[, channel], message )


If channel is missing, the default channel will be 0. Moreover, if you use the first form, you are not interested to know if the message has been posted; otherwise, you can check if everything is ok by verifying the return value (TRUE is ok, FALSE otherwise).

Note that if things go wrong, they only go down the communication path between your program and the DOJO server. Once the message has reached the DOJO server, it will be available to another program, even if it is not currently active. So, if the program on the other side of the port is not available, for some reason, the message will be preserved by the DOJO server, and it will be delivered at the first available moment.


WAIT FOR A MESSAGE

Once you have created a port and sent a message, you may wait for a message to arrive to you. As explained in the previous chapters, the port is accessible to anyone who knows its identifier. Therefore, many messages may arrive or none at all. The program that wants to wait for the arrival can use the PEEK MESSAGE command. The syntax is as follows:

= PEEK [MESSAGE]( portId[, channel] )


If channel is missing, the default channel will be 0. If it returns FALSE, it means that the message port is empty; on the contrary, if it returns TRUE, it is possible to fetch the message using the GET [MESSAGE] command. The syntax is:

= GET [MESSAGE]( portId[, channel] )

GET [MESSAGE] portId[, channel], variable

Again, if channel is missing, the default channel will be 0. The second form allows to retrieve any kind of data type, even arrays, up to 256 bytes. Note that the message port behaves like a queue, that is, the first message that is inserted is the first that is retrieved. Therefore, if a program sends three messages in a row to the attention of the channel of a port, the receiving program will receive the three messages in the same order.


Obviously, if several programs do the same thing, the messages will be interspersed but, in the end, they will be in the same order.

Any problem?

If you have found a problem, if you think there is a bug or, more simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.

Thank you!