diff --git a/stepmania/src/LuaManager.cpp b/stepmania/src/LuaManager.cpp index 91a8852ef6..4fcfe26eb1 100644 --- a/stepmania/src/LuaManager.cpp +++ b/stepmania/src/LuaManager.cpp @@ -202,7 +202,11 @@ LuaManager::~LuaManager() void LuaManager::ResetState() { if( L != NULL ) + { + LuaReference::BeforeResetAll(); + lua_close( L ); + } L = lua_open(); ASSERT( L ); @@ -212,6 +216,7 @@ void LuaManager::ResetState() luaopen_base( L ); luaopen_math( L ); luaopen_string( L ); + luaopen_table( L ); lua_settop(L, 0); // luaopen_* pushes stuff onto the stack that we don't need for( const LuaFunctionList *p = g_LuaFunctions; p; p=p->next ) @@ -226,7 +231,7 @@ void LuaManager::ResetState() } } - LuaReference::ReRegisterAll(); + LuaReference::AfterResetAll(); } void LuaManager::PrepareExpression( CString &sInOut ) diff --git a/stepmania/src/LuaReference.cpp b/stepmania/src/LuaReference.cpp index 31e094ca9d..9011981b2e 100644 --- a/stepmania/src/LuaReference.cpp +++ b/stepmania/src/LuaReference.cpp @@ -3,6 +3,7 @@ #include "LuaManager.h" #include "LuaBinding.h" #include "Foreach.h" +#include "RageLog.h" #include "SubscriptionManager.h" template<> @@ -74,10 +75,6 @@ int LuaReference::GetLuaType() const return iRet; } -void LuaReference::Register() -{ -} - void LuaReference::Unregister() { if( LUA == NULL ) @@ -87,7 +84,15 @@ void LuaReference::Unregister() m_iReference = LUA_NOREF; } -void LuaReference::ReRegisterAll() +void LuaReference::BeforeResetAll() +{ + if( SubscriptionManager::s_pSubscribers == NULL ) + return; + FOREACHS( LuaReference*, *SubscriptionManager::s_pSubscribers, p ) + (*p)->BeforeReset(); +} + +void LuaReference::AfterResetAll() { if( SubscriptionManager::s_pSubscribers == NULL ) return; @@ -120,6 +125,44 @@ void LuaExpression::Register() this->SetFromStack(); } +void LuaData::BeforeReset() +{ + /* Call Serialize(t), where t is our referenced object. */ + this->PushSelf( LUA->L ); + + lua_pushstring( LUA->L, "Serialize" ); + lua_gettable( LUA->L, LUA_GLOBALSINDEX ); + + if( lua_isnil(LUA->L, -1) ) + FAIL_M( "Serialize() missing" ); + + lua_call( LUA->L, 0, 1 ); + + /* The return value is a string, which we store in m_sSerializedData. */ + const char *pString = lua_tostring( LUA->L, -1 ); + if( pString == NULL ) + FAIL_M( "Serialize() didn't return a string" ); + + m_sSerializedData = pString; +} + +void LuaData::Register() +{ + /* Restore the serialized data by evaluating the serialized data. */ + CString sError; + if( !LUA->RunScript( m_sSerializedData, "serialization", sError, 1 ) ) + { + /* Serialize() should never return an invalid script. Drop the failed + * script into the log (it may be too big to pass to FAIL_M) and fail. */ + LOG->Warn( "Unserialization of \"%s\" failed: %s", m_sSerializedData.c_str(), sError.c_str() ); + FAIL_M( "Unserialization failed" ); + } + + this->SetFromStack(); + + m_sSerializedData.clear(); +} + /* * (c) 2005 Glenn Maynard, Chris Danford * All rights reserved. diff --git a/stepmania/src/LuaReference.h b/stepmania/src/LuaReference.h index 97ff13a701..03bf8047ce 100644 --- a/stepmania/src/LuaReference.h +++ b/stepmania/src/LuaReference.h @@ -29,13 +29,17 @@ public: /* Return the referenced type, or LUA_TNONE if not set. */ int GetLuaType() const; - static void ReRegisterAll(); // call this after resetting Lua + static void BeforeResetAll(); // call this before resetting Lua + static void AfterResetAll(); // call this after resetting Lua protected: + /* If this object needs to store state to recreate itself, overload this. */ + virtual void BeforeReset() { } + /* If this object is able to recreate itself, overload this, and ReRegisterAll * will work; the reference will still exist after a theme change. If not * implemented, the reference will be unset after ReRegister. */ - virtual void Register(); + virtual void Register() { } private: void Unregister(); @@ -57,6 +61,17 @@ private: CString m_sExpression; }; +/* Reference a trivially restorable Lua object (any object that Serialize can handle). + * The object will be saved and restored across Lua resets. */ +class LuaData: public LuaReference +{ +protected: + virtual void BeforeReset(); + virtual void Register(); + + CString m_sSerializedData; +}; + #endif /*