Got a question that the wiki doesn't answer? Ask on the forum (preferred), or join us on IRC.

BeastNode

CommandHelper/Persistance

From EngineHub.org Wiki
Jump to: navigation, search


CommandHelper can easily save data that is persisted across server restarts, which can be used to store player data, state information, or anything else you can think of. All data types can be stored to disk using the persistance functions. The main operations are storing, and retrieving values, by using the store_value() and get_value() functions. The exact nature of how this information is stored to disk is handled transparently for you, and in future versions of CommandHelper, will be able to be changed to other storage backends. For more details about the lower level functionality, please read the article on the Data Manager. In general though, for most people, the default storage mechanism will be more than enough. The data is saved each time you store a value, so the data should continue to exist even if the server unexpectedly shuts down. When using the default storage backend, the data is all kept in memory, so reads are quick, having little performance penalty. Writes do incur a disk I/O penalty, but as the data is stored as binary, the performance hit is minimal, even for large servers. If you wish to keep data in memory only, not persisted for long periods of time, you should use the import() and export() functions.

Contents

Namespaces

The primary operations are storing a value and getting a value. Values are stored in key/value pairs, and only one key may exist at any given time. To help prevent naming conflicts, namespaces are also supported. Namespaces also make it easier to do mass lookups, using get_values() (note the s on the end). A key may be a un-namespaced string, however, to make it easier to manage your database, you should use namespaces whenever possible. At minimum, you should use at least one namespace per key, so that when browsing your saved values, you can have various categories of data with which to filter. There is no limit to how deep you nest namespaces. A key may look like this then: 'this.is.a.namespaced.key'. This key has 4 namespaces, and an identifier. In actuality, the namespaces could have been created using underscores or something, but using periods gives you the build in support of the namespacing system, both when using get_values and the Data Manager.

Operations

To store a value, use store_value().

store_value('namespace.key', 'value')

To retrieve a value that has already been stored, use get_value().

get_value('namespace.key') #This returns 'value'

It's important to note that this will succeed even if the value had not previously been stored. If that had been the case, the function would have returned null. However, storing null is valid as well, so there's no way to tell if the value was simply missing, or null had been stored. That's what the has_value() function is for.

has_value('namespace.key') #If our examples above had been run, returns true
has_value('does.not.exist') #Returns false

As noted above, storing null is a valid operation. So, to completely clear out a value, you can use clear_value().

get_value('new.key') #Returns null
has_value('new.key') #Returns false
store_value('new.key', null) #Puts null in that key
get_value('new.key') #Also returns null!
has_value('new.key') #Now returns true
clear_value('new.key') #Now it no longer exists
has_value('new.key') #Returns false

get_values()

Most of the time you know exactly what key you want, however there may come a time where you want a bunch of keys, and you don't necessarily know their name. You can use get_values(), which returns an associative array of all the matched keys. Assume our database looks like this:

namespace1.key1 = value
namespace1.key2 = value
namespace2.key1 = value
namespace2.key2 = value
namespace2.sub1.key1 = value
namespace2.sub1.key2 = value
namespace2.sub2.key1 = value
namespace2.sub2.key2 = value

All keys that are in the specified namespace are returned, so a call to get_values('namespace1') would return the array:

{namespace1.key1: value, namespace1.key2: value}

Sub namespaces are matched as well, so get_values('namespace2') would return:

{namespace2.key1: value, namespace2.key2: value, namespace2.sub1.key1: value, namespace2.sub1.key2: value ... }

Partial matches for a particular namespace will not match however, so a call to get_values('namespace2.sub') would not return anything at all. This allows you to have namespaces that start with the same letters, but won't give you extra results. Also, if the namespace provided to get_values is a full key, that's ok as well. That key will be returned in the results, but so will any sub namespaces of that key as well.

Example

The following example shows some code to create a command confirmation system.

/cmd1 $arg = >>>
    assign(@key, concat('confirmation.', player()))
    msg('Are you sure you want to run this command? Type /yes to confirm, or /no to cancel')
    store_value(@key, '/cmd' $arg)
<<<

/yes = >>>
    assign(@key, concat('confirmation.', player()))
    if(has_value(@key),
        run(get_value(@key))
        clear_value(@key)
    ,#else
        msg('There is no command for you to run!')
    )
<<<

/no = >>>
    assign(@key, concat('confirmation.', player()))
    if(has_value(@key),
        clear_value(@key)
    ,#else
        msg('No command was stored!')
    )
<<<

Alternatively, to use the same command:

/cmd $ = >>>
    assign(@key, concat('confirmation.', player(), '.cmd'))
    if(has_value(@key),
        #They have already confirmed they want to run it
        run('/cmd' $)
        #If you don't want to bother them again, you can omit this line
        clear_value(@key)
    ,#else
        #They haven't yet confirmed they want to run it
        msg('Are you sure you want to run this command? Type it again if you\'re sure.')
        store_value(@key)
    )
<<<






Namespaces

Variants
Actions