コード例 #1
0
void PrintBTree	( BTree <char *> *btree )
{

	UplinkAssert ( btree );

	DArray <char *> *uo = btree->ConvertToDArray ();
	DArray <char *> *uo_id = btree->ConvertIndexToDArray ();

	for ( int i = 0; i < uo->Size (); ++i ) {
		if ( uo->ValidIndex (i) ) {
			
			UplinkAssert ( uo_id->ValidIndex (i) );
			printf ( "Index = %s\n", uo_id->GetData (i) );

			if ( uo->GetData (i) )
				printf ( "%s\n", uo->GetData (i) );

			else
				printf ( "NULL\n" );

		}
	}

	delete uo;
	delete uo_id;

}
コード例 #2
0
void SaveBTree  ( BTree <UplinkObject *> *btree, FILE *file )
{

	UplinkAssert ( btree );

	DArray <UplinkObject *> *uo = btree->ConvertToDArray ();
	DArray <char *> *uo_id = btree->ConvertIndexToDArray ();

	int size = uo->Size ();

	int nbitem = 0;
	for ( int i = 0; i < size; ++i )
		if ( uo->ValidIndex (i) )
			nbitem++;

	if ( nbitem > MAX_ITEMS_DATA_STRUCTURE ) {
		UplinkPrintAbortArgs ( "WARNING: SaveBTree, number of items appears to be too big, size=%d, maxsize=%d",
		                       nbitem, MAX_ITEMS_DATA_STRUCTURE );
		nbitem = MAX_ITEMS_DATA_STRUCTURE;
	}

	fwrite ( &nbitem, sizeof(nbitem), 1, file );

	nbitem = 0;
	for ( int i = 0; i < size && nbitem < MAX_ITEMS_DATA_STRUCTURE; ++i ) {
		if ( uo->ValidIndex (i) ) {

			UplinkAssert ( uo_id->ValidIndex (i) );
			UplinkAssert ( uo->GetData (i) );

			SaveDynamicString ( uo_id->GetData (i), file );

			int OBJECTID = uo->GetData (i)->GetOBJECTID ();
			UplinkAssert ( OBJECTID != 0 );
			fwrite ( &OBJECTID, sizeof(int), 1, file );			

			uo->GetData (i)->Save ( file );

			nbitem++;

		}
	}

	delete uo;
	delete uo_id;

}
コード例 #3
0
ファイル: eclipse.cpp プロジェクト: gene9/uplink-source-code
void EclSuperUnHighlightAll	()
{

	DArray <char *> *highlights = superhighlightedbuttons.ConvertIndexToDArray ();

	for ( int i = 0; i < highlights->Size (); ++i )
		if ( highlights->ValidIndex (i) )
			EclSuperUnHighlight ( highlights->GetData (i) );

}
コード例 #4
0
void InterfaceScreen::Remove ()
{
	DArray<char *> *btns = this->interface_buttons;
	for ( int i = 0; i < btns->Size(); ++i ) {
		if ( btns->ValidIndex( i ) ) {
			char *btn_name = btns->GetData( i );
			if ( (NULL != btn_name) && ('\0' != btn_name[0]) )
				EclRemoveButton( btn_name );
		}
	}
}
コード例 #5
0
static
bool DirectoryEqual( DArray<T *> const &_a, DArray<T *> const &_b )
{
	int size = max( _a.Size(), _b.Size() );

	for( int i = 0; i < size; i++ )
	{
		bool aValid = _a.ValidIndex( i ),
			 bValid = _b.ValidIndex( i );

		if( aValid != bValid )
			return false;

		if( aValid && bValid &&
			!(*_a.GetData( i ) == *_b.GetData( i )) )
			return false;
	}

	return true;
}
コード例 #6
0
void DeleteBTreeData ( BTree <UplinkObject *> *btree )
{

	UplinkAssert ( btree );

	DArray <UplinkObject *> *uo = btree->ConvertToDArray ();

	for ( int i = 0; i < uo->Size (); ++i )
		if ( uo->ValidIndex (i) )
			if ( uo->GetData (i) )				
				delete uo->GetData (i);

	delete uo;	

}
コード例 #7
0
void LanguageTable::ClearBaseLanguage()
{
    DArray<char *> *base = m_baseLanguage.ConvertToDArray();

    for( int i = 0; i < base->Size(); ++i )
    {
        if( base->ValidIndex(i) )
        {
            char *data = base->GetData(i);
            delete data;
        }
    }

    delete base;
    m_baseLanguage.Empty();
}
コード例 #8
0
void LanguageTable::ClearTranslation()
{
    DArray<char *> *translation = m_translation.ConvertToDArray();
    
    for( int i = 0; i < translation->Size(); ++i )
    {
        if( translation->ValidIndex(i) )
        {
            char *data = translation->GetData(i);
            delete data;
        }
    }

    delete translation;
    m_translation.Empty();
}
コード例 #9
0
void DeleteBTreeData ( BTree <char *> *btree )
{

	UplinkAssert ( btree );

	DArray <char *> *uo = btree->ConvertToDArray ();

	for ( int i = 0; i < uo->Size (); ++i )
		if ( uo->ValidIndex (i) )
			if ( uo->GetData (i) )
				// Even zero length string need to be deleted
				//if ( strcmp ( uo->GetData (i), "" ) != 0 )
					delete [] uo->GetData (i);

	delete uo;	

}
コード例 #10
0
void LanguageTable::LoadTranslation(char *_filename)
{
    LoadLanguage( _filename, m_translation );

#ifdef _DEBUG
    DArray<char *> *keys = m_baseLanguage.ConvertIndexToDArray();

    for( int i = 0; i < keys->Size(); ++i )
    {
        if( keys->ValidIndex(i) )
        {
            char *key = keys->GetData(i);
			if( !m_translation.GetData( key ) )
			{
				AppDebugOut( "Warning : base language key '%s' with no translation in language file %s\n", key, _filename );
			}
        }
    }

    delete keys;
#endif
}
コード例 #11
0
ファイル: matchmaker.cpp プロジェクト: cahocachi/DEFCON
int GetListenerIndex( NetSocketListener *_listener )
{
    s_listenersMutex.Lock();

    int index = -1;

    for( int i = 0; i < s_listeners.Size(); ++i )
    {
        if( s_listeners.ValidIndex(i) )
        {
            MatchMakerListener *listener = s_listeners[i];
            if( listener->m_listener == _listener )
            {
                index = i;
            }
        }
    }

    s_listenersMutex.Unlock();

    return index;
}
コード例 #12
0
ファイル: file_system.cpp プロジェクト: cahocachi/DEFCON
// Finds all the filenames in the specified directory that match the specified
// filter. Directory should be like "textures" or "textures/".
// Filter can be NULL or "" or "*.bmp" or "map_*" or "map_*.txt"
// Set _longResults to true if you want results like "textures/blah.bmp" 
// or false for "blah.bmp"
LList<char *> *FileSystem::ListArchive(char *_dir, char *_filter, bool fullFilename)
{
    LList<char *> *results = NULL;

    //
    // List the search directories

    for( int i = 0; i < m_searchPath.Size(); ++i )
    {
        char searchPathFilename[512];
        snprintf( searchPathFilename, sizeof(searchPathFilename), "%s%s", m_searchPath[i], _dir );
        searchPathFilename[ sizeof(searchPathFilename) - 1 ] = '\x0';
        LList<char *> *results2 = ListDirectory( searchPathFilename, _filter, fullFilename );
        if( !results )
        {
            results = results2;
        }
        else
        {
            ListArchiveFilterResults( results, results2 );
            results2->EmptyAndDelete();
            delete results2;
        }
    }


    //
    // List the localisation directory

    char localisationFilename[512];
    snprintf( localisationFilename, sizeof(localisationFilename), "localisation/%s", _dir );
    localisationFilename[ sizeof(localisationFilename) - 1 ] = '\0';
    LList<char *> *results3 = ListDirectory( localisationFilename, _filter, fullFilename );
    if( !results )
    {
        results = results3;
    }
    else
    {
        ListArchiveFilterResults( results, results3 );
        results3->EmptyAndDelete();
        delete results3;
    }


    //
    // List the base data directory

    LList<char *> *results4 = ListDirectory( _dir, _filter, fullFilename );
    ListArchiveFilterResults( results, results4 );
    results4->EmptyAndDelete();
    delete results4;


    //
    // List the pre-loaded resource files

    if (m_archiveFiles.Size() > 0)
    {
        if(_filter == NULL || _filter[0] == '\0')
        {
            _filter = "*";
        }

        DArray <char *> *unfilteredResults = m_archiveFiles.ConvertIndexToDArray();

        for (int i = 0; i < unfilteredResults->Size(); ++i)
        {
            if (!unfilteredResults->ValidIndex(i)) continue;

            char *fullname = unfilteredResults->GetData(i);
            char *dirPart = (char *) GetDirectoryPart( fullname );
            if( stricmp( dirPart, _dir ) == 0 )
            {
                char *filePart = (char *) GetFilenamePart( fullname );
                int result = WildCmp(_filter, filePart);
                if (result != 0)
                {
                    if( !fullFilename )  OrderedInsert(results, filePart);
                    else                 OrderedInsert(results, fullname);
                }
            }
        }

        delete unfilteredResults;
    }

    return results;
}
コード例 #13
0
ファイル: matchmaker.cpp プロジェクト: cahocachi/DEFCON
static NetCallBackRetType RequestIdentityThread(void *ignored)
{
#ifdef WAN_PLAY_ENABLED
    NetSocketListener *listener = (NetSocketListener *) ignored;
    
    int listenerIndex = GetListenerIndex(listener);
    AppAssert( listenerIndex > -1 );
    
    s_listenersMutex.Lock();
    MatchMakerListener *_listener = s_listeners[listenerIndex];
    AppAssert(_listener);
    s_listenersMutex.Unlock();


    //
    // Generate a uniqueID for this request
    // So we can tell the replies apart

    s_uniqueRequestMutex.Lock();
    int uniqueId = s_uniqueRequestid;
    ++s_uniqueRequestid;
    s_uniqueRequestMutex.Unlock();

    _listener->m_uniqueId = uniqueId;


    //
    // Build our request and convert to a byte stream
    // (only need to do this once and keep re-sending)

    Directory request;
    request.SetName( NET_MATCHMAKER_MESSAGE );
    request.CreateData( NET_METASERVER_COMMAND, NET_MATCHMAKER_REQUEST_IDENTITY );
    request.CreateData( NET_MATCHMAKER_UNIQUEID, uniqueId );
    

    //
    // Open a connection to the MatchMaker service
    // Start sending requests for our ID every few seconds
    // to ensure the connection stays open in the NAT 

    NetSocketSession socket( *listener, s_matchMakerIp, s_matchMakerPort );


    while( true )
    {
        //
        // Stop if We've been asked to 

        if( _listener->m_shutDown )
        {
            break;
        }


        //
        // Update the request with the latest auth data
        
        Directory *clientProps = MetaServer_GetClientProperties();
        request.CreateData( NET_METASERVER_GAMENAME,    clientProps->GetDataString(NET_METASERVER_GAMENAME) );
        request.CreateData( NET_METASERVER_GAMEVERSION, clientProps->GetDataString(NET_METASERVER_GAMEVERSION) );
        request.CreateData( NET_METASERVER_AUTHKEY,     clientProps->GetDataString(NET_METASERVER_AUTHKEY) );
        delete clientProps;

        int requestSize = 0;
        char *requestByteStream = request.Write(requestSize);


        //
        // Send the request

        int numBytesWritten = 0;
        NetRetCode result = socket.WriteData( requestByteStream, requestSize, &numBytesWritten );
        delete [] requestByteStream;

        if( result != NetOk || numBytesWritten != requestSize )
        {
            AppDebugOut( "MatchMaker encountered error sending data\n" );
            break;
        }

        NetSleep( PERIOD_MATCHMAKER_REQUESTID );
    }


    //
    // Shut down the request


    s_listenersMutex.Lock();
    
    if( s_listeners.ValidIndex(listenerIndex) &&
        s_listeners[listenerIndex] == _listener )
    {
        s_listeners.RemoveData(listenerIndex);
    }
    
    s_listenersMutex.Unlock();
    delete _listener;

#endif

    return 0;
}
コード例 #14
0
ファイル: matchmaker.cpp プロジェクト: cahocachi/DEFCON
bool MatchMaker_ReceiveMessage( NetSocketListener *_listener, Directory *_message )
{
    AppAssert( _message );
    AppAssert( strcmp(_message->m_name, NET_MATCHMAKER_MESSAGE) == 0 );
    AppAssert( _message->HasData( NET_METASERVER_COMMAND, DIRECTORY_TYPE_STRING ) );

    char *cmd = _message->GetDataString( NET_METASERVER_COMMAND );

    if( strcmp( cmd, NET_MATCHMAKER_IDENTIFY ) == 0 )
    {
        //
        // This message contains the external IP and port of one of our connections

        if( !_message->HasData( NET_MATCHMAKER_UNIQUEID, DIRECTORY_TYPE_INT ) ||
            !_message->HasData( NET_MATCHMAKER_YOURIP, DIRECTORY_TYPE_STRING ) ||
            !_message->HasData( NET_MATCHMAKER_YOURPORT, DIRECTORY_TYPE_INT ) )
        {
            AppDebugOut( "MatchMaker : Received badly formed identity message, discarded\n" );
        }
        else
        {
            int uniqueId = _message->GetDataInt( NET_MATCHMAKER_UNIQUEID );
            
            s_listenersMutex.Lock();
            for( int i = 0; i < s_listeners.Size(); ++i )
            {
                if( s_listeners.ValidIndex(i) )
                {
                    MatchMakerListener *listener = s_listeners[i];
                    if( listener->m_uniqueId == uniqueId )
                    {
                        if( !listener->m_identified )
                        {                        
                            listener->m_ip = strdup( _message->GetDataString(NET_MATCHMAKER_YOURIP) );
                            listener->m_port = _message->GetDataInt(NET_MATCHMAKER_YOURPORT);
                            listener->m_identified = true;
                            AppDebugOut( "Socket %d identified as public IP %s:%d\n", 
                                            listener->m_listener->GetBoundSocketHandle(), listener->m_ip, listener->m_port );
                        }
                        break;
                    }
                }
            }
            s_listenersMutex.Unlock();
        }
    }
    else if( strcmp( cmd, NET_MATCHMAKER_REQUEST_CONNECT ) == 0 )
    {
        //
        // This is a request from a client for the server to set up a UDP hole punch
        
        if( !_message->HasData( NET_METASERVER_IP, DIRECTORY_TYPE_STRING ) ||
            !_message->HasData( NET_METASERVER_PORT, DIRECTORY_TYPE_INT ) )
        {
            AppDebugOut( "MatchMaker : Received badly formed connection request, discarded\n" );
        }
        else
        {
            char *ip = _message->GetDataString( NET_METASERVER_IP );
            int port = _message->GetDataInt( NET_METASERVER_PORT );

            AppDebugOut( "MatchMaker : SERVER Received request to allow client to join from %s:%d\n", ip, port );

            Directory dir;
            dir.SetName( NET_MATCHMAKER_MESSAGE );
            dir.CreateData( NET_METASERVER_COMMAND, NET_MATCHMAKER_RECEIVED_CONNECT );

            NetSocketSession session( *_listener, ip, port );            
            MetaServer_SendDirectory( &dir, &session );
        }
    }
    else if( strcmp( cmd, NET_MATCHMAKER_RECEIVED_CONNECT ) == 0 )
    {
        AppDebugOut( "MatchMaker : CLIENT received confirmation from Server that Hole Punch is set up\n" );
    }
    else
    {
        AppAbort( "unrecognised matchmaker message" );
    }

    return true;
}
コード例 #15
0
ファイル: eclipse.cpp プロジェクト: gene9/uplink-source-code
void EclUpdateAllAnimations ()
{

	int i;


	//
	// Update all super-highlighted buttons
	//

	DArray <char *> *superhighlighted = superhighlightedbuttons.ConvertIndexToDArray ();

	for ( i = 0; i < superhighlighted->Size (); ++i )
		if ( superhighlighted->ValidIndex (i) )
			EclUpdateSuperHighlights ( superhighlighted->GetData (i) );

	delete superhighlighted;


	//
	// Update all animations
	//

	for ( i = 0; i < anims.Size (); ++i ) {

		if ( anims.ValidIndex (i) ) {

			Animation *anim = anims [i];
			assert ( anim );
			
			// Button may have been deleted - attempt to re-aquire it here
			anim->button = EclGetButton ( anim->buttonname );
			
			if ( !anim->button ) {

				// This button has been destroyed - remove the anim
#ifdef _DEBUG
				printf ( "ECL WARNING : Animation defined on invalid button : %s\n", anim->buttonname );
#endif

                EclRemoveAnimation ( i );

			}
			else {
							
				EclDirtyButton ( anim->buttonname );

				if ( EclGetAccurateTime () >= anim->finishtime || !animsenabled ) {

					// Animation has finished - set to final position / size / caption
					// OR Animations are not enabled - set to final position as well

					if ( anim->dX || anim->dY ) {

						EclDirtyRectangle ( anim->button->x, anim->button->y, anim->button->width, anim->button->height );		

						anim->button->x = anim->targetX;
						anim->button->y = anim->targetY;						
						
					}

					if ( anim->dW || anim->dH ) {

						EclDirtyRectangle ( anim->button->x, anim->button->y, anim->button->width, anim->button->height );		

						anim->button->width = anim->targetW;
						anim->button->height = anim->targetH;						

					}

					if ( anim->dC ) {

						anim->button->SetCaption ( anim->targetC );

					}

					// Update any SuperHighlights that exist on this button

					if ( EclIsSuperHighlighted ( anim->buttonname ) )
						EclUpdateSuperHighlights ( anim->buttonname );
						
					// Call the callback if neccesary
					if ( anim->callback ) anim->callback ();

					// Remove the animation from the list
                    EclRemoveAnimation ( i );

				}
				else {

					if ( anim->MOVETYPE == MOVE_STRAIGHTLINE ) {

						// Button moves at a constant rate in a straight line to target

						if ( anim->dX || anim->dY ) {
							
							int dX = (int)(anim->sourceX + ( EclGetAccurateTime () - anim->starttime ) * anim->dX) - anim->button->x;
							int dY = (int)(anim->sourceY + ( EclGetAccurateTime () - anim->starttime ) * anim->dY) - anim->button->y;

							//EclDirtyRectangle ( anim->button->x, anim->button->y, dX, anim->button->height );		
							EclDirtyRectangle ( anim->button->x, anim->button->y, anim->button->width, anim->button->height );		

							// Buttons location can change
							// Calculate location of button
							anim->button->x = anim->sourceX + (int)(( EclGetAccurateTime () - anim->starttime ) * anim->dX);
							anim->button->y = anim->sourceY + (int)(( EclGetAccurateTime () - anim->starttime ) * anim->dY);							
// 							double now = EclGetAccurateTime();
// 							double f = ( now - anim->starttime ) / (anim->finishtime - anim->starttime);
// 							anim->button->x = anim->sourceX + (anim->targetX - anim->sourceX) * f;
// 							anim->button->y = anim->sourceY + (anim->targetY - anim->sourceY) * f;
						}
					
					}
					else if ( anim->MOVETYPE == MOVE_XFIRST ) {

						// Button moves in X direction, then in Y direction

						if ( anim->dX || anim->dY ) {

							EclDirtyRectangle ( anim->button->x, anim->button->y, anim->button->width, anim->button->height );		
						
							float ratio = (anim->dX / (anim->dX + anim->dY));
							int halftime = anim->starttime + (int)(ratio * (anim->finishtime - anim->starttime));

							if ( EclGetAccurateTime () < halftime ) {
								float firsthalf = (float) ( EclGetAccurateTime () - anim->starttime ) / (float) ( halftime - anim->starttime );
								anim->button->x = anim->sourceX + (int)((anim->targetX - anim->sourceX) * firsthalf);
							}
							else {
								float secondhalf = (float) ( EclGetAccurateTime () - halftime ) / (float) ( anim->finishtime - halftime );
								anim->button->x = anim->targetX;
								anim->button->y = anim->sourceY + (int)((anim->targetY - anim->sourceY) * secondhalf);
							}

						}

					}
					else if ( anim->MOVETYPE == MOVE_YFIRST ) {

						// Button moves in Y direction, then in X direction

						if ( anim->dX || anim->dY ) {
						
							EclDirtyRectangle ( anim->button->x, anim->button->y, anim->button->width, anim->button->height );		

							float ratio = (anim->dY / (anim->dX + anim->dY));
							int halftime = anim->starttime + (int)(ratio * (anim->finishtime - anim->starttime));

							if ( EclGetAccurateTime () < halftime ) {
								float firsthalf = (float) ( EclGetAccurateTime () - anim->starttime ) / (float) ( halftime - anim->starttime );
								anim->button->y = anim->sourceY + (int)((anim->targetY - anim->sourceY) * firsthalf);
							}
							else {
								float secondhalf = (float) ( EclGetAccurateTime () - halftime ) / (float) ( anim->finishtime - halftime );
								anim->button->y = anim->targetY;
								anim->button->x = anim->sourceX + (int)((anim->targetX - anim->sourceX) * secondhalf);
							}

						}					

					}

					if ( anim->dW || anim->dH ) {

						// Buttons size can change
						// Calculate new size
						EclDirtyRectangle ( anim->button->x, anim->button->y, anim->button->width, anim->button->height );		

						anim->button->width = anim->sourceW + (int)(( EclGetAccurateTime () - anim->starttime ) * anim->dW);
						anim->button->height = anim->sourceH + (int)(( EclGetAccurateTime () - anim->starttime ) * anim->dH);

					}

					if ( anim->dC ) {

						// Buttons caption can change
						size_t showlength = (size_t)( ( (float)EclGetAccurateTime () - anim->starttime ) * anim->dC );
						char *caption = new char [strlen(anim->targetC)+1];
						strcpy ( caption, anim->targetC );
						if ( showlength < strlen(anim->targetC)+1 )
                                                    caption [showlength] = 0;
						anim->button->SetCaption ( caption );
						delete [] caption;

					}

					// Update any SuperHighlights that exist on this button

					if ( EclIsSuperHighlighted ( anim->buttonname ) )
						EclUpdateSuperHighlights ( anim->buttonname );

				}

			}

		}

	}

}
コード例 #16
0
void LanguageTable::TestTranslation( char *_logFilename )
{
    //
    // Open the errors file

    FILE *output = fopen( _logFilename, "wt" );
    AppReleaseAssert( output, "Failed to open logfile %s", _logFilename );
    
    
    //
    // Look for strings in the base that are not in the translation
    
    DArray<char *> *basePhraseIndex = m_baseLanguage.ConvertIndexToDArray();
    DArray<char *> *basePhrases = m_baseLanguage.ConvertToDArray();

    for( int i = 0; i < basePhraseIndex->Size(); ++i )
    {
        if( basePhraseIndex->ValidIndex(i) )
        {
            char *baseIndex = basePhraseIndex->GetData(i);
            char *basePhrase = basePhrases->GetData(i);

            if( !DoesTranslationExist( baseIndex ) )
            {
                fprintf( output, "ERROR : Failed to find translation for string ID '%s'\n", baseIndex );
            }
            else
            {
                char *translatedPhrase = m_translation.GetData( baseIndex );
                if( strcmp( basePhrase, translatedPhrase ) == 0 )
                {
                    fprintf( output, "Warning : String ID appears not to be translated : '%s'\n", baseIndex );
                }
            }
        }
    }

    delete basePhraseIndex;
    delete basePhrases;


    //
    // Look for phrases in the translation that are not in the base

    DArray<char *> *translatedIndex = m_translation.ConvertIndexToDArray();

    for( int i = 0; i < translatedIndex->Size(); ++i )
    {
        if( translatedIndex->ValidIndex(i) )
        {
            char *index = translatedIndex->GetData(i);

            if( !DoesPhraseExist( index ) )
            {
                fprintf( output, "Warning : Found new string ID not present in original English : '%s'\n", index );               
            }
        }
    }

    delete translatedIndex;

    
    //
    // Clean up
    
    fclose( output );
}
コード例 #17
0
void UserIDScreenInterface::Create ( ComputerScreen *newcs )
{

	UplinkAssert ( newcs );
	cs = newcs;

	if ( !IsVisible () ) {

		EclRegisterButton ( 130, 90, 320, 25, GetComputerScreen ()->maintitle, "", "useridscreen_maintitle" );
		EclRegisterButtonCallbacks ( "useridscreen_maintitle", DrawMainTitle, NULL, NULL, NULL );
		EclRegisterButton ( 130, 110, 320, 20, GetComputerScreen ()->subtitle, "", "useridscreen_subtitle" );
		EclRegisterButtonCallbacks ( "useridscreen_subtitle", DrawSubTitle, NULL, NULL, NULL );

		EclRegisterButton ( 168, 155, 220, 120, "", "", "useridscreen_image" );
		button_assignbitmap ( "useridscreen_image", "userid.tif" );
		EclRegisterButtonCallbacks ( "useridscreen_image", imagebutton_draw, CodeButtonClick, button_click, button_highlight );

		EclRegisterButton ( 227, 210, 148, 15, "", "Enter your userID here", "useridscreen_name" );
		EclRegisterButtonCallbacks ( "useridscreen_name", UserIDButtonDraw, CodeButtonClick, button_click, button_highlight );

		EclRegisterButton ( 227, 236, 148, 15, "", "Enter your access code here", "useridscreen_code" );
		EclRegisterButtonCallbacks ( "useridscreen_code", CodeButtonDraw, CodeButtonClick, button_click, button_highlight );

		EclRegisterButton ( 168, 280, 120, 15, "", "", "useridscreen_message" );
		EclRegisterButtonCallbacks ( "useridscreen_message", textbutton_draw, NULL, NULL, NULL );

		EclRegisterButton ( 308, 280, 80, 15, "Proceed", "Click here when done", "useridscreen_proceed" );
		button_assignbitmaps ( "useridscreen_proceed", "proceed.tif", "proceed_h.tif", "proceed_c.tif" );
		EclRegisterButtonCallback ( "useridscreen_proceed", ProceedClick );

		EclMakeButtonEditable ( "useridscreen_name" );
		EclMakeButtonEditable ( "useridscreen_code" );

		// Create the box that will show the currently known codes for this screen

		UplinkAssert ( cs->GetComputer () );

		if ( game->GetWorld ()->GetPlayer ()->codes.LookupTree ( cs->GetComputer ()->ip ) ) {

			DArray <char *> *codes = game->GetWorld ()->GetPlayer ()->codes.ConvertToDArray ();
			DArray <char *> *ips   = game->GetWorld ()->GetPlayer ()->codes.ConvertIndexToDArray ();

			EclRegisterButton ( 200, 310, 250, 15, "Known Access Codes", "", "useridscreen_codestitle" );
			EclRegisterButtonCallbacks ( "useridscreen_codestitle", textbutton_draw, NULL, NULL, NULL );

			int currentcode = 0;

			for ( int i = 0; i < codes->Size (); ++i ) {
				if ( codes->ValidIndex (i) && ips->ValidIndex (i) ) {
					if ( strcmp ( ips->GetData (i), cs->GetComputer ()->ip ) == 0 ) {

						char name [64];
						UplinkSnprintf ( name, sizeof ( name ), "useridscreen_code %d", currentcode );
						EclRegisterButton ( 200, 330 + currentcode*15, 250, 15, codes->GetData (i), "Use this code", name );
						EclRegisterButtonCallbacks ( name, textbutton_draw, AccessCodeClick, button_click, button_highlight );
						++currentcode;

					}
				}
			}

			delete codes;
			delete ips;

		}

#ifdef CHEATMODES_ENABLED
		// Create a symbol for quick entry into this screen
		EclRegisterButton ( 3, 20, 30, 15, "#", "Click here to bypass this screen (DEBUG MODE ONLY)", "useridscreen_bypass" );
		EclRegisterButtonCallbacks ( "useridscreen_bypass", textbutton_draw, BypassClick, button_click, button_highlight );
#endif

	}

}