Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ee70dd2
Current work on Lua and Scripts
pizzaboxer Jan 25, 2026
fb6c819
Remove Lua submodule
pizzaboxer Jan 29, 2026
5c51f4f
Add Lua 5.1.1
pizzaboxer Jan 29, 2026
fa49b4f
Implement most of ScriptContext
pizzaboxer Jan 31, 2026
ad77090
Improve ScriptContext matches
pizzaboxer Jan 31, 2026
6ecc3be
RobloxExtraSpace
pizzaboxer Feb 1, 2026
21147c2
Match bucketRealloc (completes LuaMemory)
pizzaboxer Feb 1, 2026
e746a67
Match findDescriptor
pizzaboxer Feb 1, 2026
0914a77
Prelim work on LuaInstanceBridge and reflection descriptors
pizzaboxer Feb 1, 2026
5fcdb5a
Minor fixes
pizzaboxer Feb 3, 2026
f8f6e35
Match descriptor iterator getters
pizzaboxer Feb 3, 2026
10cb4ae
Roughly implement pushLuaValue
pizzaboxer Feb 4, 2026
6c3d683
Implement rest of LuaInstanceBridge
pizzaboxer Feb 7, 2026
6b716d6
Implement LuaSignalBridge
pizzaboxer Feb 7, 2026
610eb82
Fixup RobloxExtraSpace
pizzaboxer Feb 7, 2026
9293a91
Implement LuaAtomicClasses
pizzaboxer Feb 8, 2026
275bc09
Implement ScriptEvent
pizzaboxer Feb 8, 2026
058d368
Implement ThreadRef
pizzaboxer Feb 8, 2026
eb179a6
Match Vector3Bridge::on_mul
pizzaboxer Feb 8, 2026
a41a3cd
Implement rest of Lua::Bridge
pizzaboxer Feb 9, 2026
01c12c5
Implement most of LuaArguments
pizzaboxer Feb 12, 2026
7a40271
Implement SharedPtrBridge::getPtr
pizzaboxer Feb 12, 2026
41105e8
Improve findDescriptor
pizzaboxer Feb 12, 2026
3449395
Merge branch 'master' into 1601
pizzaboxer Apr 4, 2026
289f384
Resolve merged conflicting code
pizzaboxer Apr 4, 2026
de619f3
Fix SecurityContext.h
pizzaboxer Apr 4, 2026
03dc2e7
Finish implementing ScriptContext
pizzaboxer Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,288 changes: 1,890 additions & 1,398 deletions Client/App/App.vcproj

Large diffs are not rendered by default.

211 changes: 211 additions & 0 deletions Client/App/include/lua/LuaBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#pragma once
#include "lua.h"
#include "lauxlib.h"
#include "boost/shared_ptr.hpp"
#include "util/Utilities.h"
#include "G3D/format.h"
#include <stdexcept>

namespace RBX
{
namespace Lua
{
template <typename T, bool isComparable>
class Bridge
{
protected:
static const char* className;

public:
static T* pushNewObject(lua_State* L)
{
T* ptr = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
new(ptr) T();
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
return ptr;
}
static T& getObject(lua_State* L, size_t index)
{
return *static_cast<T*>(luaL_checkudata(L, static_cast<int>(index), className));
}
static void registerClass(lua_State* L)
{
luaL_newmetatable(L, className);

lua_pushstring(L, "__index");
lua_pushcfunction(L, on_index);
lua_settable(L, -3);

lua_pushstring(L, "__newindex");
lua_pushcfunction(L, on_newindex);
lua_settable(L, -3);

lua_pushstring(L, "__gc");
lua_pushcfunction(L, on_gc);
lua_settable(L, -3);

if (isComparable)
{
lua_pushstring(L, "__eq");
lua_pushcfunction(L, on_eq);
lua_settable(L, -3);
}

lua_pushstring(L, "__tostring");
lua_pushcfunction(L, on_tostring);
lua_settable(L, -3);

lua_pop(L, 1);
}

public:
template<typename Param1Type>
static T* pushNewObject(lua_State* L, Param1Type param1)
{
T* ptr = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
new(ptr) T(param1);
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
return ptr;
}

template<typename Object>
static bool getValue(lua_State* L, size_t index, Object& value)
{
const Object* object = static_cast<const Object*>(lua_touserdata(L,static_cast<int>(index)));
if (object)
{
if (lua_getmetatable(L, static_cast<int>(index)))
{
luaL_getmetatable(L, className);
if (lua_rawequal(L, -1, -2))
{
lua_pop(L, 2);
value = *object;
return true;
}
}
else
{
lua_pop(L, 1);
}
}

return false;
}

protected:
static int on_index(lua_State* L)
{
const char* name = luaL_checkstring(L, 2);
T& object = getObject(L, 1);
return on_index(object, name, L);
}
static int on_index(const T& object, const char* name, lua_State* L);
static int on_newindex(lua_State* L)
{
// TODO: function return not matching
const char* name = luaL_checkstring(L, 2);
T& object = getObject(L, 1);
on_newindex(object, name, L);
return 0;
}
static void on_newindex(T& object, const char* name, lua_State* L)
{
throw std::runtime_error(G3D::format("%s cannot be assigned to", name));
}
static int on_tostring(lua_State* L)
{
T& object = getObject(L, 1);
return on_tostring(object, L);
}
static int on_tostring(const T& object, lua_State* L)
{
std::string name = StringConverter<T>::convertToString(object);
lua_pushstring(L, name.c_str());
return 1;
}
static int on_gc(lua_State* L)
{
T& object = getObject(L, 1);
object.~T();
return 0;
}
static int on_eq(lua_State* L)
{
lua_pushboolean(L, getObject(L, 1) == getObject(L, 2));
return 1;
}
};

template <typename T>
class SharedPtrBridge : protected Bridge<boost::shared_ptr<T>, false>
{
public:
static void registerClass(lua_State* L)
{
Bridge<boost::shared_ptr<T>, false>::registerClass(L);
}
static void registerClassLibrary(lua_State* L)
{
lua_pushlightuserdata(L, push);
newweaktable(L, "v");
lua_rawset(L, LUA_REGISTRYINDEX);
}
static void push(lua_State* L, boost::shared_ptr<T> instance)
{
if (!instance)
{
lua_pushnil(L);
}
else
{
lua_gettop(L);
lua_pushlightuserdata(L, push);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushlightuserdata(L, instance.get());
lua_rawget(L, -2);

if (lua_type(L, -1) == LUA_TNIL)
{
lua_pop(L, 1);
pushNewObject(L, instance);
lua_pushlightuserdata(L, instance.get());
lua_pushvalue(L, -2);
lua_rawset(L, -4);
}

lua_remove(L, -2);
}
}
static boost::shared_ptr<T> getPtr(lua_State* L, size_t index)
{
// TODO: check match for T=boost::shared_ptr<Reflection::DescribedBase>
// when security is implemented

if (lua_type(L, static_cast<int>(index)) == LUA_TNIL)
{
return boost::shared_ptr<T>();
}
else
{
return getObject(L, index);
}
}

public:
template<typename ValueType>
static bool getPtr(lua_State* L, size_t index, ValueType& value)
{
if (lua_type(L, static_cast<int>(index)) == LUA_TNIL)
{
value = boost::shared_ptr<T>();
return 1;
}

return getValue(L, index, value);
}
};
}
}
28 changes: 28 additions & 0 deletions Client/App/include/lua/lua.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once
#include "lua.h"

namespace RBX
{
namespace Lua
{
class ScopedPopper
{
private:
int popCount;
lua_State* thread;

public:
ScopedPopper(lua_State* thread, int popCount)
: popCount(popCount),
thread(thread)
{
}
ScopedPopper& operator+=(int);
ScopedPopper& operator-=(int);
~ScopedPopper()
{
lua_pop(thread, popCount);
}
};
}
}
30 changes: 9 additions & 21 deletions Client/App/include/reflection/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace RBX
NeedTrustedCaller = 0,
AnyCaller = 1
};

public:
class Arguments
{
Expand All @@ -25,32 +26,23 @@ namespace RBX
public:
virtual size_t size() const = 0;
virtual void get(int, Value&) const = 0;
public:
//Arguments(const Arguments&);
Arguments();
~Arguments();
public:
//Arguments& operator=(const Arguments&);
};

public:
typedef Function Describing;

public:
const Security security;

protected:
SignatureDescriptor signature;

public:
//FunctionDescriptor(const FunctionDescriptor&);
protected:
FunctionDescriptor(ClassDescriptor& classDescriptor, const char* name, Security security);

public:
const SignatureDescriptor& getSignature() const;
virtual void execute(DescribedBase*, Arguments&) const = 0;
public:
virtual ~FunctionDescriptor();
public:
//FunctionDescriptor& operator=(const FunctionDescriptor&);
};

class Function
Expand All @@ -60,29 +52,25 @@ namespace RBX
const DescribedBase* instance;

public:
//Function(const Function&);
Function(const Function&);
Function(const FunctionDescriptor&, const DescribedBase*);
public:
Function& operator=(const Function&);
const Name& getName() const;
const FunctionDescriptor* getDescriptor() const;
const FunctionDescriptor* getDescriptor() const
{
return descriptor;
}
void execute(FunctionDescriptor::Arguments&) const;
};

template<typename Class>
class FuncDesc : public FunctionDescriptor
{
public:
//FuncDesc(const FuncDesc&);
protected:
FuncDesc(const char* name, Security security)
: FunctionDescriptor(Class::classDescriptor(), name, security)
{
}
public:
virtual ~FuncDesc();
public:
//FuncDesc& operator=(const FuncDesc&);
};
}
}
Loading