/******************************************************************************/ /* MODDING SYSTEM *************************************************************/ /******************************************************************************/ #ifndef _H_LW_LIB_MODS #define _H_LW_LIB_MODS #include #include 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