1 #include "hook_api.h"
2
3 #include "globalincs/pstypes.h"
4
5 #include <utility>
6
7 namespace scripting {
8
9 namespace {
10
11 class HookManager {
12 public:
addHook(HookBase * hook)13 int32_t addHook(HookBase* hook)
14 {
15 Assertion(std::find_if(_hooks.cbegin(),
16 _hooks.cend(),
17 [hook](const HookBase* test) { return test->getHookName() == hook->getHookName(); }) ==
18 _hooks.cend(),
19 "Hook '%s' already exists!",
20 hook->getHookName().c_str());
21
22 const auto id = ++_lastId;
23 _hooks.push_back(hook);
24 return id;
25 }
26
addHookWithId(HookBase * hook)27 void addHookWithId(HookBase* hook)
28 {
29 Assertion(std::find_if(_hooks.cbegin(),
30 _hooks.cend(),
31 [hook](const HookBase* test) { return test->getHookName() == hook->getHookName(); }) ==
32 _hooks.cend(),
33 "Hook '%s' already exists!",
34 hook->getHookName().c_str());
35
36 _hooks.push_back(hook);
37 }
38
getHooks() const39 const SCP_vector<HookBase*>& getHooks() const { return _hooks; }
40
41 private:
42 int32_t _lastId = CHA_LAST;
43 SCP_vector<HookBase*> _hooks;
44 };
45
getHookManager()46 HookManager& getHookManager()
47 {
48 static HookManager mgr;
49 return mgr;
50 }
51 } // namespace
52
53 namespace detail {
convert_arg_type(object * objp)54 ade_odata_setter<object_h> convert_arg_type(object* objp)
55 {
56 return ade_object_to_odata(objp != nullptr ? OBJ_INDEX(objp) : -1);
57 }
58 } // namespace detail
59
HookVariableDocumentation(const char * name_,ade_type_info type_,const char * description_)60 HookVariableDocumentation::HookVariableDocumentation(const char* name_, ade_type_info type_, const char* description_)
61 : name(name_), type(std::move(type_)), description(description_)
62 {
63 }
64
HookBase(SCP_string hookName,SCP_string description,SCP_vector<HookVariableDocumentation> parameters,int32_t hookId)65 HookBase::HookBase(SCP_string hookName,
66 SCP_string description,
67 SCP_vector<HookVariableDocumentation> parameters,
68 int32_t hookId)
69 : _hookName(std::move(hookName)), _description(std::move(description)), _parameters(std::move(parameters))
70 {
71 // If we specify a forced id then use that. This is for special hooks that need a guaranteed id
72 if (hookId >= 0) {
73 _hookId = hookId;
74 getHookManager().addHookWithId(this);
75 } else {
76 _hookId = getHookManager().addHook(this);
77 }
78 }
79
getHookName() const80 const SCP_string& HookBase::getHookName() const { return _hookName; }
getDescription() const81 const SCP_string& HookBase::getDescription() const { return _description; }
getParameters() const82 const SCP_vector<HookVariableDocumentation>& HookBase::getParameters() const { return _parameters; }
getHookId() const83 int32_t HookBase::getHookId() const { return _hookId; }
84 HookBase::~HookBase() = default;
85
Factory(SCP_string hookName,SCP_string description,SCP_vector<HookVariableDocumentation> parameters,int32_t hookId)86 std::shared_ptr<Hook> Hook::Factory(SCP_string hookName,
87 SCP_string description,
88 SCP_vector<HookVariableDocumentation> parameters,
89 int32_t hookId)
90 {
91 return std::make_shared<Hook>(std::move(hookName), std::move(description), std::move(parameters), hookId);
92 }
Factory(SCP_string hookName,int32_t hookId)93 std::shared_ptr<Hook> Hook::Factory(SCP_string hookName, int32_t hookId)
94 {
95 return std::make_shared<Hook>(std::move(hookName), SCP_string(), SCP_vector<HookVariableDocumentation>(), hookId);
96 }
Hook(SCP_string hookName,SCP_string description,SCP_vector<HookVariableDocumentation> parameters,int32_t hookId)97 Hook::Hook(SCP_string hookName,
98 SCP_string description,
99 SCP_vector<HookVariableDocumentation> parameters,
100 int32_t hookId)
101 : HookBase(std::move(hookName), std::move(description), std::move(parameters), hookId)
102 {
103 }
104 Hook::~Hook() = default;
105
isOverridable() const106 bool Hook::isOverridable() const { return false; }
107
OverridableHook(SCP_string hookName,SCP_string description,SCP_vector<HookVariableDocumentation> parameters,int32_t hookId)108 OverridableHook::OverridableHook(SCP_string hookName,
109 SCP_string description,
110 SCP_vector<HookVariableDocumentation> parameters,
111 int32_t hookId)
112 : Hook(std::move(hookName), std::move(description), std::move(parameters), hookId)
113 {
114 }
115 OverridableHook::~OverridableHook() = default;
116
Factory(SCP_string hookName,SCP_string description,SCP_vector<HookVariableDocumentation> parameters,int32_t hookId)117 std::shared_ptr<OverridableHook> OverridableHook::Factory(SCP_string hookName,
118 SCP_string description,
119 SCP_vector<HookVariableDocumentation> parameters,
120 int32_t hookId)
121 {
122 return std::make_shared<OverridableHook>(std::move(hookName),
123 std::move(description),
124 std::move(parameters),
125 hookId);
126 }
isOverridable() const127 bool OverridableHook::isOverridable() const { return true; }
128
getHooks()129 const SCP_vector<HookBase*>& getHooks() { return getHookManager().getHooks(); }
130
131 } // namespace scripting
132