Esempio n. 1
0
/**
* @brief	Attempts to executes a Lua script.
* 			If it has not been compiled already, it will compile the script
* 			and cache it in the internal script map.
*
* @param	pUser		   	The user running the script.
* @param	pNpc		   	The NPC attached to the script.
* @param	nEventID	   	Identifier for the event.
* @param	bSelectedReward	The reward selected, if applicable.
* @param	filename	   	The script's filename.
*
* @return	true if it succeeds, false if it fails.
*/
bool CLuaEngine::ExecuteScript(CUser * pUser, CNpc * pNpc, int32 nEventID, int8 bSelectedReward, const char * filename)
{
	ScriptBytecodeMap::iterator itr;
	bool result = false;

	m_lock->AcquireReadLock();
	itr = m_scriptMap.find(filename);
	if (itr == m_scriptMap.end())
	{
		// Build full path to script
		std::string szPath = LUA_SCRIPT_DIRECTORY;
		szPath += filename;

		// Release the read lock (we're not reading anymore)
		m_lock->ReleaseReadLock();

		// Attempt to compile 
		BytecodeBuffer bytecode;
		bytecode.reserve(LUA_SCRIPT_BUFFER_SIZE);
		if (!SelectAvailableScript()->CompileScript(szPath.c_str(), bytecode))
		{
			printf("ERROR: Could not compile Lua script.\n");
			printf("FILE: %s\n", szPath.c_str());
			printf("USER: %s\n", pUser->GetName().c_str());
			printf("ZONE: %d\n", pUser->GetZoneID());
			printf("NPC ID: %d\n", pNpc->m_sSid);
			printf("-\n");
			return false;
		}

		// Acquire the write lock (we're adding the compiled script)
		m_lock->AcquireWriteLock();

#if !defined(LUA_SCRIPT_CACHE_DISABLED)
		// Add the script to our map
		m_scriptMap[filename] = bytecode;
#endif

		// Now that we have the bytecode, we can use it.
		result = SelectAvailableScript()->ExecuteScript(pUser, pNpc, nEventID, bSelectedReward, 
			filename, bytecode);

		// Done using the lock.
		m_lock->ReleaseWriteLock();
	}
	else
	{
		// Already have the bytecode, so now we need to use it.
		result = SelectAvailableScript()->ExecuteScript(pUser, pNpc, nEventID, bSelectedReward, 
			filename, itr->second);

		// Done using the lock.
		m_lock->ReleaseReadLock();
	}

	return result;
}
Esempio n. 2
0
/**
 * @brief	Attempts to executes a Lua script.
 * 			If it has not been compiled already, it will compile the script
 * 			and cache it in the internal script map.
 *
 * @param	pUser		   	The user running the script.
 * @param	pNpc		   	The NPC attached to the script.
 * @param	nEventID	   	Identifier for the event.
 * @param	bSelectedReward	The reward selected, if applicable.
 * @param	filename	   	The script's filename.
 *
 * @return	true if it succeeds, false if it fails.
 */
bool CLuaEngine::ExecuteScript(CUser * pUser, CNpc * pNpc, int32 nEventID, int8 bSelectedReward, const char * filename)
{
	ScriptBytecodeMap::iterator itr;
	bool result = false;

	m_lock->AcquireReadLock();
	itr = m_scriptMap.find(filename);
	if (itr == m_scriptMap.end())
	{
		// Build full path to script
		char szPath[_MAX_PATH];
		_snprintf(szPath, sizeof(szPath), LUA_SCRIPT_DIRECTORY "%s", filename);

		// Release the read lock (we're not reading anymore)
		m_lock->ReleaseReadLock();

		// Attempt to compile 
		BytecodeBuffer bytecode;
		bytecode.reserve(LUA_SCRIPT_BUFFER_SIZE);
		if (!SelectAvailableScript()->CompileScript(szPath, bytecode))
		{
			printf("ERROR: Could not compile Lua script `%s`.\n", szPath);
			return false;
		}

		// Acquire the write lock (we're adding the compiled script)
		m_lock->AcquireWriteLock();

#if !defined(LUA_SCRIPT_CACHE_DISABLED)
		// Add the script to our map
		m_scriptMap[filename] = bytecode;
#endif

		// Now that we have the bytecode, we can use it.
		result = SelectAvailableScript()->ExecuteScript(pUser, pNpc, nEventID, bSelectedReward, 
			filename, bytecode);

		// Done using the lock.
		m_lock->ReleaseWriteLock();
	}
	else
	{
		// Already have the bytecode, so now we need to use it.
		result = SelectAvailableScript()->ExecuteScript(pUser, pNpc, nEventID, bSelectedReward, 
			filename, itr->second);

		// Done using the lock.
		m_lock->ReleaseReadLock();
	}

	return result;
}
Esempio n. 3
0
/**
* @brief	Attempts to compile a Lua script.
*
* @param	filename	Filename of the script.
* @param	buffer  	The buffer to store the script's compiled bytecode.
*
* @return	true if it succeeds, false if it fails.
*/
bool CLuaScript::CompileScript(const char * filename, BytecodeBuffer & buffer)
{
	// ensure that we wait until the last user's done executing their script.
	Guard lock(m_lock);

	/* Attempt to load the file */
	int err = luaL_loadfile(m_luaState, filename);

	// If something bad happened, try to find an error.
	if (err != LUA_OK)
	{
		RetrieveLoadError(err, filename);
		return false;
	}

	// Everything's OK so far, the script has been loaded, now we need to start dumping it to bytecode.
	err = lua_dump(m_luaState, (lua_Writer)LoadBytecodeChunk, &buffer);
	if (err
		|| buffer.empty())
	{
		printf("ERROR: Failed to dump the Lua script `%s` to bytecode.\n", filename);
		return false;
	}

	// Compiled!
	return true;
}
Esempio n. 4
0
/**
* @brief	Attempts to compile a Lua script.
*
* @param	filename	Filename of the script.
* @param	buffer  	The buffer to store the script's compiled bytecode.
*
* @return	true if it succeeds, false if it fails.
*/
bool CLuaScript::CompileScript(const char * filename, BytecodeBuffer & buffer)
{
	// ensure that we wait until the last user's done executing their script.
	FastGuard lock(m_lock);

	/* Attempt to load the file */
	int err = luaL_loadfile(m_luaState, filename);

	// If something bad happened, try to find an error.
	if (err != LUA_OK)
	{
		RetrieveLoadError(err, filename);
		return false;
	}

	// Everything's OK so far, the script has been loaded, now we need to start dumping it to bytecode.
	err = lua_dump(m_luaState, (lua_Writer)LoadBytecodeChunk, &buffer);
	if (err
		|| buffer.empty())
	{
		printf("ERROR: Failed to dump the Lua script `%s` to bytecode.\n", filename);
		return false;
	}

#if !defined(USE_ORIGINAL_QUESTS)
	// Load up the script & revert the stack.
	// This step's only here for cleanup purposes.
	err = lua_pcall(m_luaState, 0, LUA_MULTRET, 0);
	if (err != LUA_OK)
	{
		RetrieveLoadError(err, filename);
		return false;
	}
#endif

	// Compiled!
	return true;
}
Esempio n. 5
0
/**
* @brief	Executes the Lua script from bytecode.
*
* @param	pUser		   	The user running the script.
* @param	pNpc		   	The NPC attached to the script.
* @param	nEventID	   	Identifier for the event.
* @param	bSelectedReward	The reward selected, if applicable.
* @param	filename	   	The script's filename for debugging purposes.
* @param	bytecode	   	The script's compiled bytecode.
*
* @return	true if it succeeds, false if it fails.
*/
bool CLuaScript::ExecuteScript(CUser * pUser, CNpc * pNpc, int32 nEventID, int8 bSelectedReward, const char * filename, BytecodeBuffer & bytecode)
{
	// Ensure that we wait until the last user's done executing their script.
	FastGuard lock(m_lock);

	/* Attempt to run the script. */

	// Load the buffer with our bytecode.
	int err = luaL_loadbuffer(m_luaState, reinterpret_cast<const char *>(&bytecode[0]), bytecode.size(), nullptr);
	if (err != LUA_OK)
	{
		RetrieveLoadError(err, filename);
		return false;
	}

#if !defined(USE_ORIGINAL_QUESTS) // our quest implementation

	// The user & NPC instances are globals. As is the selected quest reward.
	lua_tsetglobal(m_luaState, LUA_SCRIPT_GLOBAL_USER, pUser);
	lua_tsetglobal(m_luaState, LUA_SCRIPT_GLOBAL_NPC, pNpc);
	lua_tsetglobal(m_luaState, LUA_SCRIPT_GLOBAL_SELECTED_REWARD, bSelectedReward);

	// Find & assign script's entry point to the stack
	lua_getglobal(m_luaState, LUA_SCRIPT_ENTRY_POINT);

	// Entry point requires 1 arguments: the event ID.
	lua_tpush(m_luaState, nEventID);

	// Try calling the script's entry point (Main()).
	err = lua_pcall(m_luaState, 
		1,	// 1 arguments
		0,	// 0 returned values
		0);	// no error handler

#else

	lua_tsetglobal(m_luaState, "UID", pUser->GetID());
	lua_tsetglobal(m_luaState, "STEP", bSelectedReward);
	lua_tsetglobal(m_luaState, "EVENT", nEventID);

	// Try calling the script's entry point
	err = lua_pcall(m_luaState, 
		0,	// no arguments
		0,	// 0 returned values
		0);	// no error handler
#endif

	// Nothing returned, so we can finish up here.
	if (err == LUA_OK)
	{
#if defined(USE_ORIGINAL_QUESTS)
		lua_settop(m_luaState, 0);
#endif
		return true;
	}

	// Attempt to provide somewhat informative errors to help the user figure out what's wrong.
	switch (err)
	{
	case LUA_ERRRUN:
		printf("ERROR: A runtime error occurred within Lua script `%s`.\n", filename);
		break;

	case LUA_ERRMEM:
		printf("ERROR: Unable to allocate memory during execution of Lua script `%s`.\n", filename);
		break;

	case LUA_ERRERR:
		printf("ERROR: An error occurred during Lua script `%s`. Error handler failed.\n", filename);
		break;

	default:
		printf("ERROR: An unknown error occurred in Lua script `%s`.\n", filename);
		break;
	}

	// Is there an error set? That can be more useful than our generic error.
	if (lua_isstring(m_luaState, -1))
	{
		printf("ERROR: [%s] The following error was provided:\n%s\n",
			filename, lua_to<const char *>(m_luaState, -1));
	}

#if defined(USE_ORIGINAL_QUESTS)
	lua_settop(m_luaState, 0);
#endif

	return false;
}
Esempio n. 6
0
/**
* @brief	Executes the Lua script from bytecode.
*
* @param	pUser		   	The user running the script.
* @param	pNpc		   	The NPC attached to the script.
* @param	nEventID	   	Identifier for the event.
* @param	bSelectedReward	The reward selected, if applicable.
* @param	filename	   	The script's filename for debugging purposes.
* @param	bytecode	   	The script's compiled bytecode.
*
* @return	true if it succeeds, false if it fails.
*/
bool CLuaScript::ExecuteScript(CUser * pUser, CNpc * pNpc, int32 nEventID, int8 bSelectedReward, const char * filename, BytecodeBuffer & bytecode)
{
	// Ensure that we wait until the last user's done executing their script.
	Guard lock(m_lock);

	/* Attempt to run the script. */

	// Load the buffer with our bytecode.
	int err = luaL_loadbuffer(m_luaState, reinterpret_cast<const char *>(&bytecode[0]), bytecode.size(), nullptr);
	if (err != LUA_OK)
	{
		RetrieveLoadError(err, filename);
		return false;
	}


	lua_tsetglobal(m_luaState, "UID", pUser->GetID());
	lua_tsetglobal(m_luaState, "STEP", bSelectedReward);
	lua_tsetglobal(m_luaState, "EVENT", nEventID);

	// Try calling the script's entry point
	err = lua_pcall(m_luaState, 
		0,	// no arguments
		0,	// 0 returned values
		0);	// no error handler

	// Nothing returned, so we can finish up here.
	if (err == LUA_OK)
	{
		lua_settop(m_luaState, 0);
		return true;
	}

	// Attempt to provide somewhat informative errors to help the user figure out what's wrong.
	switch (err)
	{
	case LUA_ERRRUN:
		printf("ERROR: A runtime error occurred within Lua script.\n");
		printf("FILE: %s\n", filename);
		printf("USER: %s\n", pUser->GetName().c_str());
		printf("ZONE: %d\n", pUser->GetZoneID());
		printf("NPC ID: %d\n", pNpc->m_sSid);
		printf("-\n");
		break;

	case LUA_ERRMEM:
		printf("ERROR: Unable to allocate memory during execution of Lua script.\n");
		printf("FILE: %s\n", filename);
		printf("USER: %s\n", pUser->GetName().c_str());
		printf("ZONE: %d\n", pUser->GetZoneID());
		printf("NPC ID: %d\n", pNpc->m_sSid);
		printf("-\n");
		break;

	case LUA_ERRERR:
		printf("ERROR: An error occurred during Lua script, Error handler failed.\n");
		printf("FILE: %s\n", filename);
		printf("USER: %s\n", pUser->GetName().c_str());
		printf("ZONE: %d\n", pUser->GetZoneID());
		printf("NPC ID: %d\n", pNpc->m_sSid);
		printf("-\n");
		break;

	default:
		printf("ERROR: An unknown error occurred in Lua script.\n");
		printf("FILE: %s\n", filename);
		printf("USER: %s\n", pUser->GetName().c_str());
		printf("ZONE: %d\n", pUser->GetZoneID());
		printf("NPC ID: %d\n", pNpc->m_sSid);
		printf("-\n");
		break;
	}

	// Is there an error set? That can be more useful than our generic error.
	if (lua_isstring(m_luaState, -1))
	{
		printf("ERROR: [%s] The following error was provided.\n",filename);
		printf("MESSAGE: %s\n", lua_to<const char *>(m_luaState, -1));
		printf("-\n");

	}

	lua_settop(m_luaState, 0);

	return false;
}