Introduction

This document is still under construction.

Last update: February 03, by CJP

Description of features

Ultimate Stunts should provide some kind of file transfer, because sometimes, in a multiplayer session, one or more players does not have all required files. The server program should have these, and the clients should be able to get these from the server.

As Ultimate Stunts should be able to run on many different platforms, we have decided not to use an existing file transfer system. Instead, we will design our own (simple) protocol, and integrate it with the other Ultimate Stunts network communication.

The interface of the filetransfer-protocol code to the other parts of the code should be easy-to-use. It would be perfect if e.g. the track-loading code would look like it just loads the files using a file-class, while the file-class (when the file doesn't exist locally) automatically downloads it.

A file should be (down)loaded when the (track-)loading routine feels the need to load that file. In order to simplify the network protocol, it is preferred to download just one file at a time. The downloading of a second file should only be started when the first file-transfer is finished. On the other hand, multiple file loading requests may exist at the same time. For example, while the reading of the track-file is not finished, the track loader discovers that it needs to load tile files and texture files.

A solution to this could be the following: When a file is requested, the first thing being checked is if the file exists on the local filesystem. If so, the file is just being loaded from the disk. If not, then the file will be downloaded completely, and saved to the disk. Then, the file is being loaded from the disk.

Another probem is how to tell the file-objects how they can download. This could be different in different situatons: we can have different hostnames and portnumbers, and sometimes it is impossible to download, e.g. when the program is not connected to a server, or when the program is the server itself.

I don't want to put a network-object in the constructor of every file-object. This would require every loading routine to know about the network, which makes the program complicated. Instead, we could put some stuff in the implementation-file of the file-class, which is shared between all file-objects. This shared stuff could be controlled by a control-class, who's implementation lies in the same file as the file-class implementation.

Classes

CFile

CFile the class that should be used for all file-loading with download-support. It is also possible to write to files with CFile. If files are loaded outside CFile (e.g. library calls for loading sounds or textures), then the check(..) method should be called. This method checks if a file exists, and downloads it if possible.

Methods+properties: Uses:

CFileCtrl

CFileCtrl is a base-class for classes that are able to control download behaviour. CFileCtrl is implemented in the same file as CFile, but derived classes can be implemented outside this file. They can use the protected member function setDownloadFunc(..) to set a download function. CClientNet is derived from CFileCtrl, and as such it is able to use setDownloadFunc.

Methods+properties:

Implementation

As the implementation might be complicated, I'll try to mak an example of cfile.cpp below.

//cfile.cpp

#include <stdio.h>
#include "cfile.h"
#include "filectrl.h"
#include "usmacros.h"

#define IS_SET 123456
#define NOT_SET 0
bool (CALLBACKFUN *download)(CString);
int download_set; //Warning: uninitialised!

void CFileCtrl::setDownloadFunc( bool (CALLBACKFUN *func)(CString) )
{
	download = func;
	download_set = IS_SET; //Ugly solution!!!
}

bool CFile::check(CString filename)
{
	if exists(filename) //exists could e.g. be a CFile member
		{return true;}
	else if(download_set == IS_SET)
		{return download(filename);}
}

bool CFile::open(CString filename, bool write)
{
	if(write)
		{return open_write();}
	else
	{
		bool good = check(filename);
		if(!good) return false;
		return open_read();
	}
	return false; //Never happens, just to prevent compiler-warning
}

//Etc. : all other member functions