mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Script/LuaLibrary.h"
|
||||
|
||||
#include "Script/Script.h"
|
||||
#include "Script/ThreadRef.h"
|
||||
#include "Script/ScriptContext.h"
|
||||
#include "Script/LuaSettings.h"
|
||||
#include "Util/StandardOut.h"
|
||||
#include "V8DataModel/DebugSettings.h"
|
||||
#include "V8DataModel/ContentProvider.h"
|
||||
|
||||
#include "boost/filesystem.hpp"
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace RBX {
|
||||
|
||||
template<>
|
||||
std::string StringConverter<Lua::Library>::convertToString(const Lua::Library& value)
|
||||
{
|
||||
return value.getLibraryName();
|
||||
}
|
||||
|
||||
namespace Lua {
|
||||
|
||||
|
||||
static void registerLibraryTable(lua_State *L)
|
||||
{
|
||||
lua_pushlightuserdata(L, (void*)®isterLibraryTable);
|
||||
lua_newtable(L);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* Bridge<Library>::className("RbxLibrary");
|
||||
|
||||
static int getApi(lua_State *L)
|
||||
{
|
||||
std::list<std::string> api;
|
||||
{
|
||||
RBXASSERT_BALLANCED_LUA_STACK(L);
|
||||
const Library& self = Bridge<Library>::getObject(L, 1);
|
||||
//First get the "table" storing the real library's "Table"
|
||||
lua_pushlightuserdata(L, (void*)®isterLibraryTable); /* Registry mapping for table. Key is arbitrary. */
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // Stack: t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // did you forget to call registerClassLibrary
|
||||
|
||||
//Now look up the library associated with our object
|
||||
lua_pushstring(L, self.getLibraryName()); // Stack: libraryName, t,
|
||||
lua_gettable(L, -2); // Stack: t[libraryName], t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // A library was pushed without being created
|
||||
RBXASSERT(lua_istable( L, -1 )); // A library was pushed without being created
|
||||
|
||||
int tableIndex = lua_gettop(L);
|
||||
/* table is in the stack at index 'tableIndex' */
|
||||
lua_pushnil(L); /* first key */ // Stack: nil, t[libraryName], t
|
||||
while (lua_next(L, tableIndex) != 0) {
|
||||
/* uses 'key' (at index -2) and 'value' (at index -1) */ // Stack: value, key, t[libraryName], t
|
||||
if(lua_isstring(L, -2)){
|
||||
std::string key = safe_lua_tostring(L, -2);
|
||||
if(!key.empty()){
|
||||
api.push_back(key);
|
||||
}
|
||||
}
|
||||
/* removes 'value'; keeps 'key' for next iteration */
|
||||
lua_pop(L, 1); // Stack: key, t[libraryName], t
|
||||
}
|
||||
// Stack: t[libraryName], t
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
lua_createtable(L, api.size(), 0); // Stack: t
|
||||
int i = 1;
|
||||
for(std::list<std::string>::iterator iter = api.begin(); iter != api.end(); ++iter, ++i)
|
||||
{
|
||||
lua_pushnumber(L, i); // Stack: key, t
|
||||
lua_pushstring(L, *iter); // Stack: value, key, t
|
||||
lua_settable(L, -3); // Stack: t
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
int Bridge<Library>::on_index(const Library& object, const char* name, lua_State *L)
|
||||
{
|
||||
if(strcmp(name,"GetApi") == 0){
|
||||
lua_pushcfunction(L, getApi);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(name,"Name") == 0){
|
||||
lua_pushstring(L, object.getLibraryName());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//First get the "table" storing the real library's "Table"
|
||||
lua_pushlightuserdata(L, (void*)®isterLibraryTable); /* Registry mapping for table. Key is arbitrary. */
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // Stack: t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // did you forget to call registerClassLibrary
|
||||
|
||||
//Now look up the library associated with our object
|
||||
lua_pushstring(L, object.getLibraryName()); // Stack: libraryName, t,
|
||||
lua_gettable(L, -2); // Stack: t[libraryName], t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // A library was pushed without being created
|
||||
RBXASSERT(lua_istable( L, -1 )); // A library was pushed without being created
|
||||
|
||||
//Now find the value they are trying to index
|
||||
lua_pushstring(L, name); // Stack: name, t[libraryName], t
|
||||
lua_gettable(L, -2); // Stack: t[libraryName][name], t[libraryName], t
|
||||
|
||||
lua_remove(L, -2); // Stack: t[libraryName][name], t
|
||||
lua_remove(L, -2); // Stack: t[libraryName][name]
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
void Bridge<Library>::on_newindex(Library& object, const char* name, lua_State *L)
|
||||
{
|
||||
// Failure
|
||||
throw RBX::runtime_error("%s cannot be assigned to", name);
|
||||
}
|
||||
|
||||
void LibraryBridge::saveLibraryResult(lua_State *L, int results, std::string libraryName)
|
||||
{
|
||||
std::string exception = "";
|
||||
{
|
||||
RBXASSERT_BALLANCED_LUA_STACK(L);
|
||||
|
||||
if(results != 1) {
|
||||
exception = "Libraries should return exactly 1 result, and shouldn't wait";
|
||||
}
|
||||
else if(!lua_istable(L, -1)) {
|
||||
exception = "Libraries should return exactly 1 table";
|
||||
}
|
||||
else{
|
||||
//Stack: LibraryTableResult
|
||||
lua_pushstring(L, "Help"); //Stack: "Help", LibraryTableResult
|
||||
lua_rawget(L, -2); //Stack: LibraryTableResult.Help, LibraryTableResult
|
||||
if(!lua_isfunction(L, -1)){
|
||||
exception = "Libraries must contain a \"Help\" function";
|
||||
}
|
||||
lua_pop(L, 1); //Stack: LibraryTableResult
|
||||
}
|
||||
|
||||
//Grab the table where we store the library results
|
||||
lua_pushlightuserdata(L, (void*)®isterLibraryTable); /* Registry mapping for table. Key is arbitrary. */
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // Stack: t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // did you forget to call registerClassLibrary
|
||||
|
||||
if(!exception.empty()) {
|
||||
lua_pushstring(L, libraryName); //Stack: libName, t
|
||||
lua_pushstring(L, exception); //Stack: exception, libName, t
|
||||
lua_rawset(L, -3); //Stack: t
|
||||
}
|
||||
else {
|
||||
//No exception means exactly one argument, and its a proper table //Stack: t, LibraryTableResult
|
||||
lua_pushstring(L, libraryName.c_str()); //Stack: libName, t, LibraryTableResult
|
||||
lua_pushvalue(L, -3); //Stack: LibraryTableResult, libName, t, LibraryTableResult
|
||||
lua_rawset(L, -3); //Stack: t, LibraryTableResult
|
||||
}
|
||||
lua_pop(L, 1); //Stack: results?
|
||||
}
|
||||
{
|
||||
RBXASSERT_BALLANCED_LUA_STACK(L);
|
||||
|
||||
if(exception.empty()){
|
||||
push(L, Library(libraryName));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else{
|
||||
lua_pushlightuserdata(L, (void*)&push ); /* Registry mapping for table. Key is arbitrary. */
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // Stack: t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // Did you forget to call registerClassLibrary??
|
||||
|
||||
lua_pushstring(L, libraryName); //Stack: libName, t
|
||||
lua_pushstring(L, exception); //Stack: msg, libName, t
|
||||
lua_rawset(L, -3); //Stack: t
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int LibraryBridge::find(lua_State *L, const std::string& libraryName)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
int i = lua_gettop(L);
|
||||
#endif
|
||||
// Matt Campbell at Serotek Corporation had a great idea. Create only
|
||||
// a single instance of the userdata and re-use it. This way the userdata
|
||||
// can be used in table keys
|
||||
// Also see http://lua-users.org/lists/lua-l/2004-07/msg00391.html
|
||||
lua_pushlightuserdata(L, (void*)&push ); /* Registry mapping for table. Key is arbitrary. */
|
||||
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // Stack: t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // Did you forget to call registerClassLibrary??
|
||||
|
||||
// Now the top of the stack is our lookup table
|
||||
// See if we already have a UserData for this instance
|
||||
lua_pushstring(L, libraryName); // Stack: name, t
|
||||
lua_rawget (L, -2); // Stack: t[name], t,
|
||||
|
||||
// TODO: only allow explicit, one-time declaration
|
||||
if(lua_isnil( L, -1 )) { // Stack: nil or I, t
|
||||
lua_pop (L, 2); // Stack:
|
||||
#ifdef _DEBUG
|
||||
RBXASSERT(lua_gettop(L) == i);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else if(lua_isstring(L, -1)) {
|
||||
lua_pushnil(L); // Stack: nil, errormsg, t
|
||||
lua_insert(L, lua_gettop(L) - 1); // Stack: errormsg, nil, t
|
||||
lua_remove (L, -3); // Stack: errormsg, nil
|
||||
#ifdef _DEBUG
|
||||
RBXASSERT(lua_gettop(L) == i + 2);
|
||||
#endif
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
lua_remove (L, -2); // Stack: Lib
|
||||
#ifdef _DEBUG
|
||||
RBXASSERT(lua_gettop(L) == i + 1);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryBridge::push(lua_State *L, const Library& item)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
int i = lua_gettop(L);
|
||||
#endif
|
||||
// Matt Campbell at Serotek Corporation had a great idea. Create only
|
||||
// a single instance of the userdata and re-use it. This way the userdata
|
||||
// can be used in table keys
|
||||
// Also see http://lua-users.org/lists/lua-l/2004-07/msg00391.html
|
||||
|
||||
lua_pushlightuserdata(L, (void*)&push ); /* Registry mapping for table. Key is arbitrary. */
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // Stack: t
|
||||
RBXASSERT(!lua_isnil( L, -1 )); // Did you forget to call registerClassLibrary??
|
||||
|
||||
// Now the top of the stack is our lookup table
|
||||
// See if we already have a UserData for this instance
|
||||
lua_pushstring(L, item.getLibraryName()); // Stack: t, name
|
||||
lua_rawget (L, -2); // Stack: t, t[i]
|
||||
|
||||
// TODO: only allow explicit, one-time declaration
|
||||
if( lua_isnil( L, -1 ) ) { // Stack: t, nil or I
|
||||
lua_pop (L, 1); // Stack: t
|
||||
pushNewObject(L, item); // Stack: t, I
|
||||
/* store the value for later use */
|
||||
lua_pushstring (L, item.getLibraryName()); // Stack: t, I, name
|
||||
lua_pushvalue (L, -2); // Stack: t, I, name, I
|
||||
lua_rawset (L, -4); // Stack: t, I
|
||||
}
|
||||
lua_remove (L, -2); // Stack: I
|
||||
|
||||
#ifdef _DEBUG
|
||||
RBXASSERT(lua_gettop(L) == i + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LibraryBridge::registerClassLibrary (lua_State *L)
|
||||
{
|
||||
// Declare the UserData re-use table
|
||||
lua_pushlightuserdata(L, (void*)&push);
|
||||
lua_newtable(L); // Not a weak table, unlike SharedPtrBridge
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
registerLibraryTable(L);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user