corelib/include/ebcl/Mods.hh

248 lines
7.7 KiB
C++
Raw Normal View History

/******************************************************************************/
/* MODDING SYSTEM *************************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_MODS
#define _H_LW_LIB_MODS
#include <lw/lib/Log.hh>
#include <lw/lib/ModInterface.hh>
namespace lw {
/*= MOD INFORMATION ==========================================================*/
/* Mod identifier (name + version) */
struct T_ModIdentifier {
T_String name;
uint32_t version; // Main version number used for dependencies
bool operator ==( T_ModIdentifier const& other ) const noexcept;
bool operator !=( T_ModIdentifier const& other ) const noexcept;
int compare( T_ModIdentifier const& other ) const noexcept;
};
M_CLASS_POINTERS( ModIdentifier );
M_DECLARE_HASH( T_ModIdentifier );
M_DECLARE_COMPARATOR( T_ModIdentifier );
M_LSHIFT_OP( T_StringBuilder , T_ModIdentifier const& );
/* Types of mods */
enum class E_ModType {
DATA , // This mod consists of data only
NATIVE , // This mod consists of native code
UI , // This mod is an user interface
};
/*----------------------------------------------------------------------------*/
/* Mod information record */
struct T_ModInfo
{
T_String path;
E_ModType type;
/* Mod name, version and revision (the latter is for changes that don't
* affect the interface).
*/
T_ModIdentifier identifier;
uint32_t revision;
/* Required library version number */
uint32_t libVersion;
/* List of dependencies */
T_Array< T_ModIdentifier > modDeps;
/* Is this mod an user interface mod? */
bool isUserInterface( ) const noexcept;
};
M_CLASS_POINTERS( ModInfo );
M_LSHIFT_OP( T_StringBuilder , T_ModInfo const& );
/*= MODS MANAGER CONFIGURATION ===============================================*/
/* Loading mode for a mod */
enum class E_ModMode {
EXCLUDE , // Never load this mod
AUTO , // Load the most appropriate version of the mod
VERSION , // Load a specific version of the mod, fails
// if the mod in the specified version is not
// present
REQUIRE // Require that the specified mod be present
// Note that both VERSION and REQUIRE can apply to an UI-specific mod;
// while the mod will not be loaded if the corresponding UI isn't,
// its presence will still be required.
};
/* Mods manager configuration */
class T_ModsManagerConfiguration : public A_PrivateImplementation
{
public:
T_ModsManagerConfiguration( ) noexcept;
T_ModsManagerConfiguration(
T_ModsManagerConfiguration const& ) = delete;
T_ModsManagerConfiguration& operator =(
T_ModsManagerConfiguration const& ) = delete;
T_ModsManagerConfiguration(
T_ModsManagerConfiguration&& ) noexcept;
T_ModsManagerConfiguration& operator =(
T_ModsManagerConfiguration&& other ) noexcept;
// ---------------------------------------------------------------------
/* Set a mod configuration entry */
void setAuto( T_String const& name ) noexcept;
void setRequired( T_String const& name ) noexcept;
void setExcluded( T_String const& name ) noexcept;
void setVersion( T_String const& name ,
uint32_t version ) noexcept;
void setVersion( T_String const& name ,
uint32_t version ,
uint32_t revision ) noexcept;
/* Query mod configuration */
T_Array< T_String > configured( ) const noexcept;
E_ModMode modeFor( T_String const& name ) const noexcept;
uint32_t requiredVersion( T_String const& name ) const noexcept;
T_Optional< uint32_t > requiredRevision(
T_String const& name ) const noexcept;
// ---------------------------------------------------------------------
/* Set or clear an UI preference */
void setUIPreference(
T_String const& name ,
int32_t weight ) noexcept;
void clearUIPreference(
T_String const& name ) noexcept;
/* List UI preferences */
T_Array< T_String > uiPreferences( ) const noexcept;
/* Get the preference for an UI */
int32_t uiPreference(
T_String const& name ) const noexcept;
// ---------------------------------------------------------------------
/* Filter a list of mods using the configuration's exclusions and
* version limits.
*/
T_Array< RPC_ModInfo > filterMods(
T_Array< RPC_ModInfo > const& mods ) const noexcept;
/* Generate the list of required mods. This includes all mods that
* have been set as required, and all mods that have a version
* requirement.
*/
T_Array< T_String > requiredMods( ) const noexcept;
// ---------------------------------------------------------------------
/* Get a default configuration */
static T_ModsManagerConfiguration DefaultConfiguration( ) noexcept;
/* Get the parser's configuration used to load mods manager configuration */
static T_SRDParserConfig GetParserConfig( );
};
M_CLASS_POINTERS( ModsManagerConfiguration );
/*= MODS DEPENDENCY GRAPH ====================================================*/
class T_ModsDependencies : public A_PrivateImplementation
{
public:
T_ModsDependencies( ) noexcept;
T_ModsDependencies(
T_Logger& logger ,
T_Array< RPC_ModInfo > const& mods ,
T_ModsManagerConfiguration const& config ) noexcept;
T_ModsDependencies(
T_ModsDependencies const& other ) noexcept;
T_ModsDependencies& operator =(
T_ModsDependencies const& other ) noexcept;
T_ModsDependencies(
T_ModsDependencies&& other ) noexcept;
T_ModsDependencies& operator =(
T_ModsDependencies&& other ) noexcept;
friend M_DECLARE_SWAP( T_ModsDependencies );
// ---------------------------------------------------------------------
bool resolved( ) const;
bool ambiguous( ) const;
T_Array< T_String > userInterfaces( ) const;
T_Array< RPC_ModInfo > const& commonMods( ) const;
T_Array< RPC_ModInfo >::RPC forUserInterface(
T_String const& name ) const;
};
M_CLASS_POINTERS( ModsDependencies );
M_DECLARE_SWAP( T_ModsDependencies );
/*= MODS MANAGER =============================================================*/
/* Function type for a function that generates a feedback function used to
* update the initialisation progress when the mods are being initialised.
*/
using F_CreateInitUpdater = std::function< F_UpdateInitProgress( RPC_ModInfo ) >;
class T_ModsManager : public A_PrivateImplementation
{
public:
T_ModsManager( ) = delete;
T_ModsManager( T_ModsManager const& ) = delete;
T_ModsManager( T_ModsManager&& ) noexcept = delete;
T_ModsManager( T_ModsManagerConfiguration&& config ) noexcept;
// ---------------------------------------------------------------------
/* Find available mods, load their descriptions */
bool scanForMods( );
/* Get the list of available mods */
T_Array< RPC_ModInfo > availableMods( ) const noexcept;
/* Resolve dependencies between mods using the configuration;
* returns true if there is a valid set of mods.
*/
bool resolveDependencies( ) noexcept;
// ---------------------------------------------------------------------
/* Pre-initialise common mods */
bool preinitCommon( ) noexcept;
/* Pre-initialise UI mods and try to start the user interface. */
OP_UserInterface preinitUIMods(
T_String const& ui ) noexcept;
/* Try to pre-initialise an UI mod. */
OP_UserInterface preinitUIMods( ) noexcept;
// ---------------------------------------------------------------------
/* Get the amount of loaded mods */
uint32_t modsCount( ) const noexcept;
/* Initialise the mods, sending progress updates along the way */
bool initialise(
F_CreateInitUpdater const& fciu ) noexcept;
// ---------------------------------------------------------------------
/* Shutdown all initialised mods. */
void shutdown( ) noexcept;
/* Unload all mods, calling post-shutdown routines if available */
void unload( ) noexcept;
};
M_CLASS_POINTERS( ModsManager );
} // namespace lw
#endif // _H_LW_LIB_MODS
#include <lw/lib/inline/Mods.hh>