1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef LUA_HANDLE_H
4 #define LUA_HANDLE_H
5 #include <boost/cstdint.hpp>
6 
7 #include "System/EventClient.h"
8 //FIXME#include "LuaArrays.h"
9 #include "LuaContextData.h"
10 #include "LuaHashString.h"
11 #include "lib/lua/include/LuaInclude.h" //FIXME needed for GetLuaContextData
12 
13 #include <string>
14 #include <vector>
15 #include <set>
16 using std::string;
17 using std::vector;
18 using std::set;
19 
20 
21 #define LUA_HANDLE_ORDER_RULES            100
22 #define LUA_HANDLE_ORDER_UNITS            200
23 #define LUA_HANDLE_ORDER_GAIA             300
24 #define LUA_HANDLE_ORDER_RULES_UNSYNCED  1100
25 #define LUA_HANDLE_ORDER_UNITS_UNSYNCED  1200
26 #define LUA_HANDLE_ORDER_GAIA_UNSYNCED   1300
27 #define LUA_HANDLE_ORDER_UI              2000
28 #define LUA_HANDLE_ORDER_INTRO           3000
29 
30 
31 class CUnit;
32 class CWeapon;
33 class CFeature;
34 class CProjectile;
35 struct Command;
36 struct SRectangle;
37 struct LuaHashString;
38 struct lua_State;
39 class LuaRBOs;
40 class LuaFBOs;
41 class LuaTextures;
42 class LuaShaders;
43 class CLuaDisplayLists;
44 class CLuaRules;
45 
46 
47 class CLuaHandle : public CEventClient
48 {
49 	public:
50 		void CheckStack();
GetCallInErrors()51 		int GetCallInErrors() const { return callinErrors; }
ResetCallinErrors()52 		void ResetCallinErrors() { callinErrors = 0; }
53 
54 	public:
55 	#define PERMISSIONS_FUNCS(Name, type, dataArg) \
56 		void Set ## Name(type _ ## dataArg) { GetLuaContextData(L)->dataArg = _ ## dataArg; } \
57 		type Get ## Name() const { return GetLuaContextData(L)->dataArg; } \
58 		static void SetHandle ## Name(const lua_State* L, type _ ## dataArg) { GetLuaContextData(L)->dataArg = _ ## dataArg;; } \
59 		static type GetHandle ## Name(const lua_State* L) { return GetLuaContextData(L)->dataArg; }
60 
61 		PERMISSIONS_FUNCS(FullRead,     bool, fullRead); // virtual function in CEventClient
62 		PERMISSIONS_FUNCS(FullCtrl,     bool, fullCtrl);
63 		PERMISSIONS_FUNCS(CtrlTeam,     int,  ctrlTeam);
64 		PERMISSIONS_FUNCS(ReadTeam,     int,  readTeam);
65 		PERMISSIONS_FUNCS(ReadAllyTeam, int,  readAllyTeam); // virtual function in CEventClient
66 		PERMISSIONS_FUNCS(SelectTeam,   int,  selectTeam);
67 
68 	#undef PERMISSIONS_FUNCS
69 
GetHandleSynced(const lua_State * L)70 		static bool GetHandleSynced(const lua_State* L) { return GetLuaContextData(L)->synced; }
71 
GetUserMode()72 		bool GetUserMode() const { return userMode; }
GetHandleUserMode(const lua_State * L)73 		static bool GetHandleUserMode(const lua_State* L) { return GetLuaContextData(L)->owner->GetUserMode(); }
74 
CheckModUICtrl()75 		bool CheckModUICtrl() const { return GetModUICtrl() || GetUserMode(); }
CheckModUICtrl(lua_State * L)76 		static bool CheckModUICtrl(lua_State* L) { return GetModUICtrl() || GetHandleUserMode(L); }
77 
GetHandleAllowChanges(const lua_State * L)78 		static int GetHandleAllowChanges(const lua_State* L) { return GetLuaContextData(L)->allowChanges; }
79 
GetHandle(lua_State * L)80 		static CLuaHandle* GetHandle(lua_State* L) { return GetLuaContextData(L)->owner; }
81 
SetHandleRunning(lua_State * L,const bool _running)82 		static void SetHandleRunning(lua_State* L, const bool _running) {
83 			GetLuaContextData(L)->running += (_running) ? +1 : -1;
84 			assert( GetLuaContextData(L)->running >= 0);
85 		}
IsHandleRunning(lua_State * L)86 		static bool IsHandleRunning(lua_State* L) { return (GetLuaContextData(L)->running > 0); }
IsRunning()87 		bool IsRunning() const { return IsHandleRunning(L); }
88 
IsValid()89 		bool IsValid() const { return (L != NULL); }
90 
91 		//FIXME needed by LuaSyncedTable (can be solved cleaner?)
GetLuaState()92 		lua_State* GetLuaState() const { return L; }
93 
94 		LuaShaders& GetShaders(const lua_State* L = NULL) { return GetLuaContextData(L)->shaders; }
95 		LuaTextures& GetTextures(const lua_State* L = NULL) { return GetLuaContextData(L)->textures; }
96 		LuaFBOs& GetFBOs(const lua_State* L = NULL) { return GetLuaContextData(L)->fbos; }
97 		LuaRBOs& GetRBOs(const lua_State* L = NULL) { return GetLuaContextData(L)->rbos; }
98 		CLuaDisplayLists& GetDisplayLists(const lua_State* L = NULL) { return GetLuaContextData(L)->displayLists; }
99 
100 	public: // call-ins
WantsEvent(const string & name)101 		bool WantsEvent(const string& name) { return HasCallIn(L, name); }
102 		virtual bool HasCallIn(lua_State* L, const string& name);
103 		virtual bool UpdateCallIn(lua_State* L, const string& name);
104 
105 		void Load(IArchive* archive);
106 
107 		void GamePreload();
108 		void GameStart();
109 		void GameOver(const std::vector<unsigned char>& winningAllyTeams);
110 		void GamePaused(int playerID, bool paused);
111 		void GameFrame(int frameNum);
112 		void GameID(const unsigned char* gameID, unsigned int numBytes);
113 
114 		void TeamDied(int teamID);
115 		void TeamChanged(int teamID);
116 		void PlayerChanged(int playerID);
117 		void PlayerAdded(int playerID);
118 		void PlayerRemoved(int playerID, int reason);
119 
120 		void UnitCreated(const CUnit* unit, const CUnit* builder);
121 		void UnitFinished(const CUnit* unit);
122 		void UnitFromFactory(const CUnit* unit, const CUnit* factory,
123 		                     bool userOrders);
124 		void UnitDestroyed(const CUnit* unit, const CUnit* attacker);
125 		void UnitTaken(const CUnit* unit, int oldTeam, int newTeam);
126 		void UnitGiven(const CUnit* unit, int oldTeam, int newTeam);
127 
128 		void UnitIdle(const CUnit* unit);
129 		void UnitCommand(const CUnit* unit, const Command& command);
130 		void UnitCmdDone(const CUnit* unit, const Command& command);
131 		void UnitDamaged(
132 			const CUnit* unit,
133 			const CUnit* attacker,
134 			float damage,
135 			int weaponDefID,
136 			int projectileID,
137 			bool paralyzer);
138 		void UnitExperience(const CUnit* unit, float oldExperience);
139 		void UnitHarvestStorageFull(const CUnit* unit);
140 
141 		void UnitSeismicPing(const CUnit* unit, int allyTeam,
142 		                     const float3& pos, float strength);
143 		void UnitEnteredRadar(const CUnit* unit, int allyTeam);
144 		void UnitEnteredLos(const CUnit* unit, int allyTeam);
145 		void UnitLeftRadar(const CUnit* unit, int allyTeam);
146 		void UnitLeftLos(const CUnit* unit, int allyTeam);
147 
148 		void UnitEnteredWater(const CUnit* unit);
149 		void UnitEnteredAir(const CUnit* unit);
150 		void UnitLeftWater(const CUnit* unit);
151 		void UnitLeftAir(const CUnit* unit);
152 
153 		void UnitLoaded(const CUnit* unit, const CUnit* transport);
154 		void UnitUnloaded(const CUnit* unit, const CUnit* transport);
155 
156 		void UnitCloaked(const CUnit* unit);
157 		void UnitDecloaked(const CUnit* unit);
158 
159 		void UnitUnitCollision(const CUnit* collider, const CUnit* collidee);
160 		void UnitFeatureCollision(const CUnit* collider, const CFeature* collidee);
161 		void UnitMoveFailed(const CUnit* unit);
162 
163 		void FeatureCreated(const CFeature* feature);
164 		void FeatureDestroyed(const CFeature* feature);
165 		void FeatureDamaged(
166 			const CFeature* feature,
167 			const CUnit* attacker,
168 			float damage,
169 			int weaponDefID,
170 			int projectileID);
171 
172 		void ProjectileCreated(const CProjectile* p);
173 		void ProjectileDestroyed(const CProjectile* p);
174 
175 		bool Explosion(int weaponID, int projectileID, const float3& pos, const CUnit* owner);
176 
177 		void StockpileChanged(const CUnit* owner,
178 		                      const CWeapon* weapon, int oldCount);
179 
180 		void Save(zipFile archive);
181 
182 		void UnsyncedHeightMapUpdate(const SRectangle& rect);
183 		void Update();
184 
185 		bool KeyPress(int key, bool isRepeat);
186 		bool KeyRelease(int key);
187 		bool TextInput(const std::string& utf8);
188 		bool MouseMove(int x, int y, int dx, int dy, int button);
189 		bool MousePress(int x, int y, int button);
190 		void MouseRelease(int x, int y, int button);
191 		bool MouseWheel(bool up, float value);
192 		bool JoystickEvent(const std::string& event, int val1, int val2);
193 		bool IsAbove(int x, int y);
194 		string GetTooltip(int x, int y);
195 
196 		bool DefaultCommand(const CUnit* unit, const CFeature* feature, int& cmd);
197 
198 		bool CommandNotify(const Command& cmd);
199 
200 		bool AddConsoleLine(const string& msg, const string& section, int level);
201 
202 		bool GroupChanged(int groupID);
203 
204 		bool GameSetup(const string& state, bool& ready,
205 		               const map<int, string>& playerStates);
206 
207 		const char* RecvSkirmishAIMessage(int aiID, const char* data, int inSize);
208 
209 		string WorldTooltip(const CUnit* unit,
210 		                    const CFeature* feature,
211 		                    const float3* groundPos);
212 
213 		bool MapDrawCmd(int playerID, int type,
214 		                const float3* pos0,
215 		                const float3* pos1,
216 		                const string* labe);
217 
218 		void ViewResize();
219 
220 		void DrawGenesis();
221 		void DrawWorld();
222 		void DrawWorldPreUnit();
223 		void DrawWorldShadow();
224 		void DrawWorldReflection();
225 		void DrawWorldRefraction();
226 		void DrawScreenEffects();
227 		void DrawScreen();
228 		void DrawInMiniMap();
229 		void DrawInMiniMapBackground();
230 
231 		void GameProgress(int frameNum);
232 
233 		void CollectGarbage();
234 
235 	public: // Non-eventhandler call-ins
236 		void Shutdown();
237 		bool GotChatMsg(const string& msg, int playerID);
238 		bool RecvLuaMsg(const string& msg, int playerID);
239 
240 	public: // custom call-in  (inter-script calls)
HasXCall(const string & funcName)241 		bool HasXCall(const string& funcName) { return HasCallIn(L, funcName); }
242 		int XCall(lua_State* srcState, const string& funcName);
243 
244 	protected:
245 		CLuaHandle(const string& name, int order, bool userMode, bool synced);
246 		virtual ~CLuaHandle();
247 
248 		void KillLua();
249 
250 		static void PushTracebackFuncToRegistry(lua_State* L);
251 
252 		bool AddBasicCalls(lua_State* L);
253 		bool LoadCode(lua_State* L, const string& code, const string& debug);
254 		static bool AddEntriesToTable(lua_State* L, const char* name, bool (*entriesFunc)(lua_State*));
255 
256 		/// returns error code and sets traceback on error
257 		int  RunCallInTraceback(lua_State* L, const LuaHashString* hs, int inArgs, int outArgs, int errFuncIndex, std::string& tracebackMsg, bool popErrFunc);
258 		/// returns false and prints message to log on error
259 		bool RunCallInTraceback(lua_State* L, const LuaHashString& hs, int inArgs, int outArgs, int errFuncIndex, bool popErrFunc = true);
260 		/// returns false and and sets errormessage on error
261 		bool RunCallIn(lua_State* L, int inArgs, int outArgs, std::string& errormessage);
262 		/// returns false and prints message to log on error
263 		bool RunCallIn(lua_State* L, const LuaHashString& hs, int inArgs, int outArgs);
264 
265 		void LosCallIn(const LuaHashString& hs, const CUnit* unit, int allyTeam);
266 		void UnitCallIn(const LuaHashString& hs, const CUnit* unit);
267 
268 		void RunDrawCallIn(const LuaHashString& hs);
269 
270 	protected:
271 		bool userMode;
272 
273 		lua_State* L;
274 		luaContextData D;
275 
276 		lua_State* L_GC;
277 
278 		bool killMe;
279 		string killMsg;
280 
281 		vector<bool> watchUnitDefs;
282 		vector<bool> watchFeatureDefs;
283 		vector<bool> watchWeaponDefs; // for the Explosion call-in
284 
285 		int callinErrors;
286 
287 	private: // call-outs
288 		static int KillActiveHandle(lua_State* L);
289 		static int CallOutGetName(lua_State* L);
290 		static int CallOutGetSynced(lua_State* L);
291 		static int CallOutGetFullCtrl(lua_State* L);
292 		static int CallOutGetFullRead(lua_State* L);
293 		static int CallOutGetCtrlTeam(lua_State* L);
294 		static int CallOutGetReadTeam(lua_State* L);
295 		static int CallOutGetReadAllyTeam(lua_State* L);
296 		static int CallOutGetSelectTeam(lua_State* L);
297 		static int CallOutGetGlobal(lua_State* L);
298 		static int CallOutGetRegistry(lua_State* L);
299 		static int CallOutGetCallInList(lua_State* L);
300 		static int CallOutUpdateCallIn(lua_State* L);
301 		static int CallOutIsEngineMinVersion(lua_State* L);
302 
303 	public: // static
GetActiveShaders(lua_State * L)304 		static inline LuaShaders& GetActiveShaders(lua_State* L)  { return GetLuaContextData(L)->shaders; }
GetActiveTextures(lua_State * L)305 		static inline LuaTextures& GetActiveTextures(lua_State* L) { return GetLuaContextData(L)->textures; }
GetActiveFBOs(lua_State * L)306 		static inline LuaFBOs& GetActiveFBOs(lua_State* L) { return GetLuaContextData(L)->fbos; }
GetActiveRBOs(lua_State * L)307 		static inline LuaRBOs& GetActiveRBOs(lua_State* L)     { return GetLuaContextData(L)->rbos; }
GetActiveDisplayLists(lua_State * L)308 		static inline CLuaDisplayLists& GetActiveDisplayLists(lua_State* L) { return GetLuaContextData(L)->displayLists; }
309 
SetDevMode(bool value)310 		static void SetDevMode(bool value) { devMode = value; }
GetDevMode()311 		static bool GetDevMode() { return devMode; }
312 
SetModUICtrl(bool value)313 		static void SetModUICtrl(bool value) { modUICtrl = value; }
GetModUICtrl()314 		static bool GetModUICtrl() { return modUICtrl; }
315 
316 		static void HandleLuaMsg(int playerID, int script, int mode,
317 			const std::vector<boost::uint8_t>& msg);
318 
319 	protected: // static
320 		static bool devMode; // allows real file access
321 		static bool modUICtrl; // allows non-user scripts to use UI controls
322 
323 		// FIXME: because CLuaUnitScript needs to access RunCallIn
324 		friend class CLuaUnitScript;
325 
326 		// FIXME needs access to L & RunCallIn
327 		friend class CLuaRules;
328 };
329 
330 
RunCallIn(lua_State * L,const LuaHashString & hs,int inArgs,int outArgs)331 inline bool CLuaHandle::RunCallIn(lua_State* L, const LuaHashString& hs, int inArgs, int outArgs)
332 {
333 	return RunCallInTraceback(L, hs, inArgs, outArgs, 0, false);
334 }
335 
336 
RunCallIn(lua_State * L,int inArgs,int outArgs,std::string & errorMsg)337 inline bool CLuaHandle::RunCallIn(lua_State* L, int inArgs, int outArgs, std::string& errorMsg)
338 {
339 	return RunCallInTraceback(L, NULL, inArgs, outArgs, 0, errorMsg, false);
340 }
341 
342 
343 /******************************************************************************/
344 /******************************************************************************/
345 
346 
347 #endif /* LUA_HANDLE_H */
348 
349