Skip to main content

BaseObject

BaseObject provides interface methods for three core features:

  • Object Destruction via adding a :Destroy() method and IsDestroyed flag property,
  • Task Management across the objects lifetime by providing a janitor internally,
  • and Signal Management by providing interfaces to Register, Get, and Fire signals easily.

Destroy Behavior:

  • When a BaseObject instance is destroyed, it's IsDestroyed property is set to true, and it's Destroyed signal is fired.
  • It's metatable is set to a metatable that will error when any of it's methods or metamethods are called.

You should check IsDestroyed before calling any methods on a BaseObject instance if you are not sure if it has been destroyed or not.

Types

BaseObject

type BaseObject = BaseObject

Properties

ClassName

This item is read only and cannot be modified. Read Only
BaseObject.ClassName: string

Functions

getObjectFromId

static
BaseObject.getObjectFromId(idnumber) → BaseObject?

Fetches the object with the given ID if it exists.

local obj = BaseObject.new()

local id = obj:GetId()

print(BaseObject.getObjectFromId(id) == obj) -- true

new

static
BaseObject.new(
tbl{[any]any}?--

Table to construct the BaseObject with

) → BaseObject

Constructs a new BaseObject

local obj = BaseObject.new({
	X = 1,
	Y = 2,
})

obj.Z = 3

print(obj.X, obj.Y, obj.Z) -- 1, 2, 3
local SuperClass = setmetatable({}, BaseObject)
SuperClass.__index = SuperClass
SuperClass.ClassName = "SuperClass"

function SuperClass.new()
	local self = setmetatable(BaseObject.new(), SuperClass)
	return self
end

function SuperClass:Destroy() -- Overwrite the BaseObject Destroy method
	getmetatable(SuperClass).Destroy(self) -- If you overwrite the BaseObject Destroy method you need to have this line to call the original.
end

function SuperClass:Print()
	print("Hello, World!")
end

return SuperClass

Destroy

BaseObject:Destroy() → ()

Marks the Object as Destroyed, fires the Destroyed Signal, cleans up the BaseObject, and sets the metatable to nil/a special locked MT.

GetId

BaseObject:GetId() → number

Returns the ID of the BaseObject Can be used to fetch the object with BaseObject.getObjectFromId(id)

IsA

BaseObject:IsA(classOrClassNametable | string) → boolean

Returns true if the given object is of a given class. Takes a class name or class object.

GetTask

BaseObject:GetTask(taskIdany) → Task?

Fetches the task with the given ID if it exists.

local obj = BaseObject.new()

local part = Instance.new("Part")

obj:AddTask(part, nil, "Test")

print(obj:GetTask("Test") == part) -- true

AddTask

BaseObject:AddTask(
taskTask,
taskCleanupMethod(string | true | nil)?,--

(if none is given it will try to infer; Passing true tells it to call it as a function)

taskIdany?
) → Task--

The task that was given

Adds a task to the janitor. If a taskId is provided, it will be used as the key for the task in the janitor and can then be fetched later with :GetTask(). If an ID is provided and there already exists a task with that ID, it will clean up the existing task and then replace the index with the new one. It will return the task that was added/given.

local obj = BaseObject.new()

local task = obj:AddTask(function()
	print("Hello, World!")
end)

obj:Destroy() -- Prints "Hello, World!"

AddPromise

BaseObject:AddPromise(promPromise) → Promise

Adds a promise to the janitor. Similar to :AddTask(). Returns the same Promise that was given to it.

local prom = Promise.delay(math.random(10))

local obj = BaseObject.new()
obj:AddPromise(prom)

task.wait(math.random(10))

obj:Destroy() -- Cancels the promise if it hasn't resolved yet

RemoveTask

BaseObject:RemoveTask(
taskIdany,
dontCleanboolean?
) → ()

Removes a task from the janitor. Cleans the task as if :DoCleaning was called. If dontClean is true, it will not clean up the task, it will just remove it from the janitor.

local obj = BaseObject.new()

local task = obj:AddTask(function()
	print("Hello, World!")
end, nil, "Test")

obj:RemoveTask("Test") -- Prints "Hello, World!"

RemoveTaskNoClean

BaseObject:RemoveTaskNoClean(taskIdany) → ()

Removes a task from the janitor without cleaning it.

local obj = BaseObject.new()

local task = obj:AddTask(function()
	print("Hello, World!")
end, nil, "Test")

obj:RemoveTaskNoClean("Test") -- Does NOT print "Hello, World!"

FireSignal

BaseObject:FireSignal(
signalNamestring,--

The name of the signal to fire

...any--

Arguments to pass to the signal

) → ()

Fires the signal with the given name, if it exists. Equivalent to calling :GetSignal(signalName):Fire(...) except this does not require the signal to exist first.

local obj = BaseObject.new()
local SignalName = "Test"

obj:RegisterSignal(SignalName)

obj:GetSignal(SignalName):Connect(print)

obj:FireSignal(SignalName, "Hello, World!") -- Fires the signal with the argument "Hello, World!"

RegisterSignal

BaseObject:RegisterSignal(
signalNamestring,--

Name of signal to register

sig(Signal | RBXScriptSignal)?--

Optional signal to register

) → ()

Marks a signal with the given name as registered. Does not actually build a new signal, it sets the index to a SignalMarker to identify it as registered so that it can be fetched later. Can be given an existing signal to mimic.

local obj = BaseObject.new()

obj:RegisterSignal("Test")

obj:GetSignal("Test"):Connect(function()
	print("Hello, World!")
end)
local myPart = Instance.new("Part")
local obj = BaseObject.new()

obj:RegisterSignal("Touched", myPart.Touched)

obj:GetSignal("Touched"):Connect(function(touchedPart)
	print("Part Touched!")
end)

ConnectSignal

BaseObject:ConnectSignal(
signalNamestring,
callback(...any) → (),
taskIdany?
) → Connection

Connects a signal with the given name to a callback. Alias for :GetSignal(signalName):Connect(callback).

local obj = BaseObject.new()

local SignalName = "Test"

obj:RegisterSignal(SignalName)

obj:ConnectSignal(SignalName, function()
	print("Hello, World!")
end)

obj:FireSignal(SignalName) -- Prints "Hello, World!"

PromiseSignal

BaseObject:PromiseSignal(
signalNamestring,--

The name of the signal to connect to

predicate((U...) → boolean)?--

An optional predicate to run before the callback. The promise will not resolve until the predicate returns false.

) → Promise<U...>--

A promise that resolves when the signal is fired.

Connects a signal with the given name to a callback that will only run once. Alias for object:AddPromise(Promise.fromEvent(object:GetSignal(signalName))).

local obj = BaseObject.new()

local SignalName = "Test"

obj:RegisterSignal(SignalName)

obj:PromiseSignal(SignalName, function(Letter)
	return Letter == "B"
end):andThen(function(Letter)
	print("Hello, World!")
end)

obj:FireSignal(SignalName, "A") -- Does not print anything
obj:FireSignal(SignalName, "B") -- Prints "Hello, World!"
obj:FireSignal(SignalName, "B") -- Does not print anything as it was disconnected

HasSignal

BaseObject:HasSignal(signalNamestring) → boolean

Checks whether or not a signal with the given name is registered.

local obj = BaseObject.new()

local SignalName = "Test"

print(obj:HasSignal(SignalName)) -- false

obj:RegisterSignal(SignalName)

print(obj:HasSignal(SignalName)) -- true

GetSignal

BaseObject:GetSignal(signalNamestring) → Signal

Fetches a signal with the given name. Creates the Signal JIT.

GetDestroyedSignal

BaseObject:GetDestroyedSignal() → Signal

Returns a signal that fires when the object is destroyed. Creates the signal JIT. Kept for backwards compatibility.

local obj = BaseObject.new()

obj:GetDestroyedSignal():Connect(function()
	print("Object Destroyed!")
end)

obj:Destroy() -- Prints "Object Destroyed!"

BindToInstance

BaseObject:BindToInstance(
objInstance,
destroyOnNilParentboolean?--

Whether or not to destroy the object when the parent is nil'd

) → function--

Disconnects the binding

Binds the object to the given instance. When the object is destroyed, it will destroy the instance. When the instance is destroyed, it will destroy the object.

local obj = BaseObject.new()
local part = Instance.new("Part")
obj:BindToInstance(part)

do -- setup prints on destroy
	obj:AddTask(function()
		print("Object Destroyed!")
	end)

	part.Destroying:Connect(function()
		print("Part Destroyed!")
	end)
end

local X = if math.random(1,2) == 1 then obj or part
X:Destroy() -- Prints "Object Destroyed!" and "Part Destroyed!" (Destroying one will destroy the other)
Show raw api
{
    "functions": [
        {
            "name": "getObjectFromId",
            "desc": "Fetches the object with the given ID if it exists.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal id = obj:GetId()\n\nprint(BaseObject.getObjectFromId(id) == obj) -- true\n```",
            "params": [
                {
                    "name": "id",
                    "desc": "",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "BaseObject?"
                }
            ],
            "function_type": "static",
            "tags": [
                "static"
            ],
            "source": {
                "line": 154,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "new",
            "desc": "Constructs a new BaseObject\n\n\n\n```lua\nlocal obj = BaseObject.new({\n\tX = 1,\n\tY = 2,\n})\n\nobj.Z = 3\n\nprint(obj.X, obj.Y, obj.Z) -- 1, 2, 3\n```\n\n```lua\nlocal SuperClass = setmetatable({}, BaseObject)\nSuperClass.__index = SuperClass\nSuperClass.ClassName = \"SuperClass\"\n\nfunction SuperClass.new()\n\tlocal self = setmetatable(BaseObject.new(), SuperClass)\n\treturn self\nend\n\nfunction SuperClass:Destroy() -- Overwrite the BaseObject Destroy method\n\tgetmetatable(SuperClass).Destroy(self) -- If you overwrite the BaseObject Destroy method you need to have this line to call the original.\nend\n\nfunction SuperClass:Print()\n\tprint(\"Hello, World!\")\nend\n\nreturn SuperClass\n```",
            "params": [
                {
                    "name": "tbl",
                    "desc": "Table to construct the BaseObject with",
                    "lua_type": "{ [any]: any }?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "BaseObject"
                }
            ],
            "function_type": "static",
            "tags": [
                "static"
            ],
            "source": {
                "line": 199,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "Destroy",
            "desc": "Marks the Object as Destroyed, fires the Destroyed Signal, cleans up\nthe BaseObject, and sets the metatable to nil/a special locked MT.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 223,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "GetId",
            "desc": "Returns the ID of the BaseObject\nCan be used to fetch the object with BaseObject.getObjectFromId(id)",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "number\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 255,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "IsA",
            "desc": "Returns true if the given object is of a given class.\nTakes a class name or class object.",
            "params": [
                {
                    "name": "classOrClassName",
                    "desc": "",
                    "lua_type": "table | string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 263,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "GetTask",
            "desc": "Fetches the task with the given ID if it exists.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal part = Instance.new(\"Part\")\n\nobj:AddTask(part, nil, \"Test\")\n\nprint(obj:GetTask(\"Test\") == part) -- true\n```",
            "params": [
                {
                    "name": "taskId",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Task?"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 295,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "AddTask",
            "desc": "Adds a task to the janitor. If a taskId is provided, it will be used as the\nkey for the task in the janitor and can then be fetched later with :GetTask().\nIf an ID is provided and there already exists a task with that ID, it will\nclean up the existing task and then replace the index with the new one.\nIt will return the task that was added/given.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal task = obj:AddTask(function()\n\tprint(\"Hello, World!\")\nend)\n\nobj:Destroy() -- Prints \"Hello, World!\"\n```",
            "params": [
                {
                    "name": "task",
                    "desc": "",
                    "lua_type": "Task"
                },
                {
                    "name": "taskCleanupMethod",
                    "desc": "(if none is given it will try to infer; Passing true tells it to call it as a function)",
                    "lua_type": "(string | true | nil)?"
                },
                {
                    "name": "taskId",
                    "desc": "",
                    "lua_type": "any?"
                }
            ],
            "returns": [
                {
                    "desc": "The task that was given",
                    "lua_type": "Task"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 320,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "AddPromise",
            "desc": "Adds a promise to the janitor. Similar to :AddTask(). Returns the same Promise\nthat was given to it.\n\n```lua\nlocal prom = Promise.delay(math.random(10))\n\nlocal obj = BaseObject.new()\nobj:AddPromise(prom)\n\ntask.wait(math.random(10))\n\nobj:Destroy() -- Cancels the promise if it hasn't resolved yet\n```",
            "params": [
                {
                    "name": "prom",
                    "desc": "",
                    "lua_type": "Promise"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Promise"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 342,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "RemoveTask",
            "desc": "Removes a task from the janitor. Cleans the task as if :DoCleaning was called.\nIf dontClean is true, it will not clean up the task, it will just remove\nit from the janitor.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal task = obj:AddTask(function()\n\tprint(\"Hello, World!\")\nend, nil, \"Test\")\n\nobj:RemoveTask(\"Test\") -- Prints \"Hello, World!\"\n```",
            "params": [
                {
                    "name": "taskId",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "dontClean",
                    "desc": "",
                    "lua_type": "boolean?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 365,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "RemoveTaskNoClean",
            "desc": "Removes a task from the janitor without cleaning it.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal task = obj:AddTask(function()\n\tprint(\"Hello, World!\")\nend, nil, \"Test\")\n\nobj:RemoveTaskNoClean(\"Test\") -- Does NOT print \"Hello, World!\"\n```",
            "params": [
                {
                    "name": "taskId",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 386,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "FireSignal",
            "desc": "Fires the signal with the given name, if it exists.\nEquivalent to calling `:GetSignal(signalName):Fire(...)` except this does not require\nthe signal to exist first.\n\n```lua\nlocal obj = BaseObject.new()\nlocal SignalName = \"Test\"\n\nobj:RegisterSignal(SignalName)\n\nobj:GetSignal(SignalName):Connect(print)\n\nobj:FireSignal(SignalName, \"Hello, World!\") -- Fires the signal with the argument \"Hello, World!\"\n```",
            "params": [
                {
                    "name": "signalName",
                    "desc": "The name of the signal to fire",
                    "lua_type": "string"
                },
                {
                    "name": "...",
                    "desc": "Arguments to pass to the signal",
                    "lua_type": "any"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 412,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "RegisterSignal",
            "desc": "Marks a signal with the given name as registered. Does not actually\nbuild a new signal, it sets the index to a SignalMarker to identify\nit as registered so that it can be fetched later. Can be given an existing\nsignal to mimic.\n\n```lua\nlocal obj = BaseObject.new()\n\nobj:RegisterSignal(\"Test\")\n\nobj:GetSignal(\"Test\"):Connect(function()\n\tprint(\"Hello, World!\")\nend)\n```\n```lua\nlocal myPart = Instance.new(\"Part\")\nlocal obj = BaseObject.new()\n\nobj:RegisterSignal(\"Touched\", myPart.Touched)\n\nobj:GetSignal(\"Touched\"):Connect(function(touchedPart)\n\tprint(\"Part Touched!\")\nend)\n```",
            "params": [
                {
                    "name": "signalName",
                    "desc": "Name of signal to register",
                    "lua_type": "string"
                },
                {
                    "name": "sig",
                    "desc": "Optional signal to register",
                    "lua_type": "(Signal | RBXScriptSignal)?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 447,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "ConnectSignal",
            "desc": "Connects a signal with the given name to a callback.\nAlias for `:GetSignal(signalName):Connect(callback)`.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal SignalName = \"Test\"\n\nobj:RegisterSignal(SignalName)\n\nobj:ConnectSignal(SignalName, function()\n\tprint(\"Hello, World!\")\nend)\n\nobj:FireSignal(SignalName) -- Prints \"Hello, World!\"\n```",
            "params": [
                {
                    "name": "signalName",
                    "desc": "",
                    "lua_type": "string"
                },
                {
                    "name": "callback",
                    "desc": "",
                    "lua_type": "(...any) -> ()"
                },
                {
                    "name": "taskId",
                    "desc": "",
                    "lua_type": "any?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Connection\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 481,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "PromiseSignal",
            "desc": "Connects a signal with the given name to a callback that will only run once.\nAlias for `object:AddPromise(Promise.fromEvent(object:GetSignal(signalName)))`.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal SignalName = \"Test\"\n\nobj:RegisterSignal(SignalName)\n\nobj:PromiseSignal(SignalName, function(Letter)\n\treturn Letter == \"B\"\nend):andThen(function(Letter)\n\tprint(\"Hello, World!\")\nend)\n\nobj:FireSignal(SignalName, \"A\") -- Does not print anything\nobj:FireSignal(SignalName, \"B\") -- Prints \"Hello, World!\"\nobj:FireSignal(SignalName, \"B\") -- Does not print anything as it was disconnected\n```",
            "params": [
                {
                    "name": "signalName",
                    "desc": "The name of the signal to connect to",
                    "lua_type": "string"
                },
                {
                    "name": "predicate",
                    "desc": "An optional predicate to run before the callback. The promise will not resolve until the predicate returns false.",
                    "lua_type": "((U...) -> boolean)?"
                }
            ],
            "returns": [
                {
                    "desc": "A promise that resolves when the signal is fired.",
                    "lua_type": "Promise<U...>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 510,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "HasSignal",
            "desc": "Checks whether or not a signal with the given name is registered.\n\n```lua\nlocal obj = BaseObject.new()\n\nlocal SignalName = \"Test\"\n\nprint(obj:HasSignal(SignalName)) -- false\n\nobj:RegisterSignal(SignalName)\n\nprint(obj:HasSignal(SignalName)) -- true\n```",
            "params": [
                {
                    "name": "signalName",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 532,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "GetSignal",
            "desc": "Fetches a signal with the given name. Creates the Signal JIT.",
            "params": [
                {
                    "name": "signalName",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Signal"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 541,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "GetDestroyedSignal",
            "desc": "Returns a signal that fires when the object is destroyed. Creates the signal JIT.\nKept for backwards compatibility.\n\n```lua\nlocal obj = BaseObject.new()\n\nobj:GetDestroyedSignal():Connect(function()\n\tprint(\"Object Destroyed!\")\nend)\n\nobj:Destroy() -- Prints \"Object Destroyed!\"\n```",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Signal\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 572,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        },
        {
            "name": "BindToInstance",
            "desc": "Binds the object to the given instance. When the object is destroyed, it will\ndestroy the instance. When the instance is destroyed, it will destroy the object.\n\n```lua\nlocal obj = BaseObject.new()\nlocal part = Instance.new(\"Part\")\nobj:BindToInstance(part)\n\ndo -- setup prints on destroy\n\tobj:AddTask(function()\n\t\tprint(\"Object Destroyed!\")\n\tend)\n\n\tpart.Destroying:Connect(function()\n\t\tprint(\"Part Destroyed!\")\n\tend)\nend\n\nlocal X = if math.random(1,2) == 1 then obj or part\nX:Destroy() -- Prints \"Object Destroyed!\" and \"Part Destroyed!\" (Destroying one will destroy the other)\n```",
            "params": [
                {
                    "name": "obj",
                    "desc": "",
                    "lua_type": "Instance"
                },
                {
                    "name": "destroyOnNilParent",
                    "desc": "Whether or not to destroy the object when the parent is nil'd",
                    "lua_type": "boolean?"
                }
            ],
            "returns": [
                {
                    "desc": "Disconnects the binding",
                    "lua_type": "function"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 612,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        }
    ],
    "properties": [
        {
            "name": "ClassName",
            "desc": "",
            "lua_type": "string",
            "readonly": true,
            "source": {
                "line": 138,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        }
    ],
    "types": [
        {
            "name": "BaseObject",
            "desc": "",
            "lua_type": "BaseObject",
            "source": {
                "line": 132,
                "path": "src/baseobject/src/BaseObject.lua"
            }
        }
    ],
    "name": "BaseObject",
    "desc": "BaseObject provides interface methods for three core features:\n- Object Destruction via adding a :Destroy() method and IsDestroyed flag property,\n- Task Management across the objects lifetime by providing a janitor internally,\n- and Signal Management by providing interfaces to Register, Get, and Fire signals easily.\n\n\nDestroy Behavior:\n* When a BaseObject instance is destroyed, it's `IsDestroyed` property is set to true, and it's `Destroyed` signal is fired.\n* It's metatable is set to a metatable that will error when any of it's methods or metamethods are called.\n\nYou should check `IsDestroyed` before calling any methods on a BaseObject instance if you are not sure if it has been destroyed or not.",
    "source": {
        "line": 19,
        "path": "src/baseobject/src/BaseObject.lua"
    }
}