enderalse/source/fs.dll/skse64/skse64/PluginAPI.h

317 lines
11 KiB
C++

#pragma once
typedef UInt32 PluginHandle; // treat this as an opaque type
class GFxMovieView;
class GFxValue;
class TaskDelegate;
class UIDelegate_v1;
class InventoryEntryData;
class SKSEDelayFunctorManager;
class SKSEObjectRegistry;
class SKSEPersistentObjectStorage;
class BranchTrampoline;
struct PluginInfo
{
enum
{
kInfoVersion = 1
};
UInt32 infoVersion;
const char * name;
UInt32 version;
};
enum
{
kPluginHandle_Invalid = 0xFFFFFFFF
};
enum
{
kInterface_Invalid = 0,
kInterface_Scaleform,
kInterface_Papyrus,
kInterface_Serialization,
kInterface_Task,
kInterface_Messaging,
kInterface_Object,
kInterface_Trampoline,
kInterface_Max,
};
struct SKSEInterface
{
UInt32 skseVersion;
UInt32 runtimeVersion;
UInt32 editorVersion;
UInt32 isEditor;
void * (* QueryInterface)(UInt32 id);
// call during your Query or Load functions to get a PluginHandle uniquely identifying your plugin
// invalid if called at any other time, so call it once and save the result
PluginHandle (* GetPluginHandle)(void);
// returns the SKSE build's release index
UInt32 (* GetReleaseIndex)(void);
// Minimum SKSE version 2.0.18
// returns the plugin info structure for a plugin by name, only valid to be called after PostLoad message
const PluginInfo* (* GetPluginInfo)(const char* name);
};
struct SKSEScaleformInterface
{
enum
{
kInterfaceVersion = 2
};
UInt32 interfaceVersion;
// This callback will be called once for every new menu that is created.
// Create your objects relative to the 'root' GFxValue parameter.
typedef bool (* RegisterCallback)(GFxMovieView * view, GFxValue * root);
typedef void (* RegisterInventoryCallback)(GFxMovieView * view, GFxValue * object, InventoryEntryData * item);
// Register your plugin's scaleform API creation callback here.
// The "name" parameter will be used to create an object with the path:
// "skse.plugins.name" that will be passed to the callback.
// Make sure that the memory it points to is valid from the point the callback
// is registered until the game exits.
bool (* Register)(const char * name, RegisterCallback callback);
// Registers your plugin for when item data is extended to the UI
// either favorites menu, or inventory menu
void (* RegisterForInventory)(RegisterInventoryCallback callback);
};
struct SKSESerializationInterface
{
enum
{
kVersion = 4,
};
typedef void (* EventCallback)(SKSESerializationInterface * intfc);
typedef void (* FormDeleteCallback)(UInt64 handle);
UInt32 version;
void (* SetUniqueID)(PluginHandle plugin, UInt32 uid);
void (* SetRevertCallback)(PluginHandle plugin, EventCallback callback);
void (* SetSaveCallback)(PluginHandle plugin, EventCallback callback);
void (* SetLoadCallback)(PluginHandle plugin, EventCallback callback);
void (* SetFormDeleteCallback)(PluginHandle plugin, FormDeleteCallback callback);
bool (* WriteRecord)(UInt32 type, UInt32 version, const void * buf, UInt32 length);
bool (* OpenRecord)(UInt32 type, UInt32 version);
bool (* WriteRecordData)(const void * buf, UInt32 length);
bool (* GetNextRecordInfo)(UInt32 * type, UInt32 * version, UInt32 * length);
UInt32 (* ReadRecordData)(void * buf, UInt32 length);
bool (* ResolveHandle)(UInt64 handle, UInt64 * handleOut);
bool (* ResolveFormId)(UInt32 formId, UInt32 * formIdOut);
};
struct SKSETaskInterface
{
enum
{
kInterfaceVersion = 2
};
UInt32 interfaceVersion;
// Derive your type from TaskDelegate or UIDelegate
// Allocate before adding
// Define your Run function
// Delete your object in the Dispose call
void (* AddTask)(TaskDelegate * task);
void (* AddUITask)(UIDelegate_v1 * task);
};
//#ifdef _PPAPI
// ### this code is unsupported and will be changed in the future
class VMClassRegistry;
struct SKSEPapyrusInterface
{
enum
{
kInterfaceVersion = 1
};
UInt32 interfaceVersion;
typedef bool (* RegisterFunctions)(VMClassRegistry * registry);
bool (* Register)(RegisterFunctions callback);
};
//#endif
/**** Messaging API docs ********************************************************************
*
* Messaging API allows inter-plugin communication at run-time. A plugin may register
* one callback for each plugin from which it wishes to receive messages, specifying
* the sender by name in the call to RegisterListener(). RegisterListener returns false
* if the specified plugin is not loaded, true otherwise. Any messages dispatched by
* the specified plugin will then be forwarded to the listener as they occur. Passing NULL as
* the sender registers the calling plugin as a listener to every loaded plugin.
*
* Messages may be dispatched via Dispatch() to either a specific listener (specified
* by name) or to all listeners (with NULL passed as the receiver). The contents and format of
* messageData are left up to the sender, and the receiver is responsible for casting the message
* to the expected type. If no plugins are registered as listeners for the sender,
* Dispatch() returns false, otherwise it returns true.
*
* Calling RegisterListener() or Dispatch() during plugin load is not advised as the requested plugin
* may not yet be loaded at that point. Instead, if you wish to register as a listener or dispatch a
* message immediately after plugin load, use RegisterListener() during load to register to receive
* messages from SKSE (sender name: "SKSE"). You will then receive a message from SKSE once
* all plugins have been loaded, at which point it is safe to establish communications between
* plugins.
*
* Some plugin authors may wish to use strings instead of integers to denote message type. In
* that case the receiver can pass the address of the string as an integer and require the receiver
* to cast it back to a char* on receipt.
*
*********************************************************************************************/
struct SKSEMessagingInterface
{
struct Message {
const char * sender;
UInt32 type;
UInt32 dataLen;
void * data;
};
typedef void (* EventCallback)(Message* msg);
enum {
kInterfaceVersion = 2
};
// SKSE messages
enum {
kMessage_PostLoad, // sent to registered plugins once all plugins have been loaded (no data)
kMessage_PostPostLoad, // sent right after kMessage_PostLoad to facilitate the correct dispatching/registering of messages/listeners
kMessage_PreLoadGame, // dispatched immediately before savegame is read by Fallout
// dataLen: length of file path, data: char* file path of .ess savegame file
kMessage_PostLoadGame, //dispatched after an attempt to load a saved game has finished (the game's LoadGame() routine
//has returned). You will probably want to handle this event if your plugin uses a Preload callback
//as there is a chance that after that callback is invoked the game will encounter an error
//while loading the saved game (eg. corrupted save) which may require you to reset some of your
//plugin state.
//data: bool, true if game successfully loaded, false otherwise
// plugins may register as listeners during the first callback while deferring dispatches until the next
kMessage_SaveGame,
kMessage_DeleteGame, // sent right before deleting the .skse cosave and the .ess save.
// dataLen: length of file path, data: char* file path of .ess savegame file
kMessage_InputLoaded, // sent right after game input is loaded, right before the main menu initializes
kMessage_NewGame, // sent after a new game is created, before the game has loaded (Sends CharGen TESQuest pointer)
kMessage_DataLoaded // send after the data handler has loaded all its forms
};
UInt32 interfaceVersion;
bool (* RegisterListener)(PluginHandle listener, const char* sender, EventCallback handler);
bool (* Dispatch)(PluginHandle sender, UInt32 messageType, void * data, UInt32 dataLen, const char* receiver);
enum
{
kDispatcher_ModEvent = 0,
kDispatcher_CameraEvent,
kDispatcher_CrosshairEvent,
kDispatcher_ActionEvent,
kDispatcher_NiNodeUpdateEvent
};
// Use this to acquire SKSE's internal EventDispatchers so that you can sink to them
void * (* GetEventDispatcher)(UInt32 dispatcherId);
};
struct SKSEObjectInterface
{
enum
{
kInterfaceVersion = 1
};
UInt32 interfaceVersion;
SKSEDelayFunctorManager & (* GetDelayFunctorManager)();
SKSEObjectRegistry & (* GetObjectRegistry)();
SKSEPersistentObjectStorage & (* GetPersistentObjectStorage)();
};
struct SKSETrampolineInterface
{
enum
{
kInterfaceVersion = 1
};
UInt32 interfaceVersion;
void* (*AllocateFromBranchPool)(PluginHandle plugin, size_t size);
void* (*AllocateFromLocalPool)(PluginHandle plugin, size_t size);
};
typedef bool(*_SKSEPlugin_Query)(const SKSEInterface * skse, PluginInfo * info);
typedef bool(*_SKSEPlugin_Load)(const SKSEInterface * skse);
/**** plugin API docs **********************************************************
*
* The base API is pretty simple. Create a project based on the
* skse_plugin_example project included with the SKSE source code, then define
* and export these functions:
*
* bool SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info)
*
* This primary purposes of this function are to fill out the PluginInfo
* structure, and to perform basic version checks based on the info in the
* SKSEInterface structure. Return false if your plugin is incompatible with
* the version of SKSE or the runtime passed in, otherwise return true. In
* either case, fill out the PluginInfo structure.
*
* Do not do anything other than fill out the PluginInfo structure and return
* true/false in this callback.
*
* If the plugin is being loaded in the context of the editor, isEditor will be
* non-zero, editorVersion will contain the current editor version, and
* runtimeVersion will be zero. In this case you can probably just return
* true, however if you have multiple DLLs implementing the same behavior, for
* example one for each version of ther runtime, only one of them should return
* true.
*
* The PluginInfo fields should be filled out as follows:
* - infoVersion should be set to PluginInfo::kInfoVersion
* - name should be a pointer to a null-terminated string uniquely identifying
* your plugin, it will be used in the plugin querying API
* - version is only used by the plugin query API, and will be returned to
* scripts requesting the current version of your plugin
*
* bool SKSEPlugin_Load(const SKSEInterface * skse)
*
* In this function, use the interfaces above to register your commands, patch
* memory, generally do whatever you need to for integration with the runtime.
*
* At this time, or at any point forward you can call the QueryInterface
* callback to retrieve an interface structure for the base services provided
* by the SKSE core.
*
* You may optionally return false from this function to unload your plugin,
* but make sure that you DO NOT register any commands if you do.
*
* Note that all structure versions are backwards-compatible, so you only need
* to check against the latest version that you need. New fields will be only
* added to the end, and all old fields will remain compatible with their
* previous implementations.
*
******************************************************************************/