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

655 lines
15 KiB
C++

#pragma once
#include "GameForms.h"
#include "GameTypes.h"
#include "GameEvents.h"
#include "GameInput.h"
#include "GameCamera.h"
#include <map>
#include <set>
#include "Serialization.h"
#include "PapyrusVM.h"
template <typename D>
class EventRegistration
{
public:
UInt64 handle;
D params;
bool operator<(const EventRegistration & rhs) const { return handle < rhs.handle; }
bool Save(SKSESerializationInterface * intfc, UInt32 version) const
{
if (! intfc->WriteRecordData(&handle, sizeof(handle)))
return false;
if (! params.Save(intfc, version))
return false;
return true;
}
bool Load(SKSESerializationInterface * intfc, UInt32 version)
{
if (! intfc->ReadRecordData(&handle, sizeof(handle)))
return false;
if (! params.Load(intfc, version))
return false;
return true;
}
void Dump(void)
{
_MESSAGE("> handle:\t%016I64x", handle);
params.Dump();
}
};
class NullParameters
{
public:
bool Save(SKSESerializationInterface * intfc, UInt32 version) const { return true; }
bool Load(SKSESerializationInterface * intfc, UInt32 version) { return true; }
void Dump(void) {}
};
class ModCallbackParameters
{
public:
BSFixedString callbackName;
bool Save(SKSESerializationInterface * intfc, UInt32 version) const
{
return Serialization::WriteData<BSFixedString>(intfc, &callbackName);
}
bool Load(SKSESerializationInterface * intfc, UInt32 version)
{
return Serialization::ReadData<BSFixedString>(intfc, &callbackName);
}
void Dump(void)
{
_MESSAGE("> callbackName:\t%s", callbackName);
}
};
template <typename K, typename D = NullParameters>
class RegistrationMapHolder : public SafeDataHolder<std::map<K,std::set<EventRegistration<D>>>>
{
typedef std::set<EventRegistration<D>> RegSet;
typedef std::map<K,RegSet> RegMap;
public:
void Register(K & key, UInt64 handle, D * params = NULL)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = handle;
if (params)
reg.params = *params;
Lock();
if (m_data[key].insert(reg).second)
policy->AddRef(handle);
Release();
}
template <typename T>
void Register(K & key, UInt32 type, T * classType, D * params = NULL)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = policy->Create(type, (void *)classType);
if (params)
reg.params = *params;
#ifdef _DEBUG
_MESSAGE("Executed PapyrusEvents::Register - %016llX", reg.handle);
#endif
Lock();
if (m_data[key].insert(reg).second)
policy->AddRef(reg.handle);
Release();
}
void Unregister(K & key, UInt64 handle)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = handle;
Lock();
if (m_data[key].erase(reg))
policy->Release(handle);
Release();
}
template <typename T>
void Unregister(K & key, UInt32 type, T * classType)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = policy->Create(type, (void *)classType);
Lock();
if (m_data[key].erase(reg))
policy->Release(reg.handle);
Release();
}
void UnregisterAll(UInt64 handle)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = handle;
Lock();
for (RegMap::iterator iter = m_data.begin(); iter != m_data.end(); ++iter)
if (iter->second.erase(reg))
policy->Release(handle);
Release();
}
template <typename T>
void UnregisterAll(UInt32 type, T * classType)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = policy->Create(type, (void *)classType);
Lock();
for (RegMap::iterator iter = m_data.begin(); iter != m_data.end(); ++iter)
if (iter->second.erase(reg))
policy->Release(reg.handle);
Release();
}
template <typename F>
void ForEach(K & key, F & functor)
{
Lock();
RegMap::iterator handles = m_data.find(key);
if (handles != m_data.end())
for (RegSet::iterator iter = handles->second.begin(); iter != handles->second.end(); ++iter)
functor(*iter);
Release();
}
void Clear(void)
{
Lock();
m_data.clear();
Release();
}
bool Save(SKSESerializationInterface * intfc, UInt32 type, UInt32 version)
{
intfc->OpenRecord(type, version);
Lock();
for (RegMap::iterator iter = m_data.begin(); iter != m_data.end(); ++iter)
{
UInt32 numRegs = iter->second.size();
if (!numRegs)
continue;
intfc->OpenRecord('REGS', version);
// Key
Serialization::WriteData(intfc, &iter->first);
// Reg count
intfc->WriteRecordData(&numRegs, sizeof(numRegs));
// Regs
for (RegSet::iterator elems = iter->second.begin(); elems != iter->second.end(); ++elems)
elems->Save(intfc, version);
}
intfc->OpenRecord('REGE', version);
Release();
return true;
}
bool Load(SKSESerializationInterface* intfc, UInt32 version)
{
UInt32 type, length, curVersion;
while (intfc->GetNextRecordInfo(&type, &curVersion, &length))
{
switch (type)
{
case 'REGS':
{
K curKey;
// Key
if (! Serialization::ReadData(intfc, &curKey))
{
_MESSAGE("Error loading reg key");
return false;
}
// Reg count
UInt32 numRegs = 0;
if (! intfc->ReadRecordData(&numRegs, sizeof(numRegs)))
{
_MESSAGE("Error loading reg count");
return false;
}
for (UInt32 i=0; i<numRegs; i++)
{
EventRegistration<D> reg;
if (reg.Load(intfc, version))
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
UInt64 newHandle = 0;
// Skip if handle is no longer valid.
if (! intfc->ResolveHandle(reg.handle, &newHandle))
continue;
reg.handle = newHandle;
Lock();
if (m_data[curKey].insert(reg).second)
policy->AddRef(reg.handle);
Release();
}
else
{
_MESSAGE("Error loading regs");
return false;
}
}
break;
}
case 'REGE':
{
return true;
}
default:
{
_MESSAGE("Error loading unexpected chunk type %08X (%.4s)", type, &type);
return false;
}
}
}
_MESSAGE("Missing record data for type %08X (%.4s)", type, &type);
return false;
}
};
template <typename D = NullParameters>
class RegistrationSetHolder : public SafeDataHolder<std::set<EventRegistration<D>>>
{
typedef std::set<EventRegistration<D>> RegSet;
public:
void Register(UInt64 handle, D * params = NULL)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = handle;
if (params)
reg.params = *params;
Lock();
if (m_data.insert(reg).second)
policy->AddRef(handle);
Release();
}
template <typename T>
void Register(UInt32 type, T * classType, D * params = NULL)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = policy->Create(type, (void *)classType);
if (params)
reg.params = *params;
Lock();
if (m_data.insert(reg).second)
policy->AddRef(reg.handle);
Release();
}
void Unregister(UInt64 handle)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = handle;
Lock();
if (m_data.erase(reg))
policy->Release(handle);
Release();
}
template <typename T>
void Unregister(UInt32 type, T * classType)
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
EventRegistration<D> reg;
reg.handle = policy->Create(type, (void *)classType);
Lock();
if (m_data.erase(reg))
policy->Release(reg.handle);
Release();
}
template <typename F>
void ForEach(F & functor)
{
Lock();
for (RegSet::iterator iter = m_data.begin(); iter != m_data.end(); ++iter)
functor(*iter);
Release();
}
void Clear(void)
{
Lock();
m_data.clear();
Release();
}
bool Save(SKSESerializationInterface * intfc, UInt32 type, UInt32 version)
{
intfc->OpenRecord(type, version);
Lock();
UInt32 numRegs = m_data.size();
// Reg count
intfc->WriteRecordData(&numRegs, sizeof(numRegs));
// Regs
for (RegSet::iterator iter = m_data.begin(); iter != m_data.end(); ++iter)
iter->Save(intfc, version);
Release();
return true;
}
bool Load(SKSESerializationInterface* intfc, UInt32 version)
{
// Reg count
UInt32 numRegs = 0;
if (! intfc->ReadRecordData(&numRegs, sizeof(numRegs)))
{
_MESSAGE("Error loading reg count");
return false;
}
for (UInt32 i=0; i<numRegs; i++)
{
EventRegistration<D> reg;
if (reg.Load(intfc, version))
{
VMClassRegistry * registry = (*g_skyrimVM)->GetClassRegistry();
IObjectHandlePolicy * policy = registry->GetHandlePolicy();
UInt64 newHandle = 0;
// Skip if handle is no longer valid.
if (! intfc->ResolveHandle(reg.handle, &newHandle))
continue;
reg.handle = newHandle;
Lock();
if (m_data.insert(reg).second)
policy->AddRef(reg.handle);
Release();
}
else
{
_MESSAGE("Error loading regs");
return false;
}
}
return true;
}
};
extern RegistrationMapHolder<BSFixedString> g_menuOpenCloseRegs;
extern RegistrationMapHolder<UInt32> g_inputKeyEventRegs;
extern RegistrationMapHolder<BSFixedString> g_inputControlEventRegs;
extern RegistrationMapHolder<BSFixedString,ModCallbackParameters> g_modCallbackRegs;
extern RegistrationSetHolder<NullParameters> g_cameraEventRegs;
extern RegistrationSetHolder<NullParameters> g_crosshairRefEventRegs;
extern RegistrationMapHolder<UInt32> g_actionEventRegs;
extern RegistrationSetHolder<NullParameters> g_ninodeUpdateEventRegs;
struct SKSEModCallbackEvent
{
BSFixedString eventName;
BSFixedString strArg;
float numArg;
TESForm * sender;
SKSEModCallbackEvent(BSFixedString a_eventName, BSFixedString a_strArg, float a_numArg, TESForm * a_sender) :
eventName(a_eventName.data), strArg(a_strArg.data), numArg(a_numArg), sender(a_sender) {}
};
template <>
class BSTEventSink <SKSEModCallbackEvent>
{
public:
virtual ~BSTEventSink() {}; // todo?
virtual EventResult ReceiveEvent(SKSEModCallbackEvent * evn, EventDispatcher<SKSEModCallbackEvent> * dispatcher) = 0;
};
extern EventDispatcher<SKSEModCallbackEvent> g_modCallbackEventDispatcher;
struct SKSECameraEvent
{
TESCameraState * oldState;
TESCameraState * newState;
SKSECameraEvent(TESCameraState * a_oldState, TESCameraState * a_newState) :
oldState(a_oldState), newState(a_newState) {}
};
template <>
class BSTEventSink <SKSECameraEvent>
{
public:
virtual ~BSTEventSink() {}; // todo?
virtual EventResult ReceiveEvent(SKSECameraEvent * evn, EventDispatcher<SKSECameraEvent> * dispatcher) = 0;
};
extern EventDispatcher<SKSECameraEvent> g_cameraEventDispatcher;
struct SKSECrosshairRefEvent
{
NiPointer<TESObjectREFR> crosshairRef;
SKSECrosshairRefEvent(NiPointer<TESObjectREFR> & a_crosshairRef);
};
template <>
class BSTEventSink <SKSECrosshairRefEvent>
{
public:
virtual ~BSTEventSink() {}; // todo?
virtual EventResult ReceiveEvent(SKSECrosshairRefEvent * evn, EventDispatcher<SKSECrosshairRefEvent> * dispatcher) = 0;
};
extern EventDispatcher<SKSECrosshairRefEvent> g_crosshairRefEventDispatcher;
struct SKSEActionEvent
{
enum {
kType_WeaponSwing = 0,
kType_SpellCast = 1,
kType_SpellFire = 2,
kType_VoiceCast = 3,
kType_VoiceFire = 4,
kType_BowDraw = 5,
kType_BowRelease = 6,
kType_BeginDraw = 7,
kType_EndDraw = 8,
kType_BeginSheathe = 9,
kType_EndSheathe = 10
};
enum {
kSlot_Left = 0,
kSlot_Right = 1,
kSlot_Voice = 2
};
UInt32 type;
Actor * actor;
TESForm * sourceForm;
UInt32 slot;
SKSEActionEvent(UInt32 a_type, Actor * a_actor, TESForm * a_source, UInt32 a_slot) :
type(a_type), actor(a_actor), sourceForm(a_source), slot(a_slot) {}
};
struct SKSENiNodeUpdateEvent
{
TESObjectREFR * reference;
SKSENiNodeUpdateEvent(TESObjectREFR * a_reference) : reference(a_reference) {}
};
template <>
class BSTEventSink <SKSENiNodeUpdateEvent>
{
public:
virtual ~BSTEventSink() {}; // todo?
virtual EventResult ReceiveEvent(SKSENiNodeUpdateEvent * evn, EventDispatcher<SKSENiNodeUpdateEvent> * dispatcher) = 0;
};
extern EventDispatcher<SKSENiNodeUpdateEvent> g_ninodeUpdateEventDispatcher;
template <>
class BSTEventSink <SKSEActionEvent>
{
public:
virtual ~BSTEventSink() {}; // todo?
virtual EventResult ReceiveEvent(SKSEActionEvent * evn, EventDispatcher<SKSEActionEvent> * dispatcher) = 0;
};
extern EventDispatcher<SKSEActionEvent> g_actionEventDispatcher;
class MenuEventHandler : public BSTEventSink <MenuOpenCloseEvent>
{
public:
virtual EventResult ReceiveEvent(MenuOpenCloseEvent * evn, EventDispatcher<MenuOpenCloseEvent> * dispatcher);
};
class InputEventHandler : public BSTEventSink <InputEvent>
{
public:
virtual EventResult ReceiveEvent(InputEvent ** evns, InputEventDispatcher * dispatcher);
};
class ModCallbackEventHandler : public BSTEventSink <SKSEModCallbackEvent>
{
public:
virtual EventResult ReceiveEvent(SKSEModCallbackEvent * evn, EventDispatcher<SKSEModCallbackEvent> * dispatcher);
};
class CameraEventHandler : public BSTEventSink <SKSECameraEvent>
{
public:
virtual EventResult ReceiveEvent(SKSECameraEvent * evn, EventDispatcher<SKSECameraEvent> * dispatcher);
};
class CrosshairRefEventHandler : public BSTEventSink <SKSECrosshairRefEvent>
{
public:
virtual EventResult ReceiveEvent(SKSECrosshairRefEvent * evn, EventDispatcher<SKSECrosshairRefEvent> * dispatcher);
};
class ActionEventHandler : public BSTEventSink <SKSEActionEvent>
{
public:
virtual EventResult ReceiveEvent(SKSEActionEvent * evn, EventDispatcher<SKSEActionEvent> * dispatcher);
};
class NiNodeUpdateEventHandler : public BSTEventSink <SKSENiNodeUpdateEvent>
{
public:
virtual EventResult ReceiveEvent(SKSENiNodeUpdateEvent * evn, EventDispatcher<SKSENiNodeUpdateEvent> * dispatcher);
};
extern MenuEventHandler g_menuEventHandler;
extern InputEventHandler g_inputEventHandler;
extern ModCallbackEventHandler g_modCallbackEventHandler;
extern CameraEventHandler g_cameraEventHandler;
extern CrosshairRefEventHandler g_crosshairRefEventHandler;
extern ActionEventHandler g_actionEventHandler;
extern NiNodeUpdateEventHandler g_ninodeUpdateEventHandler;