BOSS API Readme

Contents

  1. Introduction
  2. Load Orders
    1. Introduction To Load Ordering
    2. The Textfile-based Load Order Standard
    3. Load Ordering With BOSS API
  3. Variable Types
  4. Memory Management
  5. API Codes
    1. Return Codes
    2. Game Codes
    3. Load Order Method Codes
    4. Plugin Cleanliness Codes
  6. Functions
    1. Error Handling Functions
    2. Version Functions
    3. Lifecycle Management Functions
    4. Database Loading Functions
    5. Network Functions
    6. Plugin Activity Functions
    7. Plugin Sorting Functions
    8. Database Access Functions
  7. Examples
    1. C++
  8. Contact
  9. Credits
  10. License

Introduction

BOSS is a utility that helps mod users avoid serious conflicts by setting the mod plugins they have installed in their optimal load order. It also provides over 10,000 plugin-specific messages, including usage notes, requirements, incompatibilities, warnings on bugs and installation mistake notifications.

The load order BOSS sets is decided by its masterlist, which lists all the plugins recognised by BOSS in their optimal load order, and contains the plugin-specific messages BOSS provides. Each game that BOSS supports has a separate masterlist, which are kept up to date via community submissions. Users can customise BOSS's positioning of plugins and the messages it displays using a userlist file. Each game has a separate userlist.


This documentation details the BOSS API (a.k.a. BAPI) and is intended for use by third party developers of modding utilities for TES III: Morrowind, TES IV: Oblivion, TES V: Skyrim, Nehrim - At Fate's Edge, Fallout 3 and Fallout: New Vegas.

BAPI has a C frontend and is available as 32-bit and 64-bit DLLs that can be loaded by other modding utilities. BAPI currently has the following capabilities:

BAPI is intended as a full solution to the management of load order and plugin activation status across all supported games, freeing client utilities from the requirement to maintain their own code for those functions. The source code is available at BOSS's Google Code repository. BAPI is licensed as part of BOSS under the GNU General Public License v3, see the main BOSS readme for more information.

Load Orders

Introduction To Load Ordering

Load ordering is the method used to determine how conflicts between mod plugins should be decided. If two plugins alter the same game data, then the changes made by the plugin loading later will override those made by the plugin loading earlier. This rule of one results in a list of plugins, with those earlier in the list having any conflicting changes overriden by those later in the list. This list is the load order of the plugins.

A game will only load the plugins that are active. Up to 255 plugins, including the game's .esm file, can be active at any one time. Active plugins are listed in the game's plugins.txt file (or Morrowind.ini, in the case of Morrowind), which is stored in the user's local application data folder. Nevertheless, it is useful when working with load orders to consider the load order of all plugins, even if only some of them will actually be loaded. This is both because it is easier to display a single list of plugins than a list and an unordered set, and because modders have engineered methods that allow the changes made by inactive plugins to be loaded by another plugin (eg. Wrye *ash's Bashed Patch). When any such methods are being used, the load order of inactive plugins decides which plugins override others, similar to as if they were active.

In Morrowind, Oblivion, Nehrim, Fallout 3, Fallout: New Vegas and early versions (pre-1.4.26) of Skyrim, load order is decided by the relative timestamps of plugins in the game's Data directory. An installed plugin's load order is therefore an intrinsic property of that plugin.

In Skyrim v1.4.26+, a new textfile-based load order system was introduced, in which load order is decide by the order in which plugins are listed in plugins.txt. This brought with it a fundamental change, in that load order is no longer an intrinsic property of a plugin, and so inactive plugins do not have any load order.

Note: The games enforce one rule that overrides the load order of plugins set by either system. This rule is that master files always load before all plugin files. Simple enough, except that master files are not necessarily .esm files, and plugin files aren't necessarily .esp files. Whether a file is a master or a plugin depends on the value of a bit flag in the file itself, rather than its file extension. This also confuses terminology, so the usage in this readme is clarified below:

The Textfile-based Load Order Standard

As the load order of all plugins, not just inactive plugins, is important, a standard solution that would allow ordering of inactive plugins was decided by Lojack (Wrye Bash), Kaburke (Nexus Mod Manager), WrinklyNinja (BOSS) and Dark0ne (owner of the Nexus sites) that could serve the community's needs. The BOSS API contains the canonical implementation of this standard.

The standard dictates that:

There are some circumstances that produce scenarios in which the behaviour of utilities is not defined. These are detailed in the table below.

CircumstanceRecommended BehaviourBOSS API Behaviour
An attempt is made to activate a plugin with a filename that cannot be represented in the Windows-1252 encoding.Utilities check that filename strings are encoded correctly before outputting them. On a failure to convert to the correct encoding, the user should be alerted that the plugin in question cannot be activated.BAPI attempts to convert the filename string, fails and returns a warning code with an associated string containing the filename in question to the client, after performing whatever other processing that was required by the function the client called. The client is then free to decide on the action taken.
The plugins.txt and loadorder.txt files become unsynchronised.Utilities check for synchronisation on startup and maintain it throughout their operation, rather than re-synchronising the files on program close, for instance. This is to prevent issues for any other programs open at the same time. If desynchronisation is detected, the only standard-based recovery option is to derive plugins.txt from loadorder.txt, first getting a list of filenames to be written from plugins.txt. Alternatively, a utility could use some internal load order backup to restore from. See the coloured box below for a more detailed breakdown of the issue.BAPI detects loss of synchronisation when a database is created and returns a warning code to the client after creating the database. The client is then free to decide on the action taken.
For one reason or another, a plugin becomes listed twice in loadorder.txt.Utilities use the earliest-listed instance of that plugin, as this is most likely to be correct.The API ignores all but the earliest-listed instance of a plugin, neither operating on or returning any other instance.
The Desynchronisation Problem

If either plugins.txt or loadorder.txt are changed such that the load order of the plugins in plugins.txt is not the same in plugins.txt and loadorder.txt, then the difference cannot generally be precisely resolved without discarding one file's ordering. This is due to the load order of plugins in plugins.txt being weakly defined, ie. it is defined relative to other active plugins, but not in relation to inactive plugins. An example:

If you use the API to set a load order of A,b,c,d,E,f,g where uppercase letters denote active plugins, then you use the Skyrim launcher to move A after E, then plugins.txt will read E,A while loadorder.txt remains unchanged. There is no way of knowing from the contents of plugins.txt whether you moved A after E or E before A. If these were the only two plugins, then it would not be an issue, but you also have inactive plugins interspersed amongst them, so you have the following possibilities, all of which are potentially valid, but also potentially damaging in terms of conflicts, etc.:
b,c,d,E,A,f,g
b,c,d,E,f,A,g
b,c,d,E,f,g,A
E,A,b,c,d,f,g
There is no way of knowing which is the correct order to choose for the full load order based on the active load order. You must therefore choose to use one of the two files' orderings. Since plugins.txt does not define the load order positions of inactive plugins, it is unsuitable, and loadorder.txt must be used. The alternative would be for a utility to restore load order from their own internal backup, hence why the standard does not define a specific behaviour, as it may be loadorder.txt that was altered and is now wrong.

Load Ordering with BOSS API

BAPI's implementation of load ordering support presents one set of functions that handle the differences between timestamp-based and textfile-based load ordering opaquely, so there is no difference in usage for clients. It is fully compatible with the community standard for textfile-based load ordering, handling all requirements internally.

In addition, BAPI also handles the following:

Variable Types

The API uses character strings and integers for information input/output.

The API also introduces three new structures: typedef struct _boss_db_int * boss_db;

The boss_db structure abstracts the definition of BOSS's internal state while still providing type safety across the API. typedef struct { uint32_t id; const uint8_t * name; } BashTag;

The BashTag structure gives the Unique Identifier (UID) for each Bash Tag and the corresponding Bash Tag name. typedef struct { uint32_t type; const uint8_t * message; } BossMessage;

The BossMessage structure gives the type of a message and the message string itself.

Memory Management

BAPI manages the memory of strings and arrays it returns internally, so such strings and arrays should not be deallocated by the client.

A string/array returned by a function lasts until a BAPI function is called which returns data of the same type (eg. a string is stored until the client calls another function which returns a string, an integer array lasts until another integer array is returned, etc.).

Strings and arrays may also be deallocated by calling Load or DestroyBossDb. DestroyBossDb also destroys the database passed as its argument.

The two exceptions to the above are the strings returned by GetLastErrorDetails and GetVersionString, which exist independently of each other and strings returned by other functions. A string returned by one of these two functions lasts until that function is called again, or until CleanUpAPI is called.

API Codes

Return Codes

The BOSS API functions uses the following uint32_t return codes to signal how a function completes. WARN return codes signify a problem that did not cause the function to exit prematurely, whereas ERROR return codes signify issues that did cause the function to exit prematurely.

Return CodeDescription
BOSS_API_OK The function completed successfully.
BOSS_API_OK_NO_UPDATE_NECESSARY No update was found for the masterlist.
BOSS_API_WARN_BAD_FILENAME The plugin filename contains characters that do not have Windows-1251/1252 code points. The plugin cannot be activated.
BOSS_API_WARN_LO_MISMATCH The order of plugins in plugins.txt and their order in loadorder.txt does not match. This is due to something (eg. the Skyrim launcher) editing one file without sychronising the other. Synchronisation is automatic when load order is managed through BAPI.
BOSS_API_ERROR_FILE_WRITE_FAIL A file could not be written to.
BOSS_API_ERROR_FILE_DELETE_FAIL A file could not be deleted.
BOSS_API_ERROR_FILE_NOT_UTF8 The specified BOSS file (masterlist or userlist) is not encoded in UTF-8.
BOSS_API_ERROR_FILE_NOT_FOUND The specified file could not be found.
BOSS_API_ERROR_FILE_RENAME_FAIL A file could not be renamed.
BOSS_API_ERROR_TIMESTAMP_READ_FAIL The modification date of a file could not be read.
BOSS_API_ERROR_TIMESTAMP_WRITE_FAIL The modification date of a file could not be set.
BOSS_API_ERROR_PARSE_FAIL There was an error parsing the file.
BOSS_API_ERROR_CONDITION_EVAL_FAIL There was an error evaluating the conditionals in the masterlist.
BOSS_API_ERROR_REGEX_EVAL_FAIL There was an error evaluating the regular expressions in the masterlist.
BOSS_API_ERROR_NO_MEM The API was unable to allocate the required memory.
BOSS_API_ERROR_INVALID_ARGS Invalid arguments were given for the function.
BOSS_API_ERROR_NETWORK_FAIL There was an error in an Internet-related operation.
BOSS_API_ERROR_NO_INTERNET_CONNECTION No Internet connection detected.
BOSS_API_ERROR_NO_TAG_MAP No Bash Tag map has been generated yet. GetBashTagMap must be run before GetModBashTags to build the Bash Tag map.
BOSS_API_ERROR_PLUGINS_FULL Writing the specified plugins to plugins.txt would bring the number of active plugins over 255, which is the maximum allowed.
BOSS_API_ERROR_GAME_NOT_FOUND The specified game could not be found.
BOSS_API_RETURN_MAX Matches the value of the highest-numbered return code. It isn't returned by any functions.

Game Codes

The following uint32_t codes are used by CreateBossDb to specify which game the API is acting for, in cases where distinctions between games are necessary.

Game CodeGame
BOSS_API_GAME_OBLIVION The Elder Scrolls IV: Oblivion
BOSS_API_GAME_FALLOUT3 Fallout 3
BOSS_API_GAME_FALLOUTNV Fallout: New Vegas
BOSS_API_GAME_NEHRIM Nehrim - At Fate's Edge
BOSS_API_GAME_SKYRIM The Elder Scrolls V: Skyrim
BOSS_API_GAME_MORROWIND The Elder Scrolls III: Morrowind

Load Order Method Codes

The following codes are used by GetLoadOrderMethod to signify which load order system BAPI is running for.

Load Order Method CodeDescription
BOSS_API_LOMETHOD_TIMESTAMPThe API is running for a game which uses the timestamp-based load order system. Oblivion, Fallout 3, Fallout: New Vegas all use this system, as does pre-v1.4.26 Skyrim.
BOSS_API_LOMETHOD_TEXTFILEThe API is running for a game which uses the textfile-based load order system. Skyrim v1.4.26+ uses this system.

Plugin Cleanliness Codes

The following codes are returned by GetDirtyMessage to signify the cleanliness status of the plugin passed to the function.

Plugin Cleanliness CodeDescription
BOSS_API_CLEAN_NOThe plugin does not need cleaning or should not be cleaned.
BOSS_API_CLEAN_YESThe plugin needs cleaning.
BOSS_API_CLEAN_UNKNOWNBOSS does not know whether the plugin needs cleaning or not, or if it should not be cleaned.

Message Type Codes

The following codes are used in the BossMessage data structure to signify what type of message a particular message is.

Message Type CodeDescription
BOSS_API_MESSAGE_SAYA general message.
BOSS_API_MESSAGE_TAGA Bash Tag suggestion or suggestions.
BOSS_API_MESSAGE_REQUIREMENTAn installation requirement or requirements.
BOSS_API_MESSAGE_INCOMPATIBILITYAn incompatibility or incompatibilities.
BOSS_API_MESSAGE_DIRTYA message about dirty edits.
BOSS_API_MESSAGE_WARNA warning message.
BOSS_API_MESSAGE_ERRORAn error message.

Functions

BOSS API provides the functions listed below to clients. Where a function returns a uint32_t value, this is the function's return code.

Error Handling Functions

GetLastErrorDetails - Outputs a string giving the details of the last time an error or warning return code was returned by a function. uint32_t GetLastErrorDetails (uint8_t ** details);

Version Functions

IsCompatibleVersion - Returns whether this version of BOSS supports the API from the given BOSS version. Abstracts BOSS API stability policy away from clients. bool IsCompatibleVersion (const uint32_t bossVersionMajor, const uint32_t bossVersionMinor, const uint32_t bossVersionPatch); GetVersionString - Returns the version string for the loaded version of the BOSS API. uint32_t GetVersionString (uint8_t ** bossVersionStr);

Lifecycle Management Functions

CreateBossDb - Creates a database for one of the games supported by the API, and sets the path to the Data directory for that game. It then checks that the game's master file exists at that location. If the clientGame uses the textfile-based load order system, this function also checks that plugins.txt and loadorder.txt are in sync, provided that they both exist. You can create multiple databases. uint32_t CreateBossDb (boss_db * db, const uint32_t clientGame, const uint8_t * dataPath); DestroyBossDb - Explicitly manage a database's lifetime. Allows clients to free memory when they want/need to. Destroys the given DB, freeing any memory allocated as part of its use. void DestroyBossDb (boss_db db); CleanUpAPI - Frees memory allocated to the strings returned by GetVersionString and GetLastErrorDetails. void CleanUpAPI ();

Database Loading Functions

Load - Loads the masterlist and userlist from the paths specified, for the game specified when the given database was created. Can be called multiple times. If an error is encountered, the database remains unchanged. Calling this function for a database that has already been loaded will reload it, freeing any memory allocated by functions that take a boss_db argument, and scanning the data directory specified when the database was created for newly added plugins. uint32_t Load (boss_db db, const uint8_t * masterlistPath, const uint8_t * userlistPath); EvalConditionals - Evaluates all conditional lines and regex mods in the loaded masterlist. This exists so that Load doesn't need to be called whenever the mods installed are changed. Evaluation does not take place unless this function is called. Repeated calls re-evaluate the masterlist from scratch each time, ignoring the results of any previous evaluations. This function affects the results of GetBashTagMap, GetModBashTags and GetDirtyMessage. uint32_t EvalConditionals (boss_db db);

Network Functions

These functions require a database to be created, but do not require Load to have been called, apart from SetProxy, which does not require a database to be created.

SetProxy - Sets the proxy settings for BAPI globally, so that all subsequent BAPI network function calls are affected until SetProxy is called again or BAPI is unloaded. uint32_t SetProxy (const uint8_t * hostname, const uint32_t port, const uint8_t * username, const uint8_t * password); UpdateMasterlist - Updates the masterlist at masterlistPath to the latest version of the masterlist for the game specified when the given database was created. If there is no masterlist present, then the latest masterlist will be downloaded to masterlistPath. If the local masterlist is already at the latest version, no masterlist is downloaded. uint32_t UpdateMasterlist (boss_db db, const uint8_t * masterlistPath); SubmitUnrecognisedPlugin - Submits the given plugin as unrecognised to BOSS's unrecognised plugin tracker, using the same method as the BOSS Log plugin submitter. Whether or not the plugin is actually unrecognised is not checked, but recognised plugin submissions will be ignored and slow down the addition of unrecognised plugin that are submitted, so recognised plugins should not be submitted. Either link or info can be NULL, but not both. If link is NULL, load order suggestions and detail on what the plugin does is crucial for addition to the masterlist. uint32_t SubmitUnrecognisedPlugin (boss_db db, const uint8_t * plugin, const uint8_t * link, const uint8_t * info);

Plugin Activity Functions

These functions require a database to be created, but do not require Load to have been called. Plugins should be passed with their unghosted filenames, whether or not they are currently ghosted.

GetActivePlugins - Returns the contents of plugins.txt. uint32_t GetActivePlugins (boss_db db, uint8_t *** plugins, size_t * numPlugins); SetActivePlugins - Replace the current contents of plugins.txt with the given plugins. uint32_t SetActivePlugins (boss_db db, uint8_t ** plugins, const size_t numPlugins); IsPluginActive - Checks to see if the given plugin is listed in plugins.txt. uint32_t IsPluginActive (boss_db db, const uint8_t * plugin, bool * isActive); SetPluginActive - If active is true, adds the plugin to plugins.txt in its load order if it is not already present. If active is false, removes the plugin from plugins.txt if it is present. If activating a plugin that is ghosted, the .ghost extension is removed. uint32_t SetPluginActive (boss_db db, const uint8_t * plugin, const bool active);

Plugin Sorting Functions

These functions require a database to be created, but only SortMods requires Load to have been called. Plugins should be passed with their unghosted filenames, whether or not they are currently ghosted.

GetLoadOrderMethod - Returns which method BOSS is using for the load order. uint32_t GetLoadOrderMethod (boss_db db, uint32_t * method); SortMods - Sorts the mods for the database's game, using the masterlist loaded by Load. Outputs a list of plugins in their new load order. If trialOnly is false, then sortedPlugins, sortedListLength, unrecognisedPlugins and unrecListLength can either all be valid pointers, or can all be NULL. uint32_t SortMods (boss_db db, const bool trialOnly, uint8_t *** sortedPlugins, size_t * sortedListLength, uint8_t *** unrecognisedPlugins, size_t * unrecListLength); GetLoadOrder - Outputs a list of installed plugins in load order. uint32_t GetLoadOrder (boss_db db, uint8_t *** plugins, size_t * numPlugins); SetLoadOrder - Sets the load order to the passed plugin array, then scans the Data directory and appends any plugins not included in the passed array to the end of the new load order. Only the game's master file may be positioned at the top of the load order. If the client game is Skyrim, then only Update.esm may be positioned in the second position from the top of the load order. uint32_t SetLoadOrder (boss_db db, uint8_t ** plugins, const size_t numPlugins); GetPluginLoadOrder - Gets the load order position of the specified plugin. uint32_t GetPluginLoadOrder (boss_db db, const uint8_t * plugin, size_t * index); SetPluginLoadOrder - Sets the load order of the specified plugin, moving it from its current position. Only the game's master file may be positioned at the top of the load order. If the client game is Skyrim, then only Update.esm may be positioned in the second position from the top of the load order. uint32_t SetPluginLoadOrder (boss_db db, const uint8_t * plugin, const size_t index); GetIndexedPlugin - Get what plugin is at the specified load order position. The first position in the load order is 0. uint32_t GetIndexedPlugin (boss_db db, const size_t index, uint8_t ** plugin); IsPluginMaster - Check if a plugin is a master file or not. This function checks the value of the internal master bit flag, not the file extension, as is correct. The file extension doesn't define whether a plugin is a master or not. uint32_t IsPluginMaster (boss_db db, const uint8_t * plugin, bool * isMaster);

Database Access Functions

GetBashTagMap - Returns an array of the Bash Tags encountered when loading the masterlist and userlist. This function must be called prior to calling GetModBashTags, to ensure that the Bash Tag map exists so that GetModBashTags may return the Tags found using the correct UIDs. uint32_t GetBashTagMap (boss_db db, BashTag ** tagMap, size_t * numTags); GetModBashTags - Returns arrays of Bash Tag UIDs for Bash Tags suggested for addition and removal by BOSS's masterlist and userlist. GetBashTagMap must be called before calling this function in order to assign UIDs to Bash Tags. uint32_t GetModBashTags (boss_db db, const uint8_t * modName, uint32_t ** tagIds_added, size_t * numTags_added, uint32_t **tagIds_removed, size_t *numTags_removed, bool * userlistModified); GetDirtyMessage - Outputs the message associated with a dirty mod and whether the mod needs cleaning. uint32_t GetDirtyMessage (boss_db db, const uint8_t * modName, uint8_t ** message, uint32_t * needsCleaning); GetPluginMessages - Outputs the messages associated with a plugin. uint32_t GetPluginMessages (boss_db db, const uint8_t * plugin, BossMessage ** message, size_t * numMessages); IsRecognised - Outputs whether or not a plugin is listed in the masterlist for the database's game. uint32_t IsRecognised (boss_db db, const uint8_t * plugin, bool * recognised); DumpMinimal - Writes a minimal masterlist that only contains mods that have Bash Tag suggestions and/or dirty messages, plus the Tag suggestions and/or dirty messages themselves. uint32_t DumpMinimal (boss_db db, const uint8_t * outputFile, const bool overwrite);

Examples

Below are (lengthy) code snippets showing examples of how the BOSS API may be used.

C++

#include <iostream> #include <stdint.h> #include <fstream> #include <clocale> #include <boost/filesystem/detail/utf8_codecvt_facet.hpp> #include <boost/filesystem.hpp> #include "BOSS-API.h" using namespace std; int main() { //Set the locale to get encoding conversions working correctly. setlocale(LC_CTYPE, ""); locale global_loc = locale(); locale loc(global_loc, new boost::filesystem::detail::utf8_codecvt_facet()); boost::filesystem::path::imbue(loc); boss_db db; uint8_t * mPath = reinterpret_cast<uint8_t *>("Oblivion/masterlist.txt"); uint8_t * uPath = reinterpret_cast<uint8_t *>(""); uint8_t * dPath = reinterpret_cast<uint8_t *>("../Data"); uint32_t game = BOSS_API_GAME_OBLIVION; const uint8_t * file = reinterpret_cast<uint8_t *>("minimal.txt"); const uint8_t * cleanMod = reinterpret_cast<uint8_t *>("All Natural Base.esm"); const uint8_t * doNotCleanMod = reinterpret_cast<uint8_t *>("bgBalancingEVLAMEAddition.esp"); const uint8_t * inactiveMod = reinterpret_cast<uint8_t *>("français.esp"); const uint8_t * messageMod = reinterpret_cast<uint8_t *>("PerkUP-5555.esp"); const uint8_t * isActiveMod = reinterpret_cast<uint8_t *>("汉语漢語.esp"); uint8_t ** sortedPlugins; uint8_t ** unrecPlugins; size_t len; uint8_t * message; size_t numTagsAdded, numTagsRemoved; bool modified; uint32_t * tagIDsAdded, * tagIDsRemoved; bool active; BashTag * BTmap; size_t size; uint32_t toClean; BossMessage * messages; uint32_t ret; ofstream out("API test.txt"); out << "TESTING IsCompatibleVersion(...)" << endl; bool b = IsCompatibleVersion(2,0,0); if (b) out << '\t' << "API is compatible." << endl; else out << '\t' << "API is incompatible." << endl; out << "TESTING GetVersionString(...)" << endl; ret = GetVersionString(&message); if (ret != BOSS_API_OK) out << '\t' << "Failed to get version string. Error: " << ret << endl; else out << '\t' << "Version: " << *message << endl; out << "TESTING CreateBossDb(...)" << endl; ret = CreateBossDb(&db, game, NULL); if (ret != BOSS_API_OK) out << '\t' << "Creation failed. Error: " << ret << endl; else { out << "TESTING UpdateMasterlist(...)" << endl; ret = UpdateMasterlist(db, mPath); if (ret != BOSS_API_OK) out << '\t' << "Masterlist update failed. Error: " << ret << endl; out << "TESTING Load(...)" << endl; ret = Load(db, mPath, NULL); if (ret != BOSS_API_OK) { uint32_t ret2 = GetLastErrorDetails(&message); out << '\t' << "Loading failed. Error: " << ret << ", " << ret2 << ", " << message << endl; } else { out << "TESTING EvalConditionals(...)" << endl; ret = EvalConditionals(db); if (BOSS_API_OK != ret) out << '\t' << "Conditional evaluation failed. Error: " << ret << endl; else { out << "TESTING SortMods(...)" << endl; ret = SortMods(db, false, &sortedPlugins, &len, &unrecPlugins, &size); if (BOSS_API_OK != ret) out << '\t' << "Sorting failed. Error: " << ret << endl; else { out << '\t' << "List size: " << len << endl; for (size_t i=0; i<len; i++) { out << '\t' << '\t' << i << " : " << sortedPlugins[i] << endl; } out << '\t' << "Unrecognised plugin list size: " << size << endl; for (size_t i=0; i<size; i++) { out << '\t' << '\t' << i << " : " << unrecPlugins[i] << endl; } } out << "TESTING GetDirtyMessage(...)" << endl; //This should give no dirty message. ret = GetDirtyMessage(db, cleanMod, &message, &toClean); if (ret != BOSS_API_OK) out << '\t' << "Failed to get dirty info on \"" << cleanMod << "\". Error no " << ret << endl; else { out << '\t' << "\"" << cleanMod << "\" clean status: " << toClean << endl; if (message != NULL) { out << '\t' << "Message: " << message << endl; } } out << "TESTING GetDirtyMessage(...)" << endl; //Now try getting dirty message from one that will have one. ret = GetDirtyMessage(db, doNotCleanMod, &message, &toClean); if (ret != BOSS_API_OK) out << '\t' << "Failed to get dirty info on \"" << doNotCleanMod << "\". Error no " << ret << endl; else { out << '\t' << "\"" << doNotCleanMod << "\" clean status: " << toClean << endl; if (message != NULL) { out << '\t' << "Message: " << message << endl; } } out << "TESTING DumpMinimal(...)" << endl; ret = DumpMinimal(db, file, true); if (ret != BOSS_API_OK) out << '\t' << "Dump failed. Error no " << ret << endl; out << "TESTING GetBashTagMap(...)" << endl; ret = GetBashTagMap(db, &BTmap, &size); if (ret != BOSS_API_OK) out << '\t' << "Failed to get Bash Tag map. Error no " << ret << endl; else { out << '\t' << "Tag map size: " << size << endl; out << '\t' << "Bash Tags:" << endl; for (size_t i=0; i<size; i++) out << '\t' << '\t' << BTmap[i].id << " : " << BTmap[i].name << endl; } out << "TESTING GetModBashTags(...)" << endl; ret = GetModBashTags(db, doNotCleanMod, &tagIDsAdded, &numTagsAdded, &tagIDsRemoved, &numTagsRemoved, &modified); if (ret != BOSS_API_OK) out << '\t' << "Failed to get Bash Tags for \"" << doNotCleanMod << "\". Error no " << ret << endl; else { out << '\t' << "Tags for \"" << doNotCleanMod << "\":" << endl << '\t' << '\t' << "Modified by userlist: " << modified << endl << '\t' << '\t' << "Number of tags added: " << numTagsAdded << endl << '\t' << '\t' << "Number of tags removed: " << numTagsRemoved << endl << '\t' << '\t' << "Tags added:" << endl; for (size_t i=0; i<numTagsAdded; i++) out << '\t' << '\t' << tagIDsAdded[i] << endl; out << '\t' << '\t' << "Tags removed:" << endl; for (size_t i=0; i<numTagsRemoved; i++) out << '\t' << '\t' << tagIDsRemoved[i] << endl; } out << "TESTING GetLoadOrder(...)" << endl; ret = GetLoadOrder(db, &sortedPlugins, &len); if (BOSS_API_OK != ret) out << '\t' << "GetLoadOrder(...) failed. Error: " << ret << endl; else { out << '\t' << "List size: " << len << endl; for (size_t i=0; i<len; i++) { out << '\t' << '\t' << i << " : " << sortedPlugins[i] << endl; } } out << "TESTING SetLoadOrder(...)" << endl; ret = SetLoadOrder(db, sortedPlugins, len); if (BOSS_API_OK != ret) out << '\t' << "SetLoadOrder(...) failed. Error: " << ret << endl; else { out << '\t' << "List size: " << len << endl; for (size_t i=0; i<len; i++) { out << '\t' << '\t' << i << " : " << sortedPlugins[i] << endl; } } out << "TESTING GetActivePlugins(...)" << endl; ret = GetActivePlugins(db, &sortedPlugins, &len); if (BOSS_API_OK != ret) out << '\t' << "GetActivePlugins(...) failed. Error: " << ret << endl; else { out << '\t' << "List size: " << len << endl; for (size_t i=0; i<len; i++) { out << '\t' << '\t' << i << " : " << sortedPlugins[i] << endl; } } out << "TESTING SetActivePlugins(...)" << endl; ret = SetActivePlugins(db, sortedPlugins, len); if (BOSS_API_OK != ret) out << '\t' << "SetActivePlugins(...) failed. Error: " << ret << endl; else { out << '\t' << "List size: " << len << endl; for (size_t i=0; i<len; i++) { out << '\t' << '\t' << i << " : " << sortedPlugins[i] << endl; } } out << "TESTING GetPluginLoadOrder(...)" << endl; ret = GetPluginLoadOrder(db, doNotCleanMod, &len); if (BOSS_API_OK != ret) out << '\t' << "GetPluginLoadOrder(...) failed. Error: " << ret << endl; else { out << '\t' << "\"" << doNotCleanMod << "\" position: " << len << endl; } out << "TESTING SetPluginLoadOrder(...)" << endl; len = 1; ret = SetPluginLoadOrder(db, doNotCleanMod, len); if (BOSS_API_OK != ret) out << '\t' << "SetPluginLoadOrder(...) failed. Error: " << ret << endl; else { out << '\t' << "\"" << doNotCleanMod << "\" set position: " << len << endl; } out << "TESTING GetIndexedPlugin(...)" << endl; len = 10; ret = GetIndexedPlugin(db, len, &message); if (BOSS_API_OK != ret) out << '\t' << "GetIndexedPlugin(...) failed. Error: " << ret << endl; else { out << '\t' << "Plugin at position " << len << " : " << message << endl; } out << "TESTING GetPluginMessages(...)" << endl; ret = GetPluginMessages(db, messageMod, &messages, &len); if (BOSS_API_OK != ret) out << '\t' << "GetIndexedPlugin(...) failed. Error: " << ret << endl; else { out << '\t' << "Message array size: " << size << endl; out << '\t' << "Messages:" << endl; for (size_t i=0; i<len; i++) out << '\t' << '\t' << messages[i].type << " : " << messages[i].message << endl; } //Assume there are at least 3 plugins. out << "TESTING SetPluginActive(...)" << endl; ret = SetPluginActive(db, sortedPlugins[2], true); if (BOSS_API_OK != ret) out << '\t' << "SetPluginActive(...) failed. Error: " << ret << endl; else { out << '\t' << "\"" << sortedPlugins[2] << "\" activated." << endl; } //Assume there are at least 3 plugins. out << "TESTING IsPluginActive(...)" << endl; ret = IsPluginActive(db, sortedPlugins[2], &active); if (BOSS_API_OK != ret) out << '\t' << "IsPluginActive(...) failed. Error: " << ret << endl; else { out << '\t' << "\"" << sortedPlugins[2] << "\" active status: " << active << endl; } out << "TESTING IsPluginMaster(...)" << endl; ret = IsPluginMaster(db, cleanMod, &active); if (BOSS_API_OK != ret) out << '\t' << "IsPluginMaster(...) failed. Error: " << ret << endl; else if (active) out << '\t' << "\"" << cleanMod << "\" is a master." << endl; else out << '\t' << "\"" << cleanMod << "\" is not a master." << endl; out << "TESTING IsPluginMaster(...)" << endl; ret = IsPluginMaster(db, doNotCleanMod, &active); if (BOSS_API_OK != ret) out << '\t' << "IsPluginMaster(...) failed. Error: " << ret << endl; else if (active) out << '\t' << "\"" << doNotCleanMod << "\" is a master." << endl; else out << '\t' << "\"" << doNotCleanMod << "\" is not a master." << endl; } } DestroyBossDb(db); } out.close(); return 0; }

Contact

Contact information for the BOSS Development Team may be found in the Project Members section of the main BOSS readme. For API-specific support it is best to contact WrinklyNinja, who played a large role in setting up the textfile-based load order standard, created the API, and is currently responsible for BOSS code development.

Credits

Credit goes to myk002 and Lojack for significant contributions to the API's development from initial template submission through to beta testing. Credit also goes to kaburke for his contribution to the beta testing of the API.

The BOSS API is written in C/C++ and makes use of the Boost, libcurl and UTF8-CPP libraries.

License

This document is part of the BOSS documentation.
Copyright (C) 2012 BOSS Development Team.
See the file BOSS ReadMe.html for copying conditions.