Skip to content

Commit d258e2b

Browse files
committed
feat(lua): added Instance.new for object creation
1 parent 2135fa9 commit d258e2b

4 files changed

Lines changed: 80 additions & 1 deletion

File tree

core/src/lua/instancelib.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include "objects/base/instance.h"
2+
#include "datatypes/ref.h"
3+
#include "luaapis.h" // IWYU pragma: keep
4+
#include "objects/meta.h"
5+
#include <memory>
6+
7+
static int lib_Instance_index(lua_State*);
8+
static int lib_Instance_tostring(lua_State*);
9+
static const struct luaL_Reg lib_Instance_metatable [] = {
10+
{"__index", lib_Instance_index},
11+
{"__tostring", lib_Instance_tostring},
12+
{NULL, NULL} /* end of array */
13+
};
14+
15+
static int __lua_impl__Instance__new(lua_State* L) {
16+
int n = lua_gettop(L);
17+
18+
// First argument (className)
19+
std::string className = luaL_checkstring(L, 1);
20+
21+
// [Optional] Second argument (parent)
22+
std::shared_ptr<Instance> parent;
23+
if (n > 1) {
24+
parent = **(std::shared_ptr<Instance>**)luaL_checkudata(L, 2, "__mt_instance");
25+
}
26+
27+
// Look up class name
28+
if (INSTANCE_MAP.count(className) == 0)
29+
return luaL_error(L, "Attempt to create instance of unknown type '%s'", className.c_str());
30+
31+
const InstanceType* type = INSTANCE_MAP[className];
32+
33+
if (type->flags & (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE) || type->constructor == nullptr)
34+
return luaL_error(L, "Attempt to create Instance of type '%s', which is not creatable", className.c_str());
35+
36+
std::shared_ptr<Instance> object = type->constructor();
37+
38+
if (parent != nullptr)
39+
object->SetParent(parent);
40+
41+
InstanceRef(object).PushLuaValue(L);
42+
return 1;
43+
}
44+
45+
void Instance::PushLuaLibrary(lua_State* L) {
46+
lua_getglobal(L, "_G");
47+
lua_pushstring(L, "Instance");
48+
49+
lua_newuserdata(L, 0);
50+
51+
// Create the library's metatable
52+
luaL_newmetatable(L, "__mt_lib_Instance");
53+
luaL_register(L, NULL, lib_Instance_metatable);
54+
lua_setmetatable(L, -2);
55+
56+
lua_rawset(L, -3);
57+
lua_pop(L, 1);
58+
}
59+
60+
61+
int lib_Instance_tostring(lua_State* L) {
62+
lua_pushstring(L, "Instance");
63+
return 1;
64+
}
65+
66+
static int lib_Instance_index(lua_State* L) {
67+
std::string key(lua_tostring(L, 2));
68+
lua_pop(L, 2);
69+
70+
if (key == "new") {
71+
lua_pushcfunction(L, __lua_impl__Instance__new);
72+
return 1;
73+
}
74+
75+
return luaL_error(L, "%s is not a valid member of %s\n", key.c_str(), "Instance");
76+
}
77+

core/src/objects/base/instance.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class Instance : public std::enable_shared_from_this<Instance> {
9595

9696
// Instance is abstract, so it should not implement GetClass directly
9797
virtual const InstanceType* GetClass() = 0;
98+
static void PushLuaLibrary(lua_State*); // Defined in lua/instancelib.cpp
9899
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
99100
std::optional<std::shared_ptr<Instance>> GetParent();
100101
bool IsParentLocked();

core/src/objects/service/script/scriptcontext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void ScriptContext::InitService() {
4646
Vector3::PushLuaLibrary(state);
4747
CFrame::PushLuaLibrary(state);
4848
Color3::PushLuaLibrary(state);
49+
Instance::PushLuaLibrary(state);
4950

5051
// TODO: custom os library
5152

editor/script/scriptdocument.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class ObLuaLexer : public QsciLexerLua {
7171
//"foreach foreachi getn "
7272

7373
// Openblocks extensions
74-
"shared require game workspace "
74+
"shared require game workspace Instance Instance.new "
7575

7676
"_G _VERSION getfenv getmetatable ipairs loadstring "
7777
"next pairs pcall rawequal rawget rawset select "

0 commit comments

Comments
 (0)