Etterna 0.75.1
Loading...
Searching...
No Matches
MessageManager.h
1#ifndef MessageManager_H
2#define MessageManager_H
3
4#include "LuaManager.h"
5struct lua_State;
6class LuaTable;
7class LuaReference;
8
10enum MessageID
11{
12 Message_CurrentGameChanged,
13 Message_CurrentStyleChanged,
14 Message_PlayModeChanged,
15 Message_CoinsChanged,
16 Message_CurrentSongChanged,
17 Message_CurrentStepsChanged,
18 Message_GameplayLeadInChanged,
19 Message_GameplayModeChanged,
20 Message_EditStepsTypeChanged,
21 Message_EditCourseDifficultyChanged,
22 Message_EditSourceStepsChanged,
23 Message_EditSourceStepsTypeChanged,
24 Message_PreferredStepsTypeChanged,
25 Message_PreferredDifficultyP1Changed,
26 Message_PreferredDifficultyP2Changed,
27 Message_PreferredCourseDifficultyP1Changed,
28 Message_PreferredCourseDifficultyP2Changed,
29 Message_EditCourseEntryIndexChanged,
30 Message_EditLocalProfileIDChanged,
31 Message_NoteCrossed,
32 Message_NoteWillCrossIn400Ms,
33 Message_NoteWillCrossIn800Ms,
34 Message_NoteWillCrossIn1200Ms,
35 Message_CardRemovedP1,
36 Message_CardRemovedP2,
37 Message_BeatCrossed,
38 Message_MenuUpP1,
39 Message_MenuUpP2,
40 Message_MenuDownP1,
41 Message_MenuDownP2,
42 Message_MenuLeftP1,
43 Message_MenuLeftP2,
44 Message_MenuRightP1,
45 Message_MenuRightP2,
46 Message_MenuStartP1,
47 Message_MenuStartP2,
48 Message_MenuSelectionChanged,
49 Message_PlayerJoined,
50 Message_PlayerUnjoined,
51 Message_AutosyncChanged,
52 Message_PreferredSongGroupChanged,
53 Message_PreferredCourseGroupChanged,
54 Message_SortOrderChanged,
55 Message_LessonTry1,
56 Message_LessonTry2,
57 Message_LessonTry3,
58 Message_LessonCleared,
59 Message_LessonFailed,
60 Message_StorageDevicesChanged,
61 Message_AutoJoyMappingApplied,
62 Message_ScreenChanged,
63 Message_SongModified,
64 Message_ScoreMultiplierChangedP1,
65 Message_ScoreMultiplierChangedP2,
66 Message_StarPowerChangedP1,
67 Message_StarPowerChangedP2,
68 Message_CurrentComboChangedP1,
69 Message_CurrentComboChangedP2,
70 Message_StarMeterChangedP1,
71 Message_StarMeterChangedP2,
72 Message_LifeMeterChangedP1,
73 Message_LifeMeterChangedP2,
74 Message_UpdateScreenHeader,
75 Message_LeftClick,
76 Message_RightClick,
77 Message_MiddleClick,
78 Message_MouseWheelUp,
79 Message_MouseWheelDown,
80 Message_ReloadedMetrics,
81 Message_ReloadedScripts,
82 Message_ReloadedOverlayScreens,
83 Message_ReloadedTextures,
84 Message_ReloadedCurrentSong,
85 Message_ReloadedCurrentPack,
86 Message_FavoritesUpdated,
87 Message_PermamirrorUpdated,
88 Message_GoalsUpdated,
89 Message_SpectatorInputUpdate,
90 Message_SpectatorHoldUpdate,
91 Message_SpectatorMineUpdate,
92 Message_SpectatorMissUpdate,
93 Message_SpectatorV2Update,
94 NUM_MessageID, // leave this at the end
95 MessageID_Invalid
96};
97auto
98MessageIDToString(MessageID m) -> const std::string&;
99
101{
102 explicit Message(const std::string& s);
103 explicit Message(MessageID id);
104 Message(const std::string& s, const LuaReference& params);
105 ~Message();
106
107 void SetName(const std::string& sName) { m_sName = sName; }
108 [[nodiscard]] auto GetName() const -> std::string { return m_sName; }
109
110 [[nodiscard]] auto IsBroadcast() const -> bool { return m_bBroadcast; }
111 void SetBroadcast(const bool b) { m_bBroadcast = b; }
112
113 void PushParamTable(lua_State* L);
114 [[nodiscard]] auto GetParamTable() const -> const LuaReference&;
115 void SetParamTable(const LuaReference& params);
116
117 void GetParamFromStack(lua_State* L, const std::string& sName) const;
118 void SetParamFromStack(lua_State* L, const std::string& sName);
119
120 template<typename T>
121 auto GetParam(const std::string& sName, T& val) const -> bool
122 {
123 Lua* L = LUA->Get();
124 GetParamFromStack(L, sName);
125 bool bRet = LuaHelpers::Pop(L, val);
126 LUA->Release(L);
127 return bRet;
128 }
129
130 template<typename T>
131 void SetParam(const std::string& sName, const T& val)
132 {
133 Lua* L = LUA->Get();
134 LuaHelpers::Push(L, val);
135 SetParamFromStack(L, sName);
136 LUA->Release(L);
137 }
138
139 template<typename T>
140 void SetParam(const std::string& sName, const std::vector<T>& val)
141 {
142 Lua* L = LUA->Get();
143 LuaHelpers::CreateTableFromArray(val, L);
144 SetParamFromStack(L, sName);
145 LUA->Release(L);
146 }
147
148 auto operator==(const std::string& s) const -> bool { return m_sName == s; }
149 auto operator==(const MessageID id) const -> bool
150 {
151 return MessageIDToString(id) == m_sName;
152 }
153
154 private:
155 std::string m_sName;
156 LuaTable* m_pParams;
157 bool m_bBroadcast;
158
159 auto operator=(const Message& rhs) -> Message&; // don't use
160 /* Work around a gcc bug where HandleMessage( Message("Init") ) fails
161 * because the copy ctor is private. The copy ctor is not even used so I
162 * have no idea why it being private is an issue. Also, if the Message
163 * object were constructed implicitly (remove explicit above), it works:
164 * HandleMessage( "Init" ). Leaving this undefined but public changes a
165 * compile time error into a link time error. Hmm.*/
166 public:
167 Message(const Message& rhs); // don't use
168};
169
171{
172 public:
173 virtual ~IMessageSubscriber() = default;
174 virtual void HandleMessage(const Message& msg) = 0;
175 void ClearMessages(const std::string& sMessage = "");
176
177 private:
178 friend class MessageManager;
179};
180
182{
183 public:
184 MessageSubscriber() = default;
186 auto operator=(const MessageSubscriber& cpy) -> MessageSubscriber&;
187
188 //
189 // Messages
190 //
191 void SubscribeToMessage(
192 MessageID message); // will automatically unsubscribe
193 void SubscribeToMessage(
194 const std::string& sMessageName); // will automatically unsubscribe
195
196 void UnsubscribeAll();
197
198 private:
199 std::vector<std::string> m_vsSubscribedTo;
200};
201
204{
205 public:
208
209 static void Subscribe(IMessageSubscriber* pSubscriber,
210 const std::string& sMessage);
211 static void Subscribe(IMessageSubscriber* pSubscriber, MessageID m);
212 static void Unsubscribe(IMessageSubscriber* pSubscriber,
213 const std::string& sMessage);
214 static void Unsubscribe(IMessageSubscriber* pSubscriber, MessageID m);
215 void Broadcast(Message& msg) const;
216 void Broadcast(const std::string& sMessage) const;
217 void Broadcast(MessageID m) const;
218 static auto IsSubscribedToMessage(IMessageSubscriber* pSubscriber,
219 const std::string& sMessage) -> bool;
220
221 static auto IsSubscribedToMessage(IMessageSubscriber* pSubscriber,
222 const MessageID message) -> bool
223 {
224 return IsSubscribedToMessage(pSubscriber, MessageIDToString(message));
225 }
226
227 void SetLogging(bool set) { m_Logging = set; }
228 bool m_Logging;
229
230 // Lua
231 void PushSelf(lua_State* L);
232};
233
234extern MessageManager*
235 MESSAGEMAN; // global and accessible from anywhere in our program
236
237template<class T>
239{
240 MessageID mSendWhenChanged;
241 T val;
242
243 public:
244 explicit BroadcastOnChange(const MessageID m)
245 {
246 val = T();
247 mSendWhenChanged = m;
248 }
249 [[nodiscard]] auto Get() const -> T { return val; }
250 void Set(T t)
251 {
252 val = t;
253 MESSAGEMAN->Broadcast(MessageIDToString(mSendWhenChanged));
254 }
255 operator T() const { return val; }
256 auto operator==(const T& other) const -> bool { return val == other; }
257 auto operator!=(const T& other) const -> bool { return val != other; }
258};
259
261namespace LuaHelpers {
262template<class T>
263void
264Push(lua_State* L, const BroadcastOnChange<T>& Object)
265{
266 LuaHelpers::Push<T>(L, Object.Get());
267}
268}
269
270template<class T>
272{
273 MessageID mSendWhenChanged;
274 T* val;
275
276 public:
277 explicit BroadcastOnChangePtr(const MessageID m)
278 {
279 mSendWhenChanged = m;
280 val = nullptr;
281 }
282 [[nodiscard]] auto Get() const -> T* { return val; }
283 void Set(T* t)
284 {
285 val = t;
286 if (MESSAGEMAN) {
287 MESSAGEMAN->Broadcast(MessageIDToString(mSendWhenChanged));
288 }
289 }
290
291 /* This is only intended to be used for setting temporary values; always
292 * restore the original value when finished, so listeners don't get confused
293 * due to missing a message. */
294 void SetWithoutBroadcast(T* t) { val = t; }
295 operator T*() const { return val; }
296 auto operator->() const -> T* { return val; }
297};
298
299template<class T>
301{
302 MessageID mSendWhenChanged;
303 T* val;
304
305 public:
306 explicit BroadcastOnChangePtrWithSelf(const MessageID m)
307 {
308 mSendWhenChanged = m;
309 val = nullptr;
310 }
311 [[nodiscard]] auto Get() const -> T* { return val; }
312 void Set(T* t)
313 {
314 val = t;
315 if (MESSAGEMAN) {
316 Message msg(MessageIDToString(mSendWhenChanged));
317 msg.SetParam("ptr", t);
318 MESSAGEMAN->Broadcast(msg);
319 }
320 }
321
322 /* This is only intended to be used for setting temporary values; always
323 * restore the original value when finished, so listeners don't get confused
324 * due to missing a message. */
325 void SetWithoutBroadcast(T* t) { val = t; }
326 operator T*() const { return val; }
327 auto operator->() const -> T* { return val; }
328};
329
330#endif
Definition MessageManager.h:301
Definition MessageManager.h:272
Definition MessageManager.h:239
Definition MessageManager.h:171
A self-cleaning Lua reference.
Definition LuaReference.h:10
Definition LuaReference.h:106
Deliver messages to any part of the program as needed.
Definition MessageManager.h:204
Definition MessageManager.h:182
Utilities for working with Lua.
Definition LuaReference.cpp:172
Definition MessageManager.h:101