How to use resource maps ?, Wintermute
.: Publication date 29-June-2004 :: Reads: 1645 :: Review :: Print current page :: Print all:.

In the newest builds the possibility to define resource maps aka hashmaps has been made possible.

What is the purpose of those resource maps ?
They can be used to store a value with a unique key which is useful when using data structures who would be sparsely populated in the form of an array. This is particulary useful if you want to store map data of only some spots of the whole map since you would have to define the whole map grid as an array but only a small fracture of that array would be used for the actual data storage.

The API provided by small is quite simple

/*!
\brief Open a resource map in memory
\author Wintermute
\since 0.82
\param 1 the type of the resource map
\param 2 bool flag if the map should be kept in memory
\param 3 optional filename if the map should be made persistent on disk on worldsave
\return the index of the resource map
\fn createResourceMap( )
*/
native createResourceMap( const type=RESOURCEMAP_LOCATION, const inMemory=1, ... );

/*!
\brief Remove a resource map from memory
\author Wintermute
\since 0.82
\param 1 the index of the resource map
\fn deleteResourceMap( const set )
\return 0
*/
native deleteResourceMap( const map );

/*!
\brief set a value in a resource map
\author Wintermute
\since 0.82
\param 1 the index of the resource map
\param 2 the actual position parameter
\param 3 the first position parameter
\param 4 the second position parameter
\param 5 the third position parameter
\fn setResourceLocationValue( const set )
\return 0
*/
native setResourceLocationValue( const map, const value, const x, const y, const z );

/*!
\brief get a value in a resource map
\author Wintermute
\since 0.82
\param 1 the index of the resource map
\param 2 the first position parameter
\param 3 the second position parameter
\param 4 the third position parameter
\return the value of the resource map entry
\fn getResourceStringValue( const set )
\return 0
*/
native getResourceLocationValue( const map, const x, const y, const z );

/*!
\brief get a value in a resource map
\author Wintermute
\since 0.82
\param 1 the index of the resource map
\param 2 the string used as key
\return the value of the resource map entry
\fn getResourceStringValue( const set )
\return 0
*/
native getResourceStringValue( const map, const key[], ... );

/*!
\brief set a value in a resource map
\author Wintermute
\since 0.82
\param 1 the index of the resource map
\param 2 the new value of the entry
\param 3 the string used as key
\fn setResourceStringValue( const set )
\return 0
*/
native setResourceStringValue( const map, const value, const key[], ... );

I will take skill lumberjacking as an example on using these maps.

Defining a resource map

public __nxw_sk_lumber(const cc, const x, const y, const mapid)
{
bypass();
new logFound = pine;//log found if nothing else will be found by the miner.
new logAmount = 1;
new logMaxAmount = -1;
new index = 0;
new skill = chr_getSkill(cc, SK_LUMBERJACKING);
new region = -1;

if ( resourceLumberMap == 0 )
{
  // make a persistent map so the resources are saved during worldsave
  resourceLumberMap = createResourceMap(RESOURCEMAP_LOCATION, 1, "lumberjacking_type");
  resourceLumberRespawnMap= createResourceMap(RESOURCEMAP_LOCATION, 1, "lumberjacking_time");
}

IN the last if block two resource maps are defined. They use the type RESOURCEMAP_LOCATION, because the unique key to identify a resource entry will be defined by x,y and z values. Both maps should be held in memory (second parameter = 1 ) and be saved to a binary file on worldsave, which will automatically reload them on a server restart.

The variables resourceLumberMap and resourceLumberRespawnMap are static variables so they remain the same during server runtime. It would be a good idea to put the initializing part into a separate method which is only called on server startup, but this hasn't been done here (shame on me)

In the next part the values are read from memory. The call getResourceLocationValue takes as first parameter the resource map id, as second to fourth the key (which consists of a location defined by x,y,0)

new lumberMemory=getResourceLocationValue(resourceLumberMap, x,y,0);
new lumberSpawnTime=getResourceLocationValue(resourceLumberRespawnMap, x,y,0);
if ( lumberMemory >= 0 )
{
  logMaxAmount=(lumberMemory>>16)&0xFFFF;
  logFound=lumberMemory&0xFFFF;
}
if ( lumberSpawnTime > 0 && lumberSpawnTime <­ getCurrentTime() )
{
  logMaxAmount=-1;
  logFound=pine;
}

All values that are set or returned from a resource map are 32 Bit signed integer (which is by a funny coincidence just the size of a normal amx variable :) ). Since it may be limiting to use only one variable per resource map i used it to contain actually two values (logmaxAmount in the first two bytes and logfound in the last two bytes)

This may be seen also when setting the new value in the resource maps:

// if the use the region map then save the amount and type now
// since the value is a 32 bit unsigned WORD we save the remaining amount in the higher two bytes
         // and the ore type in the lower to byte
         setResourceLocationValue(resourceLumberMap, ((logMaxAmount&0xFFFF) <­<­16)+logFound,   x,     y,     0 );
         setResourceLocationValue( resourceLumberRespawnMap, getTimerValue(LUMBERRESPAWN_DELAY),   x,    y,   0 );


The function setResourceLocationValue works the same way as getResourceLocationValuem but takes as the second parameter the value of the resource map for the key given by parameters 3-5.

Basically this is all you need to use resource maps.
You may use RESOURCE_STRING maps, too, where not a location but a string is used for indexing the values. E.g. a resource map which keeps in memory for each player which other players he has already seen. The resource map id would be stored as a amx local variable on the player char, and the string index would be the name of another player which is in the vicinity. The value of the resource map would then decide how well the current character knows the other one.

Last but not least there is the possibility to remove resource maps, if they are no longer needed.
This may be done by simply calling

deleteResourceMap(id of resourcemap);


 
 
MD-Pro is Free Software released under the licenza GNU/GPL.
 
 

Powered by MD-Pro