Named Objects Library

From TrainzOnline
Jump to: navigation, search
Surveyor's Hotkeys
Driver's Hotkeys
Notations
Glossary

Contents

 


Named Objects Library (SP2 and later)

NamedObjectsLib.jpg



The Named Objects Library is a 3rd party script library that may be used to manage information about available named objects in the current session. The library can manage cached data for several common objects type, which can be individually asynchronously refreshed in the background using internal threads inside the library, and can return at any time synchronously the content of any of the managed caches.

Usually, an asset using the Named Objects Library will first load and initialize the library in its init routine, will then register the objects type to be cached in the library (which will immediately start the asynchronous process of collecting the cached data for this object type), and will later use the cached data by calling the library to retrieve the current cached data. The library uses all the new object search API available since Tane SP2 and will automaticly refresh in the background any expired cache data in both surveyor and driver mode.

Named Objects Library has been designed and developped to support the new search request Tane SP2 API for all the assets by pguy. It is not a general purpose API interface but an adapted interface to make Tane SP2 migration easy for pguy's assets. The API is now published and public, as it may be interesting for some other scripters that have not already done this migration to use this library for their own migration to the new interfaces.


The present article is for scripters who wants to use the Named Objects Library and give details below on how to configure an asset to use the Named Objects Library, on how to initialise in an asset the library and on how to register the objects type you want to cache, and finaly on how later to retrieve the current content of a cache for a specific object type.

Named Objects Library : How to use it ?

To use the Named Object Library in any of your assets, you need first to modify its config.txt file to add the Named Objects Library in its kuid table section and in its script include table so that your asset can reference the Named Objects Library to import the Named Object Library API as a static class nochelper contained in nochelper.gs inside the Named Objects Library Asset.

The current Named Objects Library available on DLS is <kuid2:61392:4053:22> [for date 23/10/2020]. There will be in the future new versions to add new cache types and fix any remaining bugs.

Your asset config.txt file should include the following sections to be able to load the Named Objects Library API as nochelper static class :

script-include-table
{
   . . . 
   noclib    <kuid:61392:4053>
   . . .
}

and

kuid-table
{
  . . .
  noclib     <kuid2:61392:4053:22>
  . . .
}

with these two modifications in your asset config.txt file, you should now be able to import the noclib API by adding :

include "nochelper.gs"

to the header in your assets script files needing to call the noclib API

Named Objects Library : How to initialise it ?

Now that we have imported the file "nochelper.gs" in your scripts, all other needed steps will be done by calling some API functions defined in the nochelper static class.


First, you need to initialise the library by calling

public void Init(Asset p_asset) ;

this call is mandatory with p_asset being the current asset that will use the library. You can check that the initialisation has been successfull by calling

public bool IsLibraryAvailable(void) ;

that will return true if the library has been initialised and false if it is not the case. These calls are generally made inside your asset init function but can be located else where as long as they are done before any other call to the library.


For example, your asset init function may look like :

public void Init(Asset p_asset)
{
  . . .
  my asset initialisation code
  . . .
  nochelper.Init(p_asset) ;
  if (!nochelper.IsLibraryAvailable())
    {
      . . .
      my asset error code for noclib not available
      . . .
    }
  . . .
}

Named Objects Library : How to register the objects type you want to be cached by the library

The Named Objects Library currently supports 13 objects type that are defined in nochelper static class as integer values :

public define int NOC_TRACKMARK = 1 ;		// for trackmarks names
public define int NOC_TRACKMARK_LIST = 2 ;	// for trackmark list names
public define int NOC_TRIGGER = 4 ;		// for triggers
public define int NOC_SIGNAL = 8 ;		// for signals
public define int NOC_JUNCTION = 16 ;		// for junctions
public define int NOC_CROSSING = 32 ;		// for crossings
public define int NOC_TCB = 64 ;		// for track circuit block detector
public define int NOC_ITS = 128 ;		// for interlocking towers
public define int NOC_CONSIST = 512 ;		// for trains or consists
public define int NOC_VEHICLE = 1024 ;		// for vehicles
public define int NOC_INDUSTRY = 4096 ;         // for industries
public define int NOC_STATION = 8192 ;		// for passenger stations
public define int NOC_PORTAL = 16384 ;	        // for portals
public define int NOC_SCENERY = 32768 ;         // for any scenery object
public define int NOC_TRC = 32769 ;		// for #TRC objects

A cache in the library is defined by its objects type integer value and by a searchFilter string. After being refreshed, a cache will contain an array of NamedObjectInfo objects containing all available objects matching the cache objects type and whose name begin by the search filter. If the search filter is empty (blank string) all the objects matching the cache objects type are returned.

To add an object type and searchFilter to be cached by the library, you only need to call one of these functions :

public int AddNamedObjectsTypeToCache(int cacheType, string searchFilter, bool autoupdate, float period, GameObject notifyGameObject) ;		
public int AddNamedObjectsTypeToCache(int cacheType, string searchFilter, bool autoupdate, float period) ;	
public int AddNamedObjectsTypeToCache(int cacheType,GameObject notifyGameObject) ; 													
public int AddNamedObjectsTypeToCache(int cacheType) ;																						
where cacheType defines the type of objects to be cached
      searchfilter is an optional string to limit the search to all objects whose name are prefixed by searchfilter
      autoupdate is now an obsolete bool parameter that will be ignored. autoupdate is always done in both surveyor and driver mode when needed. 
      notifyGameObject is an optional GameObject reference that will receive a message "Noclib","CacheRefreshComplete" when the cached data will be available (Cf RefreshNamedObjectsCache below)


When a AddNamedObjectsTypeToCache call is made to the library, the library checks if there has been already a similar call made earlier by another asset. If it is the case, the library will reuse the already existing cached data array ; if it is not the case it will create the new cached data array. In all cases it will start an implicit refresh cache operation to collect or refresh the available information on the existing objects matching both the cache objects type and the searchfilter prefix. The integer value returned is a sequential number for the implicit refresh operation that can be later used to check if the asynchronous cache refresh operation is complete. The cache refresh operations are optimized by the library. If several cache refresh operations for the same cache type and search filter are pending when the asynchronous refresh thread starts its operation, all the pending cache refresh operations are merged in only one refresh operation notifying all the requesters.


Depending on the number of objects to scan and retrieve in your route, the duration of a cache refresh operation may last from a few miliseconds to several seconds. If you want to be sure that the implicit cache refresh operation is complete, you will need to wait for the "Noclib","CacheRefreshComplete" message to be received by the notifyGameObject and check that the parameter soup included in the message has the expected cache type (cachetype tag), search filter (searchfilter tag) and refresh serial value (refreshserialvalue tag) for the cache refresh operation just being completed. It is also possible to call IsNamedObjectsCacheRefreshComplete described later in this documentation with the cache type, search filter and refresh sequential number to check cache refresh is complete.


Cached data supports the search results expiry notification option included in Tane SP2 and will redo an automatic cache refresh operation if the current cached data expires. This means that adding a new object or renaming or deletion of an existing object will be detected and cached data will be refreshed. There is only a little latency of a few seconds for the cache update before the new cache content is available.


AddNamedObjectsTypeToCache are generally located in the Init function of your asset and you need to make one call for each of the objects type to be cached.


for example, if you want to cache both interlocking towers and consists, you will have in your asset init function :

public void Init(Asset p_asset)
{
  . . .
  my asset initialisation code
  . . .
  nochelper.Init(p_asset) ;
  if (!nochelper.IsLibraryAvailable())
    {
      . . .
      my asset error code for noclib not available
      . . .
    }
  nochelper.AddNamedObjectsTypeToCache(nochelper.NOC_ITS) ;
  nochelper.AddNamedObjectsTypeToCache(nochelper.NOC_CONSIST) ;
}

Named Objects Library : How to retrieve the cached objects

Now that we have added the objects we want to be managed in the cache, the last step is to call the library to retrieve the data currently in the cache

To retrieve the data currently in cache, you will call this function :

public NamedObjectInfo[] GetNamedObjects(int cacheType,string searchFilter) ; // returns named objects cache with filter
public NamedObjectInfo[] GetNamedObjects(int cacheType) ; // returns named objects cache
where cacheType defines the type of objects to be retrieved
      searchfilter is an optional string to limit the search to only objects whose name are prefixed by searchfilter

These calls returns an array of NamedObjectInfo containing all the current data for the target cacheType and searchFilter.

For readers who do not already know NamedObjectInfo class data, NamedObjectInfo class object is a class defined in World.gs that is used to return available data on exisisting objects in a route and session. You will find below its class definition extracted from World.gs :

//=============================================================================
// Name: NamedObjectInfo
// Desc: The result type used by AsyncObjectSearchResult, see below for more.
//=============================================================================
final class NamedObjectInfo
{
  public GameObject   objectRef;          // A reference to the object, if it's loaded
  public GameObjectID objectId;           // The unique ID of the object
  public string       localisedUsername;  // The display name for the object, in the current language
  public string       categoryString;     // The category code string for the object
};

For each object returned, NamedObjectInfo gives you its reference if loaded, its unique GameObjectID, its display name and its category list string for future search.


Take care that reference to the object may be no longer valid if the object has been unloaded since the information was cached, and you should check if the reference is still valid by calling

bool isStillValid = Router.DoesGameObjectStillExist(GameObject obj);

before using the object reference. If the reference is null or is no longer valid, you can retrieve a reference on the object by calling some functions in world.gs using the unique object gameobjectid :

  public native GameObject GetGameObjectByIDIfLoaded(GameObjectID objectID);  will return a GameObject reference if the object is currently loaded and null if it is no longer loaded
  public GameObject SynchronouslyLoadGameObjectByID(GameObjectID objectID) ; will load the gameobject and return the new gameobject reference. This primitive can only be called under a thread


for example, if you want to loop on all existing interlocking towers, you will use the following code :

. . .
NamedObjectInfo[] itInfos = nochelper.GetNamedObjects(nochelper.NOC_ITS) ;
if (itInfos.size())
  for (I=0;i<itInfos.size();I++)
    {
       . . .
       processing to be done on each itInfos
       . . .
    }

Named Objects Library : How to refresh the cached objects

In order to refresh a named objects cache you will call one of these functions :

public int RefreshNamedObjectsCache(int cacheType, string searchFilter, GameObject postGameObject) ; // refresh cached type with post option
public int RefreshNamedObjectsCache(int cacheType, GameObject postGameObject) ; // refresh cached type with post option
public int RefreshNamedObjectsCache(int cacheType) ; // refresh cached type
where cacheType defines the type of objects to be refreshed
      searchfilter is an optional string to limit the search to only objects whose name are prefixed by searchfilter
      postGameObject is an optional GameObject that will be notified that the cache refresh operation is complete by receiving a message "Noclib","CacheRefreshComplete" from the library

The integer value returned is a unique refresh sequential serial number that can be used later to check if the cache refresh operation is complete. If you want to be sure that the cache refresh operation is complete, you will need to wait for the "Noclib","CacheRefreshComplete" message to be received by the postGameObject and check that the parameter soup included in the message has the expected cache type (cachetype tag), search filter (searchfilter tag) and refresh serial value (refreshserialvalue tag) for the cache refresh operation just being completed. It is also possible to call IsNamedObjectsCacheRefreshComplete described later in this documentation with the cache type, search filter and refresh sequential number to check the cache refresh completion.


It is not needed to call RefreshNamedObjectsCache(. . .) just after a AddNamedObjectsToCache(. . .) as the AddNamedObjectsToCache processing includes already an implicit RefreshNamedObjectsCache call to initialise the cached data.


It is also possible to check if a cache refresh is complete by calling one of these functions :

public bool IsNamedObjectsCacheRefreshComplete(int cacheType, string searchFilter, int refreshSerialValue, GameObject postGameObject) ; 
public bool IsNamedObjectsCacheRefreshComplete(int cacheType, string searchFilter, GameObject postGameObject) ;
public bool IsNamedObjectsCacheRefreshComplete(int cacheType, GameObject postGameObject) ;
public bool IsNamedObjectsCacheRefreshComplete(int cacheType, string searchFilter) ;
public bool IsNamedObjectsCacheRefreshComplete(int cacheType) ;
where cacheType and searchFilter defines the cache objects type to be checked
      refreshSerialValue is an integer value identifying the cache refresh operation to check, which has been retuned by a previous RefreshNamedObjectsCache or AddNamedObjectsToCache request.
      postGameObject is an optional GameObject that will be notified that the cache refresh operation is now complete by receiving a message "Noclib","CacheRefreshComplete" from the library
      if the cache refresh operation is still in progress.


Named Objects Library : alternative RetrieveNamedObjects API

The above API is fine for regular recurrent request to retrieve available named objects, and using cache techniques enables to optimize scripts by sharing data between multiple assets and offers synchronous answers to requests that have been pre fetched asynchronously.


But sometimes scripts needs to make a non recurrent request for some specific objects for which caching is not usefull.


The alternative RetrieveNamedObjects API has been added to the Named Objects Library recently (in version 10) for this purpose. You can call it this way, if you are executing under a thread :

public NamedObjectInfo[] RetrieveNamedObjects(int cacheType,string searchFilter,bool searchInCache,bool keepInCache) ;
public NamedObjectInfo[] RetrieveNamedObjects(int cacheType,bool searchInCache,bool keepInCache) ;
public NamedObjectInfo[] RetrieveNamedObjects(int cacheType,string searchFilter) ;
public NamedObjectInfo[] RetrieveNamedObjects(int cacheType) ;
where cacheType is the type of objects you want to retrieve 
      searchFilter is the prefix for the objects to be searched
      searchInCache is a bool option to try to retrieve first the objects in the cached data
      keepInCache is a bool option to update the cached data if a new search request has been done

As you may have guess, these functions can be called even if no objects of cacheType have been added to the named objects cache library. RetrieveNamedObjects needs to be called under a thread. If searchInCache is true, it will first try to find a cache in the library matching cacheType and searchFilter. If it finds one, it will return the current cache data. If it does not find one or if searchInCache is false, it will start a new asynchronous search request for these objects and will wait for the end of this search request. If keepInCache is set to true, it will copy the results to any matching existing cache in the library or will create a new cached data in the library to keep the data in cache for future use. And it will finaly return the results to the caller.


This function may be more easy to use for callers under a thread and for specific request done only once and not recurrent between assets.


public NamedObjectInfo[] RetrieveNamedObjects(int cacheType,string[] searchFilters,bool searchInCache,bool keepInCache) ;
public NamedObjectInfo[] RetrieveNamedObjects(int cacheType,string[] searchFilters) ; 

These functions enables to return in a unique NamedObjectInfo array objects of the same cacheType matching several searchFilters with some results coming from already existing data cached and other results being only new search results not cached.

Named Objects Library : other miscellaneous functions

The nochelper class includes also a few other specific functions :

public NamedObjectInfo[] GetTrackMarksInList(string sList) ;  can be called to retrieve trackmarks belonging to a specific trackmark list. Needs NOC_TRACKMARK_LIST to be currently cached.
                                                              This primitive is needed for DriveToTrackMarkList driver command.
public int GetPlatformsCountForStation(string stationName) ;  can be called to retrieve the number of platforms for a virtual passenger station name. Needs NOC_STATION to be currently cached.
                                                              This primitive is needed for DriveToStation driver command. 
public GameObjectID GetPlatformsStationID(string sVirtualPlatformName); can be called to retrieve the real station GameObjectID for a virtual platform name. Needs NOC_STATION to be currently cached.
                                                              This primitive is needed for DriveToStation driver command. 	
public string GetPlatformsTrack(string sVirtualPlatformName) ; can be called to retrieve the real track name for a virtual platform name. Needs NOC_STATION to be currently loaded
                                                              This primitive is needed for DriveToStation driver command. 

Named Objects Library : example application

To download on the DLS : 'Named Objects Library test' <kuid:458053:102778>. A simple object to put anywhere on a route ; its only purpose is to count the triggers on the 'world', as an illustration of the possibilities of the tool 'Named Objects Library'. You can edit its script and discover how some of the codes exposed above may be implemented.

Please note : the script displays a list of triggers (if any on the route) ; this list may be consulted at the bottom left of the screen, in Driver Mode only.


Personal tools