Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/RE/IDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2259,12 +2259,12 @@ namespace RE::ID

namespace TESFormDeleteEvent
{
inline constexpr REL::ID GetEventSource{ 0 }; // 107166
inline constexpr REL::ID GetEventSource{ 64137 }; // 107166
}

namespace TESFormIDRemapEvent
{
inline constexpr REL::ID GetEventSource{ 0 }; // 107167
inline constexpr REL::ID GetEventSource{ 64138 }; // 107167
}

namespace TESFurnitureEvent
Expand Down
9 changes: 5 additions & 4 deletions include/SFSE/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ namespace SFSE
[[nodiscard]] const PluginInfo* GetPluginInfo(std::string_view a_plugin) noexcept;
[[nodiscard]] std::uint32_t GetSFSEVersion() noexcept;

[[nodiscard]] const TrampolineInterface* GetTrampolineInterface() noexcept;
[[nodiscard]] const MessagingInterface* GetMessagingInterface() noexcept;
[[nodiscard]] const MenuInterface* GetMenuInterface() noexcept;
[[nodiscard]] const TaskInterface* GetTaskInterface() noexcept;
[[nodiscard]] const TrampolineInterface* GetTrampolineInterface() noexcept;
[[nodiscard]] const MessagingInterface* GetMessagingInterface() noexcept;
[[nodiscard]] const MenuInterface* GetMenuInterface() noexcept;
[[nodiscard]] const TaskInterface* GetTaskInterface() noexcept;
[[nodiscard]] const SerializationInterface* GetSerializationInterface() noexcept;
}

namespace SFSE
Expand Down
104 changes: 104 additions & 0 deletions include/SFSE/Interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ namespace SFSE
void (*Register)(void*);
};

struct SFSESerializationInterface
{
std::uint32_t version;
void (*SetUniqueID)(PluginHandle, std::uint32_t);
void (*SetRevertCallback)(PluginHandle, void*);
void (*SetSaveCallback)(PluginHandle, void*);
void (*SetLoadCallback)(PluginHandle, void*);
void (*SetFormDeleteCallback)(PluginHandle, void*);
bool (*WriteRecord)(std::uint32_t, std::uint32_t, const void*, std::uint32_t);
bool (*OpenRecord)(std::uint32_t, std::uint32_t);
bool (*WriteRecordData)(const void*, std::uint32_t);
bool (*GetNextRecordInfo)(std::uint32_t*, std::uint32_t*, std::uint32_t*);
std::uint32_t (*ReadRecordData)(void*, std::uint32_t);
bool (*ResolveHandle)(std::uint64_t, std::uint64_t*);
bool (*ResolveFormID)(std::uint32_t, std::uint32_t*);
};

struct SFSETaskInterface
{
std::uint32_t interfaceVersion;
Expand Down Expand Up @@ -121,6 +138,7 @@ namespace SFSE
kTrampoline,
kMenu,
kTask,
kSerialization,

kTotal
};
Expand Down Expand Up @@ -215,6 +233,92 @@ namespace SFSE
void Register(RegCallback* a_callback) const;
};

class SerializationInterface
{
private:
[[nodiscard]] decltype(auto) GetProxy() const noexcept
{
return reinterpret_cast<const Impl::SFSESerializationInterface&>(*this);
}

public:
enum Version : std::uint32_t
{
kVersion = 1
};

using EventCallback = std::add_pointer_t<void(const SerializationInterface* a_intfc)>;
using FormDeleteCallback = std::add_pointer_t<void(std::uint64_t a_handle)>;

[[nodiscard]] std::uint32_t Version() const noexcept { return GetProxy().version; }

void SetUniqueID(std::uint32_t a_uid) const;
void SetRevertCallback(EventCallback a_callback) const;
void SetSaveCallback(EventCallback a_callback) const;
void SetLoadCallback(EventCallback a_callback) const;
void SetFormDeleteCallback(FormDeleteCallback a_callback) const;

bool WriteRecord(std::uint32_t a_type, std::uint32_t a_version, const void* a_buf, std::uint32_t a_length) const;
bool OpenRecord(std::uint32_t a_type, std::uint32_t a_version) const;
bool WriteRecordData(const void* a_buf, std::uint32_t a_length) const;

template <class T>
requires(std::negation_v<std::is_pointer<T>>)
bool WriteRecordData(const T& a_buf) const
{
return WriteRecordData(std::addressof(a_buf), sizeof(T));
}

template <class T, std::size_t N>
bool WriteRecordData(const T (&a_buf)[N]) const
{
return WriteRecordData(std::addressof(a_buf), sizeof(T) * N);
}

bool GetNextRecordInfo(std::uint32_t& a_type, std::uint32_t& a_version, std::uint32_t& a_length) const;
std::uint32_t ReadRecordData(void* a_buf, std::uint32_t a_length) const;

template <class T>
requires(std::negation_v<std::is_pointer<T>>)
std::uint32_t ReadRecordData(T& a_buf) const
{
return ReadRecordData(std::addressof(a_buf), sizeof(T));
}

template <class T>
requires(std::negation_v<std::is_pointer<T>>)
std::uint32_t ReadRecordDataEx(std::uint32_t& a_length, T& a_buf) const
{
a_length -= sizeof(T);
return ReadRecordData(std::addressof(a_buf), sizeof(T));
}

template <class T, std::size_t N>
std::uint32_t ReadRecordData(T (&a_buf)[N]) const
{
return ReadRecordData(std::addressof(a_buf), sizeof(T) * N);
}

template <class T, std::size_t N>
std::uint32_t ReadRecordDataEx(std::uint32_t& a_length, T (&a_buf)[N]) const
{
a_length -= sizeof(T) * N;
return ReadRecordData(std::addressof(a_buf), sizeof(T) * N);
}

[[nodiscard]] std::optional<std::uint64_t> ResolveHandle(std::uint64_t a_handle) const
{
std::uint64_t result{ 0 };
return GetProxy().ResolveHandle(a_handle, std::addressof(result)) ? std::optional{ result } : std::nullopt;
}

[[nodiscard]] std::optional<std::uint32_t> ResolveFormID(std::uint32_t a_formID) const
{
std::uint32_t result{ 0 };
return GetProxy().ResolveFormID(a_formID, std::addressof(result)) ? std::optional{ result } : std::nullopt;
}
};

class ITaskDelegate
{
public:
Expand Down
15 changes: 11 additions & 4 deletions src/SFSE/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ namespace SFSE
PluginHandle pluginHandle{ static_cast<PluginHandle>(-1) };
std::function<const void*(const char*)> pluginInfoAccessor;

TrampolineInterface* trampolineInterface{ nullptr };
MessagingInterface* messagingInterface{ nullptr };
MenuInterface* menuInterface{ nullptr };
TaskInterface* taskInterface{ nullptr };
TrampolineInterface* trampolineInterface{ nullptr };
MessagingInterface* messagingInterface{ nullptr };
MenuInterface* menuInterface{ nullptr };
TaskInterface* taskInterface{ nullptr };
SerializationInterface* serializationInterface{ nullptr };

std::mutex apiLock;
std::vector<std::function<void()>> apiInitRegs;
Expand Down Expand Up @@ -158,6 +159,7 @@ namespace SFSE
api->trampolineInterface = a_intfc->QueryInterface<TrampolineInterface>(LoadInterface::kTrampoline);
api->menuInterface = a_intfc->QueryInterface<MenuInterface>(LoadInterface::kMenu);
api->taskInterface = a_intfc->QueryInterface<TaskInterface>(LoadInterface::kTask);
api->serializationInterface = a_intfc->QueryInterface<SerializationInterface>(LoadInterface::kSerialization);

const std::scoped_lock lock{ api->apiLock };
if (!api->apiInit) {
Expand Down Expand Up @@ -243,6 +245,11 @@ namespace SFSE
{
return Impl::API::GetSingleton()->taskInterface;
}

const SerializationInterface* GetSerializationInterface() noexcept
{
return Impl::API::GetSingleton()->serializationInterface;
}
}

namespace SFSE
Expand Down
50 changes: 50 additions & 0 deletions src/SFSE/Interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,56 @@ namespace SFSE
return GetProxy().Register(reinterpret_cast<void*>(a_callback));
}

void SerializationInterface::SetUniqueID(const std::uint32_t a_uid) const
{
GetProxy().SetUniqueID(GetPluginHandle(), a_uid);
}

void SerializationInterface::SetRevertCallback(const EventCallback a_callback) const
{
GetProxy().SetRevertCallback(GetPluginHandle(), std::bit_cast<void*>(a_callback));
}

void SerializationInterface::SetSaveCallback(const EventCallback a_callback) const
{
GetProxy().SetSaveCallback(GetPluginHandle(), std::bit_cast<void*>(a_callback));
}

void SerializationInterface::SetLoadCallback(const EventCallback a_callback) const
{
GetProxy().SetLoadCallback(GetPluginHandle(), std::bit_cast<void*>(a_callback));
}

void SerializationInterface::SetFormDeleteCallback(const FormDeleteCallback a_callback) const
{
GetProxy().SetFormDeleteCallback(GetPluginHandle(), std::bit_cast<void*>(a_callback));
}

bool SerializationInterface::WriteRecord(const std::uint32_t a_type, const std::uint32_t a_version, const void* a_buf, const std::uint32_t a_length) const
{
return GetProxy().WriteRecord(a_type, a_version, a_buf, a_length);
}

bool SerializationInterface::OpenRecord(const std::uint32_t a_type, const std::uint32_t a_version) const
{
return GetProxy().OpenRecord(a_type, a_version);
}

bool SerializationInterface::WriteRecordData(const void* a_buf, const std::uint32_t a_length) const
{
return GetProxy().WriteRecordData(a_buf, a_length);
}

bool SerializationInterface::GetNextRecordInfo(std::uint32_t& a_type, std::uint32_t& a_version, std::uint32_t& a_length) const
{
return GetProxy().GetNextRecordInfo(std::addressof(a_type), std::addressof(a_version), std::addressof(a_length));
}

std::uint32_t SerializationInterface::ReadRecordData(void* a_buf, const std::uint32_t a_length) const
{
return GetProxy().ReadRecordData(a_buf, a_length);
}

const PluginVersionData* PluginVersionData::GetSingleton() noexcept
{
return reinterpret_cast<const PluginVersionData*>(REX::W32::GetProcAddress(REX::W32::GetCurrentModule(), "SFSEPlugin_Version"));
Expand Down
Loading