Skip to content

Commit

Permalink
Add GameInitialized Message, Rework Task interface, add AutoRemovable…
Browse files Browse the repository at this point in the history
… tasks
  • Loading branch information
llde committed Sep 2, 2023
1 parent be02501 commit 23939fc
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 43 deletions.
1 change: 1 addition & 0 deletions obse/obse/Hooks_Gameplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ static void HandleMainLoopHook(void)
{
static bool s_recordedMainThreadID = false;
if (!s_recordedMainThreadID) {
PluginManager::Dispatch_Message(0, OBSEMessagingInterface::kMessage_GameInitialized, nullptr, 0, nullptr);
Console_Print("xOBSE %d.%d.%d Loaded Succesfully", OBSE_VERSION_INTEGER, OBSE_VERSION_INTEGER_MINOR, OBSE_VERSION_INTEGER_HOTIFX);
s_recordedMainThreadID = true;
g_mainThreadID = GetCurrentThreadId();
Expand Down
2 changes: 1 addition & 1 deletion obse/obse/Hooks_SaveLoad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void __stdcall DoPreLoadGame(BSFile* file)
}

static BSFile* s_curLoadingFile = NULL;
static __declspec(naked) void PreLoadGameHook(void)
static __declspec(naked) void PreLoadGameHook(void) noexcept
{
static IOManager* IOManager = *g_ioManager;

Expand Down
18 changes: 13 additions & 5 deletions obse/obse/PluginAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,10 @@ struct OBSEMessagingInterface
// added v0020
kMessage_PostPostLoad, // sent right after kMessage_PostLoad to facilitate the correct dispatching/registering of messages/listeners
// plugins may register as listeners during the first callback while deferring dispatches until the next
kMessage_RuntimeScriptError // dispatched when an OBSE script error is encountered during runtime/
kMessage_RuntimeScriptError, // dispatched when an OBSE script error is encountered during runtime/
// data: char* errorMessageText
// added xOBSE 22.10
kMessage_GameInitialized // sent to plugins when the game is fully initialized (shows main menu)
};

UInt32 version;
Expand Down Expand Up @@ -587,15 +589,21 @@ struct OBSESerializationInterface
/*
* An Interface to submit and remove tasks, functions that operates in the OBSE mainloop.
* USe this if you are in need to define an Hook into the OBlivion mainloop.
* v2: The removable functions add a way to add functions that are removed if return True.
*/
#if OBLIVION
struct OBSETasksInterface {
Task* (*EnqueueTask)(TaskFunc f);
void (*RemoveTask)(Task* f);
bool (*IsTaskPresent)(Task* f);
Task<void>* (*EnqueueTask)(TaskFunc f);
void (*RemoveTask)(Task<void>* f);
bool (*IsTaskPresent)(Task<void>* f);
void (*ReEnqueueTask)(Task<void>* f);
Task<bool>* (*EnqueueTaskRemovable)(TaskFuncT<bool> f);
void (*RemoveTaskRemovable)(Task<bool>* f);
bool (*IsTaskPresentRemovable)(Task<bool>* f);
void (*ReEnqueueTaskRemovable)(Task<bool>* f);
bool (*HasTasks)();
};


struct OBSEInputInterface {
void (*DisableInputKey)(UInt16 dxCode);
void (*EnableInputKey)(UInt16 dxCode);
Expand Down
7 changes: 6 additions & 1 deletion obse/obse/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,16 @@ static OBSEScriptInterface g_OBSEScriptInterface =
PluginAPI::IsUserFunction
};


static OBSETasksInterface g_TasksInterface = {
PluginAPI::EnqueueTask,
PluginAPI::Remove,
PluginAPI::IsTaskEnqueued,
PluginAPI::ReEnqueueTask,
PluginAPI::EnqueueTask,
PluginAPI::Remove,
PluginAPI::IsTaskEnqueued,
PluginAPI::ReEnqueueTask,
PluginAPI::HasTasks
};

static OBSEInputInterface g_InputInterface = {
Expand Down
89 changes: 70 additions & 19 deletions obse/obse/Tasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,72 @@
#include "GameObjects.h"
#include "GameExtraData.h"

std::vector<Task*> TaskManager::s_taskQueue;

std::vector<Task<void>*> TaskManager::s_taskQueue;
std::vector<Task<bool>*> TaskManager::taskRemovableQueue;

template<>
bool Task<bool>::Run() noexcept {
__try {
return this->task();
}
__except (EXCEPTION_EXECUTE_HANDLER) {
_MESSAGE("Catched Exception while Running Task %08X", this);
return true;
}
}
template<>
void Task<void>::Run() noexcept {
__try {
this->task();
}
__except (EXCEPTION_EXECUTE_HANDLER) {
_MESSAGE("Catched Exception while Running Task %08X", this);
}
}

///TODO put CS in place.
void TaskManager::Enqueue(Task* task) {
s_taskQueue.push_back(task);
template<IsIntOrVoid T>
void TaskManager::Enqueue(Task<T>* task) {
auto queue = TaskManager::getQueue(task);
queue.push_back(task);
}

template<IsIntOrVoid T>
Task<T>* TaskManager::Enqueue(TaskFuncT<T> task) {
Task<T>* func = new Task(task);
auto queue = TaskManager::getQueue(func);
queue.push_back(func);
return func;
}

void Task::Run() {
this->task();
template<>
std::vector<Task<bool>*>& TaskManager::getQueue(Task<bool>* task) {
return taskRemovableQueue;
}

Task* TaskManager::Enqueue(TaskFunc task) {
Task* func = new Task(task);
s_taskQueue.push_back(func);
return func;
template<>
std::vector<Task<void>*>& TaskManager::getQueue(Task<void>* task) {
return s_taskQueue;
}

void TaskManager::Remove(Task* toRemove){
for (auto task = s_taskQueue.begin(); task != s_taskQueue.end(); ++task) {

template<IsIntOrVoid T>
void TaskManager::Remove(Task<T>* toRemove){
auto& queue = TaskManager::getQueue(toRemove);
for (auto task = queue.begin(); task != queue.end(); ++task) {
if(*task == toRemove){
s_taskQueue.erase(task);
queue.erase(task);
break;
}
}
}

bool TaskManager::IsTaskEnqueued(Task* toCheck){
for (auto task = s_taskQueue.begin(); task != s_taskQueue.end(); ++task) {
template<IsIntOrVoid T>
bool TaskManager::IsTaskEnqueued(Task<T>* toCheck){
auto& queue = TaskManager::getQueue(toCheck);

for (auto task = queue.begin(); task != queue.end(); ++task) {
if(*task == toCheck){
return true;
}
Expand All @@ -44,13 +80,28 @@ void TaskManager::Run() {
for(auto task = s_taskQueue.begin(); task != s_taskQueue.end(); ++task){
(*task)->Run();
}
auto task = taskRemovableQueue.begin();
while(task != taskRemovableQueue.end()){
if ((*task)->Run() == true) {
task = taskRemovableQueue.erase(task);
}
else {
task = ++task;
}
}
}


namespace PluginAPI {
void ReEnqueueTask(Task<void>* task) { return TaskManager::Enqueue(task); }
Task<void>* EnqueueTask(TaskFuncT<void> task) { return TaskManager::Enqueue(task); }
bool IsTaskEnqueued(Task<void>* task) { return TaskManager::IsTaskEnqueued(task); }
void Remove(Task<void>* toRemove) { return TaskManager::Remove(toRemove); }
void ReEnqueueTask(Task<bool>* task) { return TaskManager::Enqueue(task); }
Task<bool>* EnqueueTask(TaskFuncT<bool> task) { return TaskManager::Enqueue(task); }
bool IsTaskEnqueued(Task<bool>* task) { return TaskManager::IsTaskEnqueued(task); }
void Remove(Task<bool>* toRemove) { return TaskManager::Remove(toRemove); }

bool HasTasks() { return TaskManager::HasTasks(); }

bool HasTask() { return TaskManager::HasTasks(); }
bool IsTaskEnqueued(Task* task) { return TaskManager::IsTaskEnqueued(task); }
Task* EnqueueTask(TaskFunc task) { return TaskManager::Enqueue(task); }
void Remove(Task* toRemove) { return TaskManager::Remove(toRemove); }
}
}
50 changes: 34 additions & 16 deletions obse/obse/Tasks.h
Original file line number Diff line number Diff line change
@@ -1,39 +1,57 @@
#pragma once

#include <vector>
#include <vector>
#include <typeinfo>

typedef void (* TaskFunc)();

template<typename T>
concept IsIntOrVoid = std::is_same<T, bool>::value || std::is_same<T, void>::value;


template<IsIntOrVoid T> using TaskFuncT = T (*)();

using TaskFunc = TaskFuncT<void>;

template<IsIntOrVoid T>
class Task {
TaskFunc task;
TaskFuncT<T> task;

public:
Task(TaskFunc task) : task(task) {}
void Run();
Task(TaskFuncT<T> task) noexcept: task(task) {}
T Run() noexcept;
};

class TaskManager {
public:
static bool HasTasks() { return !s_taskQueue.empty(); }
static void Enqueue(Task* task);
static Task* Enqueue(TaskFunc task);
static bool IsTaskEnqueued(Task* task);
static void Remove(Task* task);
static bool HasTasks() noexcept { return !s_taskQueue.empty(); }
template<IsIntOrVoid T> static void Enqueue(Task<T>* task);
template<IsIntOrVoid T> static Task<T>* Enqueue(TaskFuncT<T> task);
template<IsIntOrVoid T> static bool IsTaskEnqueued(Task<T>* task);
template<IsIntOrVoid T> static void Remove(Task<T>* task);
static void Run();

private:
TaskManager();
template<IsIntOrVoid T> static std::vector<Task<T>*>& getQueue(Task<T>* task);

static std::vector<Task<void>*> s_taskQueue;
static std::vector<Task<bool>*> taskRemovableQueue;

static std::vector<Task*> s_taskQueue;
};


namespace PluginAPI{
void EnqueueT(Task* task);
Task* EnqueueTask(TaskFunc task);
bool IsTaskEnqueued(Task* task);
void Remove(Task* task);
void ReEnqueueTask(Task<void>* task);
Task<void>* EnqueueTask(TaskFuncT<void> task);
bool IsTaskEnqueued(Task<void>* task);
void Remove(Task<void>* task);
void ReEnqueueTask(Task<bool>* task);
Task<bool>* EnqueueTask(TaskFuncT<bool> task);
bool IsTaskEnqueued(Task<bool>* task);
void Remove(Task<bool>* task);

bool HasTasks();
}



4 changes: 3 additions & 1 deletion obse/obse/obse.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<BufferSecurityCheck>false</BufferSecurityCheck>
<StringPooling>true</StringPooling>
<LanguageStandard>stdcpplatest</LanguageStandard>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<ConformanceMode>true</ConformanceMode>
<EnableModules>true</EnableModules>
<ExceptionHandling>Sync</ExceptionHandling>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand Down
1 change: 1 addition & 0 deletions obse/obse_editor/obse_editor.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<LanguageStandard>stdcpplatest</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<ExceptionHandling>Sync</ExceptionHandling>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand Down

0 comments on commit 23939fc

Please sign in to comment.