Skip to content

Commit bb5e0eb

Browse files
committed
Create events system for script engine restarting
1 parent eec4a57 commit bb5e0eb

File tree

9 files changed

+214
-28
lines changed

9 files changed

+214
-28
lines changed

src/xrGame/MainMenu.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ CMainMenu* MainMenu() { return (CMainMenu*)g_pGamePersistent->m_pMainMenu; };
6767

6868
CMainMenu::CMainMenu()
6969
{
70+
class CResetEventCb : public CAI_Space::CEventCallback
71+
{
72+
CMainMenu* m_mainmenu;
73+
74+
public:
75+
CResetEventCb(CMainMenu* mm) : m_mainmenu(mm) {}
76+
void ProcessEvent() override
77+
{
78+
m_mainmenu->DestroyInternal(true);
79+
}
80+
};
81+
82+
m_script_reset_event_cid = ai().Subscribe(new CResetEventCb(this), CAI_Space::CNotifier::EVENT_SCRIPT_ENGINE_RESET);
83+
7084
m_Flags.zero();
7185
m_startDialog = NULL;
7286
m_screenshotFrame = u32(-1);
@@ -156,6 +170,8 @@ CMainMenu::~CMainMenu()
156170

157171
xr_delete(m_demo_info_loader);
158172
delete_data(m_pMB_ErrDlgs);
173+
174+
ai().Unsubscribe(m_script_reset_event_cid, CAI_Space::CNotifier::EVENT_SCRIPT_ENGINE_RESET);
159175
}
160176

161177
void CMainMenu::ReadTextureInfo()

src/xrGame/MainMenu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class demo_info_loader;
1515
#include "xrUICore/Callbacks/UIWndCallback.h"
1616
#include "xrUICore/ui_base.h"
1717
#include "DemoInfo.h"
18+
#include "ai_space.h"
1819

1920
namespace gamespy_gp
2021
{
@@ -196,6 +197,8 @@ class CMainMenu : public IMainMenu,
196197
LPCSTR GetCDKeyFromRegistry();
197198

198199
demo_info const* GetDemoInfo(LPCSTR file_name);
200+
201+
CAI_Space::CEventCallback::CID m_script_reset_event_cid;
199202
};
200203

201204
extern CMainMenu* MainMenu();

src/xrGame/ai_space.cpp

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,82 @@
2222
#include "moving_objects.h"
2323
#include "doors_manager.h"
2424

25+
//----------------------- Event processing-----------------------
26+
27+
CAI_Space::CEventCallback::CID CAI_Space::CEventCallbackStorage::RegisterCallback(CEventCallback* cb)
28+
{
29+
m_lock.lock();
30+
31+
size_t i, cb_count = m_callbacks.size();
32+
33+
for (i = 0; i < cb_count; ++i)
34+
{
35+
if (!m_callbacks[i])
36+
{
37+
break;
38+
}
39+
}
40+
41+
if (i == cb_count)
42+
{
43+
m_callbacks.resize(cb_count + 1);
44+
}
45+
46+
m_callbacks[i].reset(cb);
47+
48+
m_lock.unlock();
49+
return i;
50+
}
51+
bool CAI_Space::CEventCallbackStorage::UnregisterCallback(CEventCallback::CID cid)
52+
{
53+
bool result = false;
54+
m_lock.lock();
55+
56+
if (cid < m_callbacks.size() && m_callbacks[cid])
57+
{
58+
m_callbacks[cid].reset(nullptr);
59+
result = true;
60+
}
61+
62+
m_lock.unlock();
63+
return result;
64+
}
65+
66+
void CAI_Space::CEventCallbackStorage::ExecuteCallbacks()
67+
{
68+
m_lock.lock();
69+
70+
for (auto& cb : m_callbacks)
71+
{
72+
if (cb)
73+
{
74+
cb->ProcessEvent();
75+
}
76+
}
77+
78+
m_lock.unlock();
79+
}
80+
81+
CAI_Space::CEventCallback::CID CAI_Space::CNotifier::RegisterCallback(CEventCallback* cb, EEventID event_id)
82+
{
83+
R_ASSERT(event_id < EVENT_COUNT);
84+
return m_callbacks[event_id].RegisterCallback(cb);
85+
}
86+
87+
bool CAI_Space::CNotifier::UnregisterCallback(CEventCallback::CID cid, EEventID event_id)
88+
{
89+
R_ASSERT(event_id < EVENT_COUNT);
90+
return m_callbacks[event_id].UnregisterCallback(cid);
91+
}
92+
93+
void CAI_Space::CNotifier::FireEvent(EEventID event_id)
94+
{
95+
R_ASSERT(event_id < EVENT_COUNT);
96+
m_callbacks[event_id].ExecuteCallbacks();
97+
}
98+
99+
//----------------------- Main CAI_Space stuff-----------------------
100+
25101
static CAI_Space g_ai_space;
26102

27103
CAI_Space& CAI_Space::GetInstance()
@@ -48,14 +124,15 @@ void CAI_Space::init()
48124

49125
VERIFY(!GEnv.ScriptEngine);
50126
GEnv.ScriptEngine = new CScriptEngine();
51-
SetupScriptEngine();
127+
RestartScriptEngine();
52128
}
53129

54130
m_inited = true;
55131
}
56132

57133
CAI_Space::~CAI_Space()
58134
{
135+
m_events_notifier.FireEvent(CNotifier::EVENT_SCRIPT_ENGINE_RESET);
59136
unload();
60137
xr_delete(GEnv.ScriptEngine); // XXX: wrapped into try..catch(...) in vanilla source
61138
}
@@ -130,6 +207,21 @@ void CAI_Space::SetupScriptEngine()
130207
LoadCommonScripts();
131208
}
132209

210+
void CAI_Space::RestartScriptEngine()
211+
{
212+
if (GEnv.ScriptEngine != nullptr)
213+
{
214+
m_events_notifier.FireEvent(CNotifier::EVENT_SCRIPT_ENGINE_RESET);
215+
}
216+
217+
SetupScriptEngine();
218+
#ifdef DEBUG
219+
get_moving_objects().clear();
220+
#endif // DEBUG
221+
222+
m_events_notifier.FireEvent(CNotifier::EVENT_SCRIPT_ENGINE_STARTED);
223+
}
224+
133225
void CAI_Space::load(LPCSTR level_name)
134226
{
135227
VERIFY(m_game_graph);
@@ -173,3 +265,13 @@ void CAI_Space::set_alife(CALifeSimulator* alife_simulator)
173265
return;
174266
SetGameGraph(nullptr);
175267
}
268+
269+
CAI_Space::CEventCallback::CID CAI_Space::Subscribe(CEventCallback* cb, CNotifier::EEventID event_id)
270+
{
271+
return m_events_notifier.RegisterCallback(cb, event_id);
272+
}
273+
274+
bool CAI_Space::Unsubscribe(CAI_Space::CEventCallback::CID cid, CNotifier::EEventID event_id)
275+
{
276+
return m_events_notifier.UnregisterCallback(cid, event_id);
277+
}

src/xrGame/ai_space.h

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#pragma once
1010

1111
#include "xrAICore/AISpaceBase.hpp"
12+
#include "xrCommon/xr_array.h"
1213

1314
#include <memory>
15+
#include <mutex>
1416

1517
class CGameGraph;
1618
class CGameLevelCrossTable;
@@ -30,6 +32,47 @@ class manager;
3032

3133
class CAI_Space : public AISpaceBase
3234
{
35+
public:
36+
class CEventCallback
37+
{
38+
public:
39+
using CID = size_t;
40+
static const CID INVALID_CID = std::numeric_limits<CID>::max();
41+
42+
virtual void ProcessEvent() = 0;
43+
virtual ~CEventCallback(){};
44+
};
45+
46+
class CEventCallbackStorage
47+
{
48+
xr_vector<std::unique_ptr<CEventCallback>> m_callbacks;
49+
std::mutex m_lock;
50+
51+
public:
52+
CEventCallback::CID RegisterCallback(CEventCallback* cb);
53+
bool UnregisterCallback(CEventCallback::CID cid);
54+
void ExecuteCallbacks();
55+
};
56+
57+
class CNotifier
58+
{
59+
public:
60+
enum EEventID
61+
{
62+
EVENT_SCRIPT_ENGINE_STARTED,
63+
EVENT_SCRIPT_ENGINE_RESET,
64+
EVENT_COUNT,
65+
};
66+
67+
private:
68+
xr_array<CEventCallbackStorage, EVENT_COUNT> m_callbacks;
69+
70+
public:
71+
CEventCallback::CID RegisterCallback(CEventCallback* cb, EEventID event_id);
72+
bool UnregisterCallback(CEventCallback::CID cid, EEventID event_id);
73+
void FireEvent(EEventID event_id);
74+
};
75+
3376
private:
3477
friend class CALifeSimulator;
3578
friend class CALifeGraphRegistry;
@@ -39,6 +82,7 @@ class CAI_Space : public AISpaceBase
3982

4083
private:
4184
bool m_inited = false;
85+
CNotifier m_events_notifier;
4286

4387
std::unique_ptr<CEF_Storage> m_ef_storage;
4488
std::unique_ptr<CCoverManager> m_cover_manager;
@@ -54,6 +98,7 @@ class CAI_Space : public AISpaceBase
5498
void set_alife(CALifeSimulator* alife_simulator);
5599
void LoadCommonScripts();
56100
void RegisterScriptClasses();
101+
void SetupScriptEngine();
57102

58103
public:
59104
CAI_Space() = default;
@@ -62,7 +107,10 @@ class CAI_Space : public AISpaceBase
62107
virtual ~CAI_Space();
63108
static CAI_Space& GetInstance();
64109

65-
void SetupScriptEngine();
110+
CEventCallback::CID Subscribe(CEventCallback* cb, CNotifier::EEventID event_id);
111+
bool Unsubscribe(CEventCallback::CID cid, CNotifier::EEventID event_id);
112+
void RestartScriptEngine();
113+
66114
IC CEF_Storage& ef_storage() const;
67115

68116
IC const CALifeSimulator& alife() const;

src/xrGame/alife_simulator.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
LPCSTR alife_section = "alife";
2525

26-
extern void destroy_lua_wpn_params();
2726

2827
CALifeSimulator::CALifeSimulator(IPureServer* server, shared_str* command_line)
2928
: CALifeUpdateManager(server, alife_section), CALifeInteractionManager(server, alife_section),
@@ -32,13 +31,7 @@ CALifeSimulator::CALifeSimulator(IPureServer* server, shared_str* command_line)
3231
// XXX: why do we need to reinitialize script engine?
3332
if (!strstr(Core.Params, "-keep_lua"))
3433
{
35-
destroy_lua_wpn_params();
36-
MainMenu()->DestroyInternal(true);
37-
xr_delete(g_object_factory);
38-
ai().SetupScriptEngine();
39-
#ifdef DEBUG
40-
ai().get_moving_objects().clear();
41-
#endif // DEBUG
34+
ai().RestartScriptEngine();
4235
}
4336

4437
ai().set_alife(this);

src/xrGame/ui/UIWpnParams.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include "UIXmlInit.h"
44
#include "Level.h"
55
#include "game_base_space.h"
6-
#include "ai_space.h"
76
#include "xrScriptEngine/script_engine.hpp"
87
#include "inventory_item_object.h"
98
#include "UIInventoryUtilities.h"
@@ -21,6 +20,22 @@ struct SLuaWpnParams
2120
~SLuaWpnParams();
2221
};
2322

23+
static SLuaWpnParams* g_lua_wpn_params = nullptr;
24+
25+
static CAI_Space::CEventCallback::CID g_wpn_params_cb_cid = CAI_Space::CEventCallback::INVALID_CID;
26+
27+
class CResetEventCb : public CAI_Space::CEventCallback
28+
{
29+
public:
30+
void ProcessEvent() override
31+
{
32+
if (g_lua_wpn_params)
33+
{
34+
xr_delete(g_lua_wpn_params);
35+
}
36+
}
37+
};
38+
2439
SLuaWpnParams::SLuaWpnParams()
2540
{
2641
bool functor_exists;
@@ -34,16 +49,14 @@ SLuaWpnParams::SLuaWpnParams()
3449
VERIFY(functor_exists);
3550
functor_exists = GEnv.ScriptEngine->functor("ui_wpn_params.GetAccuracy", m_functorAccuracy);
3651
VERIFY(functor_exists);
52+
53+
if (g_wpn_params_cb_cid == CAI_Space::CEventCallback::INVALID_CID)
54+
{
55+
g_wpn_params_cb_cid = ai().Subscribe(new CResetEventCb(), CAI_Space::CNotifier::EVENT_SCRIPT_ENGINE_RESET);
56+
}
3757
}
3858

3959
SLuaWpnParams::~SLuaWpnParams() {}
40-
SLuaWpnParams* g_lua_wpn_params = NULL;
41-
42-
void destroy_lua_wpn_params()
43-
{
44-
if (g_lua_wpn_params)
45-
xr_delete(g_lua_wpn_params);
46-
}
4760

4861
// =====================================================================
4962

src/xrGame/xrgame_dll_detach.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,9 @@ void init_game_globals()
5858
extern CUIXml* g_uiSpotXml;
5959
extern CUIXml* pWpnScopeXml;
6060

61-
extern void destroy_lua_wpn_params();
6261

6362
void clean_game_globals()
6463
{
65-
destroy_lua_wpn_params();
6664
// destroy object factory
6765
xr_delete(g_object_factory);
6866
// destroy monster squad global var

src/xrServerEntities/object_factory.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
// Description : Object factory
77
////////////////////////////////////////////////////////////////////////////
88

9-
#ifndef object_factoryH
10-
#define object_factoryH
11-
129
#pragma once
1310

1411
#include "object_item_abstract.h"
@@ -91,4 +88,3 @@ extern CObjectFactory* g_object_factory;
9188
IC const CObjectFactory& object_factory();
9289

9390
#include "object_factory_inline.h"
94-
#endif

0 commit comments

Comments
 (0)