Utils - MSUTeam/MSU GitHub Wiki

File path: scripts/config/msu/utils.nut

Serialization

The functions here allow you to more easily (de)serialize tables and arrays.

Use ::MSU.Serialization.serialize instead.

::MSU.Utils.serialize( _object, _out )
// _object is a table or array
// _out is the C++ object passed to squirrel onSerialize functions

Easily serializes _object saving all of its data in the Battle Brothers save. Will recursively serialize objects within a data structure such as a table. Note: All tables being serialized this way must have all of their keys be of the string data type.

Use ::MSU.Serialization.deserialize instead.

::MSU.Utils.deserialize( _in )
// _in is the C++ object passed to squirrel onDeserialize functions

Deserializes a table or array serialized using ::MSU.Utils.serialize. Note: All tables being deserialized this way must have all of their keys be of the string data type.

Example

// at the end of scripts/items/item onSerialize function
local mySerializedTable = {
    Key = "asdf",
    Num = 124
};
::MSU.Utils.serialize(mySerializedTable, _out);

// at the end of scripts/items/item onDeserialize function
local myDeserializedTable = ::MSU.Utils.deserialize(_in);
// myDeserializedTable should now be the same as mySerializedTable

State Management

A quick word about state management: It appears that states are created and destroyed as you switch between them. This does not make it very convenient to check or utilize them. If you need to know if the game is currently in x state, you can use getActiveState below, and then compare its className to the available states: main_menu_state, tactical_state, world_state Example: if (::MSU.Utils.getActiveState().ClassName == "main_menu_state")

getActiveState

::MSU.Utils.getActiveState()

Returns a weakref to the currently active state: main_menu_state, tactical_state, world_state

hasState

::MSU.Utils.hasState(_id)
// _id is the filename of the state: `main_menu_state`, `tactical_state`, `world_state`

Returns true if the state is in the MSU table and is not null. Otherwise, returns false. States get destroyed when switched (mostly), so when going to world_state, main_menu_state ceases to exist.

getState

::MSU.Utils.getState(_id)
// _id is the filename of the state: `main_menu_state`, `tactical_state`, `world_state`

Returns a weakref to the state if it exists. Beware: states are dynamically created and destroyed by the game. If the state does not currently exists, returns null.

Timer

A simple timer to benchmark code

::MSU.Utils.Timer(_id)

Starts a timer. Also returns the timer class instance, although you don't need to keep it at hand.

::MSU.Utils.Timer(_id).get(_msg = "");

Gets the currently elapsed time of the timer with _id. Prints to log. Optionally prints a message.

::MSU.Utils.Timer(_id).silentGet();

Gets the currently elapsed time of the timer with _id, without printing the time to the log.

::MSU.Utils.Timer(_id).stop(_msg = "");

Stops and deletes the timer. Prints to log. Optionally prints a message.

::MSU.Utils.Timer(_id).silentStop();

Stops and deletes the timer without printing to log. An equal functionality with the same syntax (except ::, so just MSU.Timer()) exists for JS.

benchmark

::MSU.Utils.benchmark( _functions, _iterations = 100000 )
// _functions is either a function or an array
// _iterations is an integer

Outputs to the game log.html the timing of functions. If _functions is an array it must be an array of len 2 arrays where the first index is an id (can be integer/float/string) and the second index is a function. Executes each provided function for _iterations times and outputs both the time per executoin and the total time execution of all the iterations of that function. The first entry in _functions is considered the base function and the timing of all the others is compared against it.

Example

Let's say we have three implementations of a function to removing all integers from an array as shown below and we want to find out the most efficient implementation.

local function foo( _array )
{
    return _array.filter(@(_, _a) typeof _a == "integer");
}

local function bar( _array )
{
    local ret = [];
    foreach (value in _array)
    {
        if (typeof value == "integer")
            ret.push(value);
    }
    return ret;
}

local function baz( _array )
{
    local ret = [];
    for (local i = 0; i < _array.len(); i++)
    {
        if (typeof _array[i] == "integer")
        {
            ret.push(_array[i]);
        }
    }
    return ret;
}

We can use the MSU benchmark utility function to compare the timing of these functions:

// an array containing a mixture of different data types
local myArray = [1, 2, 3, "asdf", "fsdf", "wwfw", 1.3, 1.4, false, true];

// Notice we wrap our functions inside lambda function so that in the
// call to the actual functions we can pass the desired arguments
::MSU.Utils.benchmark([
    ["filter", @() foo(myArray)],
    ["foreach", @() bar(myArray)],
    ["for", @() baz(myArray)],
]);

The output will be printed to the game's log.html. It will print the timing of the function with the id "filter" first and consider its timing as the base time. Then the other two functions will be printed relative to it in terms of how much slower or faster they are.

⚠️ **GitHub.com Fallback** ⚠️