248 lines
7.7 KiB
C++
248 lines
7.7 KiB
C++
|
/******************************************************************************/
|
||
|
/* 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>
|