|
|
Line 1: |
Line 1: |
| This is code I often put at the top of my code (that's why this page is called "Heading Code", btw).
| | #redirect [[User:JulienDethurens/Scripts/Heading code]] |
| | |
| It contains many useful functions, many that I designed for making libraries easier to create.
| |
| | |
| == Variables ==
| |
| | |
| The code creates a variable that makes accessing the [[Terrain]] object easier, that variable is called "Terrain".
| |
| | |
| It also creates many variables for some services that I commonly use:
| |
| *Players
| |
| *StarterPack
| |
| *StarterGui
| |
| *Lighting
| |
| *Debris
| |
| *Teams
| |
| *BadgeService
| |
| *InsertService
| |
| | |
| Here are the functions defined by it:
| |
| | |
| == is_a(<var>value</var>, <var>data_type</var>) ==
| |
| | |
| {| class="wikitable"
| |
| |+ Parameters
| |
| ! Name !! Type !! Description
| |
| |-
| |
| | value || || The value you want to check the type of.
| |
| |-
| |
| | data_type || string || The type you want to check for.
| |
| |}
| |
| | |
| This function returns {{true}} if <var>value</var> is of type <var>data_type</var>. Otherwise, it returns {{false}}.
| |
| | |
| It supports the following types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray.
| |
| | |
| Just as a note, you can't use a "fake" value to make it return {{true}} with a value that is similar to a real value of the correct data type. If it says that the value is of the correct data type, then the value <strong>is</strong> of the correct data type.
| |
| | |
| == get_type(<var>value</var>) ==
| |
| | |
| {| class="wikitable"
| |
| |+ Parameters
| |
| ! Name !! Type !! Description
| |
| |-
| |
| |value || || The value you want to get the type of.
| |
| |}
| |
| | |
| This function returns the most specific type it can get for a certain value. It supports all the types supported by the '''is_a''' function.
| |
| | |
| == verify_arg(<var>value</var>, <var>data_type</var>, <var>arg_num</var>, <var>func_name</var>, <var>optional</var>) ==
| |
| | |
| {| class="wikitable"
| |
| |+ Parameters
| |
| ! Name !! Type !! Description
| |
| |-
| |
| | value || || The value you want the verify the type of.
| |
| |-
| |
| | data_type || string || The data type the value should be of.
| |
| |-
| |
| | arg_num || number || The № of the arg. Used in the error message.
| |
| |-
| |
| | func_name || string || The name of the function. Used in the error message.
| |
| |-
| |
| | optional || boolean || Whether the argument is optional or not. If {{true}}, the value {{nil}} will also be accepted.
| |
| |}
| |
| | |
| This function will check if <var>value</var> is of type <var>data_type</var>. If not, it will print an error message:
| |
| | |
| bad argument #arg_num to func_name (data_type expected, got [the type of the argument, found with the get_type function).
| |
| | |
| Use it in functions that receive arguments to check if arguments are of the correct type. Using this function can make debugging <strong>a lot</strong> easier (trust me, that's from experience).
| |
| | |
| == with(<var>instance</var>) ==
| |
| | |
| {| class="wikitable"
| |
| |+ Parameters
| |
| ! Name !! Type !! Description
| |
| |-
| |
| | instance || Instance || The instance you want to edit.
| |
| |}
| |
| | |
| This function allows you to edit the properties and the hierarchy of a certain object. Because I am too lazy to explain exactly how it works, and because you already have the code anyways, I will only give you an example:
| |
| | |
| {{code|=
| |
| local part with (Instance.new('Part')) {
| |
| Name = "Wall";
| |
| Position = Vector3.new(10, 50, 10);
| |
| with (Instance.new('Fire')) {
| |
| Heat = 10;
| |
| Size = 50;
| |
| };
| |
| }
| |
| }}
| |
| | |
| That code creates a part, sets its name to "Wall", sets its position to a certain Vector3, creates a Fire object in it, sets some of the properties of that Fire object, and stores the part in the <var>part</var> variable.
| |
| | |
| == recurse(<var>object</var>, <var>func</var>) ==
| |
| | |
| {| class="wikitable"
| |
| |+ Parameters
| |
| ! Name !! Type !! Description
| |
| |-
| |
| | object || Instance || The object you want to call a function on all the descendants of.
| |
| |-
| |
| | func || function || The function you want to call on all the descendants of the object.
| |
| |}
| |
| | |
| This function calls <var>func</var> on all the descendants of <var>object</var>, including <var>object</var> itself.
| |
| | |
| == The Code ==
| |
| | |
| Here is the code:
| |
| | |
| {{code|=
| |
| local Players = game:GetService('Players')
| |
| local StarterPack = game:GetService('StarterPack')
| |
| local StarterGui = game:GetService('StarterGui')
| |
| local Lighting = game:GetService('Lighting')
| |
| local Debris = game:GetService('Debris')
| |
| local Teams = game:GetService('Teams')
| |
| local BadgeService = game:GetService('BadgeService')
| |
| local InsertService = game:GetService('InsertService')
| |
| local Terrain = Workspace.Terrain
| |
| | |
| local function is_a(value, data_type)
| |
| -- Supported types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray
| |
| -- Will return false if the type is not supported, even though the value might be of that type.
| |
| -- This function can not be fooled by a fake value. If it says the value is a ClickDetector, then it IS a ClickDetector.
| |
| -- This function uses a variety of ugly hacks that were found by JulienDethurens.
| |
| -- I wish ROBLOX just provided an official way to do this, I wouldn't have to use lots of unrealiable ways to get the info I need... :/
| |
| | |
| -- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types:
| |
| if type(value) == data_type then return true end -- Lua types
| |
| if pcall(function() assert(game.IsA(value, data_type)) end) then return true end -- Instance types
| |
| if pcall(function() assert(Enum[data_type]) end) then -- Enum types
| |
| for _, enum in next, Enum[data_type]:GetEnumItems() do
| |
| if value == enum then
| |
| return true
| |
| end
| |
| end
| |
| elseif pcall(Enum.Material.GetEnumItems, value) then
| |
| for _, enum in next, value:GetEnumItems() do
| |
| if value == enum then
| |
| return true
| |
| end
| |
| end
| |
| end
| |
| if data_type == 'Color3' and pcall(function() Instance.new('Color3Value').Value = value end) then return true -- Color3
| |
| elseif data_type == 'BrickColor' and pcall(function() Instance.new('BrickColorValue').Value = value end) then return true -- BrickColor
| |
| elseif data_type == 'Vector2' and pcall(function() return Vector2.new() + value end) then return true -- Vector2
| |
| elseif data_type == 'Vector3' and pcall(function() Instance.new('Vector3Value').Value = value end) then return true -- Vector3
| |
| elseif (data_type == 'CFrame' or data_type == 'CoordinateFrame') and pcall(function() Instance.new('CFrameValue').Value = value end) then return true -- CFrame
| |
| elseif data_type == 'UDim' and pcall(function() return UDim.new() + value end) then return true -- UDim
| |
| elseif data_type == 'UDim2' and pcall(function() Instance.new('Frame').Position = value end) then return true -- UDim2
| |
| elseif data_type == 'Ray' and pcall(function() Ray.new(Vector3.new(), Vector3.new()).Distance(value, Vector3.new()) end) then return true -- Ray
| |
| elseif data_type == 'Axes' and pcall(function() Instance.new('ArcHandles').Axes = value end) then return true -- Axes
| |
| elseif data_type == 'Faces' and pcall(function() Instance.new('Handles').Faces = value end) then return true -- Faces
| |
| elseif data_type == 'Enum' and pcall(Enum.Material.GetEnumItems, value) then return true -- Enum
| |
| elseif data_type == 'RBXScriptSignal' then
| |
| local _, connection = pcall(function() return game.AllowedGearTypeChanged.connect(value) end)
| |
| if _ and connection then
| |
| connection:disconnect()
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end
| |
| | |
| local function get_type(value)
| |
| -- Returns the most specific type it can return. Supports the same types as the is_a function, except the enum types.
| |
| if is_a(value, 'Instance') then return value.ClassName
| |
| elseif is_a(value, 'Enum') then return 'Enum'
| |
| elseif is_a(value, 'Color3') then return 'Color3'
| |
| elseif is_a(value, 'BrickColor') then return 'BrickColor'
| |
| elseif is_a(value, 'Vector2') then return 'Vector2'
| |
| elseif is_a(value, 'Vector3') then return 'Vector3'
| |
| elseif is_a(value, 'CFrame') then return 'CFrame'
| |
| elseif is_a(value, 'UDim') then return 'UDim'
| |
| elseif is_a(value, 'UDim2') then return 'UDim2'
| |
| elseif is_a(value, 'Ray') then return 'Ray'
| |
| elseif is_a(value, 'Axes') then return 'Axes'
| |
| elseif is_a(value, 'Faces') then return 'Faces'
| |
| elseif is_a(value, 'RBXScriptSignal') then return 'RBXScriptSignal'
| |
| else return type(value)
| |
| end
| |
| end
| |
| | |
| local function verify_arg(value, data_type, arg_num, func_name, optional)
| |
| -- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports the same types as the is_a function.
| |
| -- Also supports coercion for the number and string types.
| |
| -- Returns the value, as it might be automatically converted if a coercion has been done.
| |
| if type(data_type) ~= 'string' then error("bad argument #2 to 'verify_arg' (string expected, got " .. type(data_type) .. ")", 2) end
| |
| if tonumber(arg_num) then
| |
| arg_num = tonumber(arg_num)
| |
| else
| |
| error("bad argument #3 to 'verify_arg' (number expected, got " .. type(arg_num) .. ")")
| |
| end
| |
| if type(func_name) ~= 'string' then error("bad argument #4 to 'verify_arg' (string expected, got " .. type(func_name) .. ")") end
| |
| | |
| if optional and value == nil then
| |
| return value
| |
| elseif is_a(value, data_type) then
| |
| return value
| |
| elseif data_type == 'number' and tonumber(value) then
| |
| return tonumber(value)
| |
| elseif data_type == 'string' and type(value) == 'number' then
| |
| return tostring(value)
| |
| else
| |
| error("bad argument #" .. arg_num .. " to " .. func_name .. " (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3)
| |
| end
| |
| end
| |
| | |
| local function with(instance)
| |
| verify_arg(instance, 'Instance', 1, "with")
| |
| return function(t)
| |
| if type(t) ~= 'table' then error("bad argument #1 (table expected, got " .. get_type(t) .. ")", 2) end -- The error message is different, it has no function name, so I can't use verify_arg.
| |
| for key, value in next, t do
| |
| if type(key) == 'number' then
| |
| value.Parent = instance
| |
| else
| |
| instance[key] = value
| |
| end
| |
| end
| |
| return instance
| |
| end
| |
| end
| |
| | |
| local function recurse(object, func)
| |
| -- Calls 'func' on 'object' and all its descendants, with the object or descendant as argument.
| |
| verify_arg(object, 'Instance', 1, "func")
| |
| verify_arg(func, 'function', 2, "func")
| |
| func(object)
| |
| for _, child in next, object:GetChildren() do
| |
| recurse(child, func)
| |
| end
| |
| end
| |
| |linenumbers=true
| |
| }}
| |
| | |
| == Additions ==
| |
| | |
| I did not put all of the code in the above section. I ignored the class system and the predefined classes I usually use. That is because I am going to use the class system present in the [[RbxUtility]] library as soon as it will be released. Not that I believe it is better than my own class system, I find mine to be a lot better, but using the one in the [[RbxUtility]] library will save me the trouble of including it at the top of all of my scripts, as well as the trouble of updating it and making sure it is kept up to date. It will also make my code actually use a class system that is recognized by ROBLOX and that more people know of, therefore making my code easier to understand for people who have never seen my class system used anywhere before.
| |
| | |
| But, in case you're interested, here is the whole code, including the class system and the classes that I usually use with it:
| |
| | |
| {{code|=
| |
| local Players = game:GetService('Players')
| |
| local StarterPack = game:GetService('StarterPack')
| |
| local StarterGui = game:GetService('StarterGui')
| |
| local Lighting = game:GetService('Lighting')
| |
| local Debris = game:GetService('Debris')
| |
| local Teams = game:GetService('Teams')
| |
| local BadgeService = game:GetService('BadgeService')
| |
| local InsertService = game:GetService('InsertService')
| |
| local Terrain = Workspace.Terrain
| |
| | |
| local function is_a(value, data_type)
| |
| -- Supported types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray
| |
| -- Will return false if the type is not supported, even though the value might be of that type.
| |
| -- This function can not be fooled by a fake value. If it says the value is a ClickDetector, then it IS a ClickDetector.
| |
| -- This function uses a variety of ugly hacks that were found by JulienDethurens.
| |
| -- I wish ROBLOX just provided an official way to do this, I wouldn't have to use lots of unrealiable ways to get the info I need... :/
| |
| | |
| -- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types:
| |
| if type(value) == data_type then return true end -- Lua types
| |
| if pcall(function() assert(game.IsA(value, data_type)) end) then return true end -- Instance types
| |
| if pcall(function() assert(Enum[data_type]) end) then -- Enum types
| |
| for _, enum in next, Enum[data_type]:GetEnumItems() do
| |
| if value == enum then
| |
| return true
| |
| end
| |
| end
| |
| elseif pcall(Enum.Material.GetEnumItems, value) then
| |
| for _, enum in next, value:GetEnumItems() do
| |
| if value == enum then
| |
| return true
| |
| end
| |
| end
| |
| end
| |
| if data_type == 'Color3' and pcall(function() Instance.new('Color3Value').Value = value end) then return true -- Color3
| |
| elseif data_type == 'BrickColor' and pcall(function() Instance.new('BrickColorValue').Value = value end) then return true -- BrickColor
| |
| elseif data_type == 'Vector2' and pcall(function() return Vector2.new() + value end) then return true -- Vector2
| |
| elseif data_type == 'Vector3' and pcall(function() Instance.new('Vector3Value').Value = value end) then return true -- Vector3
| |
| elseif (data_type == 'CFrame' or data_type == 'CoordinateFrame') and pcall(function() Instance.new('CFrameValue').Value = value end) then return true -- CFrame
| |
| elseif data_type == 'UDim' and pcall(function() return UDim.new() + value end) then return true -- UDim
| |
| elseif data_type == 'UDim2' and pcall(function() Instance.new('Frame').Position = value end) then return true -- UDim2
| |
| elseif data_type == 'Ray' and pcall(function() Ray.new(Vector3.new(), Vector3.new()).Distance(value, Vector3.new()) end) then return true -- Ray
| |
| elseif data_type == 'Axes' and pcall(function() Instance.new('ArcHandles').Axes = value end) then return true -- Axes
| |
| elseif data_type == 'Faces' and pcall(function() Instance.new('Handles').Faces = value end) then return true -- Faces
| |
| elseif data_type == 'Enum' and pcall(Enum.Material.GetEnumItems, value) then return true -- Enum
| |
| elseif data_type == 'RBXScriptSignal' then
| |
| local _, connection = pcall(function() return game.AllowedGearTypeChanged.connect(value) end)
| |
| if _ and connection then
| |
| connection:disconnect()
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end
| |
| | |
| local function get_type(value)
| |
| -- Returns the most specific type it can return. Supports the same types as the is_a function, except the enum types.
| |
| if is_a(value, 'Instance') then return value.ClassName
| |
| elseif is_a(value, 'Enum') then return 'Enum'
| |
| elseif is_a(value, 'Color3') then return 'Color3'
| |
| elseif is_a(value, 'BrickColor') then return 'BrickColor'
| |
| elseif is_a(value, 'Vector2') then return 'Vector2'
| |
| elseif is_a(value, 'Vector3') then return 'Vector3'
| |
| elseif is_a(value, 'CFrame') then return 'CFrame'
| |
| elseif is_a(value, 'UDim') then return 'UDim'
| |
| elseif is_a(value, 'UDim2') then return 'UDim2'
| |
| elseif is_a(value, 'Ray') then return 'Ray'
| |
| elseif is_a(value, 'Axes') then return 'Axes'
| |
| elseif is_a(value, 'Faces') then return 'Faces'
| |
| elseif is_a(value, 'RBXScriptSignal') then return 'RBXScriptSignal'
| |
| else return type(value)
| |
| end
| |
| end
| |
| | |
| local function verify_arg(value, data_type, arg_num, func_name, optional)
| |
| -- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports the same types as the is_a function.
| |
| -- Also supports coercion for the number and string types.
| |
| -- Returns the value, as it might be automatically converted if a coercion has been done.
| |
| if type(data_type) ~= 'string' then error("bad argument #2 to 'verify_arg' (string expected, got " .. type(data_type) .. ")", 2) end
| |
| if tonumber(arg_num) then
| |
| arg_num = tonumber(arg_num)
| |
| else
| |
| error("bad argument #3 to 'verify_arg' (number expected, got " .. type(arg_num) .. ")")
| |
| end
| |
| if type(func_name) ~= 'string' then error("bad argument #4 to 'verify_arg' (string expected, got " .. type(func_name) .. ")") end
| |
| | |
| if optional and value == nil then
| |
| return value
| |
| elseif is_a(value, data_type) then
| |
| return value
| |
| elseif data_type == 'number' and tonumber(value) then
| |
| return tonumber(value)
| |
| elseif data_type == 'string' and type(value) == 'number' then
| |
| return tostring(value)
| |
| else
| |
| error("bad argument #" .. arg_num .. " to " .. func_name .. " (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3)
| |
| end
| |
| end
| |
| | |
| local function with(instance)
| |
| verify_arg(instance, 'Instance', 1, "with")
| |
| return function(t)
| |
| if type(t) ~= 'table' then error("bad argument #1 (table expected, got " .. get_type(t) .. ")", 2) end -- The error message is different, it has no function name, so I can't use verify_arg.
| |
| for key, value in next, t do
| |
| if type(key) == 'number' then
| |
| value.Parent = instance
| |
| else
| |
| instance[key] = value
| |
| end
| |
| end
| |
| return instance
| |
| end
| |
| end
| |
| | |
| local function recurse(object, func)
| |
| -- Calls 'func' on 'object' and all its descendants, with the object or descendant as argument.
| |
| verify_arg(object, 'Instance', 1, "func")
| |
| verify_arg(func, 'function', 2, "func")
| |
| func(object)
| |
| for _, child in next, object:GetChildren() do
| |
| recurse(child, func)
| |
| end
| |
| end
| |
| | |
| local function create(constructor, ...)
| |
| -- Sometimes, there will be only one object of a certain kind. In such cases, creating a class would be useless.
| |
| verify_arg(constructor, 'function', 1, "create")
| |
| local content = {} -- This will by default be the content of the object, unless the user decides to change the __index metamethod of his object.
| |
| local metatable = setmetatable({__index = content, __metatable = false}, locked_metatable) -- Creates a locked metatable. I'm not going to let the user edit his object's metatable's metatable...
| |
| local returned_values = {constructor(content, metatable, ...)} -- Execute the constructor. Gives a content table, but also the metatable, for further customization.
| |
| local object = newproxy(true)
| |
| metatable.__metatable = false -- Incase the user edited the __metatable field.
| |
| for key, value in next, metatable do
| |
| if type(key) == 'string' and key:sub(1, 2) == "__" then
| |
| getmetatable(object)[key] = value
| |
| end
| |
| end
| |
| return object, unpack(returned_values)
| |
| end
| |
| | |
| local class, new
| |
| | |
| do -- Only the class and new functions are supposed to have access to the constructors table.
| |
| local locked_metatable = {__metatable = false} -- To avoid having to create a new table everytime.
| |
| local constructors = {}
| |
| function class(class_name, constructor)
| |
| class_name = verify_arg(class_name, 'string', 1, "class")
| |
| verify_arg(constructor, 'function', 2, "class")
| |
| if constructors[class_name] then error("bad argument #1 to 'class' (can't overwrite existing class')", 2) end
| |
| constructors[class_name] = constructor
| |
| end
| |
| function new(class_name, ...)
| |
| if not constructors[class_name] then error("bad argument #1 to 'new' (invalid class name)", 2) end
| |
| local content = {
| |
| ClassName = class_name;
| |
| } -- This will by default be the content of the object, unless the user decides to change the __index metamethod of his object.
| |
| local metatable = setmetatable({__index = content, __metatable = false}, locked_metatable) -- Creates a locked metatable. I'm not going to let the user edit his object's metatable's metatable...
| |
| local returned_values = {constructors[class_name](content, metatable, ...)} -- Execute the constructor. Gives a content table, but also the metatable, for further customization.
| |
| local object = newproxy(true)
| |
| metatable.__metatable = false -- Incase the user edited the __metatable field.
| |
| for key, value in next, metatable do
| |
| -- Transfer the metatable to the object's metatable.
| |
| if type(key) == 'string' and key:sub(1, 2) == "__" then
| |
| getmetatable(object)[key] = value
| |
| end
| |
| end
| |
| return object, unpack(returned_values)
| |
| end
| |
| end
| |
| | |
| -- Requires the basic functions.
| |
| | |
| class('Connection', function(content, listeners, func)
| |
| function content:Delete()
| |
| for key in next, content do
| |
| content[key] = nil
| |
| end
| |
| content, listeners, func = nil
| |
| end
| |
| | |
| function content:Disconnect()
| |
| listeners[func] = nil
| |
| content:Delete()
| |
| end
| |
| end)
| |
| | |
| class('Signal', function(content)
| |
| local listeners = {}
| |
| | |
| function content:Delete()
| |
| listeners = nil
| |
| for key in next, content do
| |
| content[key] = nil
| |
| end
| |
| content = nil
| |
| end
| |
| | |
| function content:Connect(func)
| |
| check_arg(func, 'function', 1, "Connect")
| |
| listeners[func] = true
| |
| return new('Connection', listeners, func)
| |
| end
| |
| return function(...)
| |
| for listener in next, listeners do
| |
| listener(...)
| |
| end
| |
| end
| |
| end)
| |
| | |
| class('Value', function(content, metatable, required_type, accept_nil)
| |
| if required_type ~= nil and type(required_type) ~= 'string' then
| |
| error("bad argument #1 (string expected, got " .. get_type(required_type) .. ")", 3) -- Yes, 3. It isn't the class system that did a mistake, it is the function that called the class system. Therefore, 3.
| |
| end
| |
| local fire
| |
| content.Changed, fire = new('Signal')
| |
| content.Value = nil
| |
| function metatable.__newindex(_, index, value)
| |
| if index ~= "Value" then
| |
| error("attempt to index a userdata value", 2)
| |
| elseif not is_a(value, required_type) and not (value == nil and accept_nil) then
| |
| error(required_type .. " expected, got " .. get_type(value), 2)
| |
| else
| |
| content.Value = value
| |
| fire(value)
| |
| end
| |
| end
| |
| end)
| |
| | |
| class('ReadOnlyValue', function(content, _, required_type, accept_nil)
| |
| if required_type ~= nil and type(required_type) ~= 'string' then
| |
| error("bad argument #1 (string expected, got " .. get_type(required_type) .. ")", 3) -- Yes, 3. It isn't the class system that did a mistake, it is the function that called the class system. Therefore, 3.
| |
| end
| |
| local fire
| |
| content.Changed, fire = new('Signal')
| |
| content.Value = nil
| |
| return function(value)
| |
| if is_a(value, required_type) or (value == nil and accept_nil) then
| |
| content.Value = value
| |
| fire(value)
| |
| else
| |
| error(required_type .. " expected, got " .. get_type(value), 2)
| |
| end
| |
| content.Value = value
| |
| fire(value)
| |
| end
| |
| end)
| |
| | |
| class('Collector', function(content)
| |
| local items = setmetatable({}, {__mode = 'kv'})
| |
| | |
| function content:Delete()
| |
| for key in next, items do
| |
| items[key] = nil
| |
| end
| |
| for key in next, content do
| |
| content[key] = nil
| |
| end
| |
| items, content = nil
| |
| end
| |
| | |
| function content:AddInstance(instance)
| |
| check_arg(instance, 'Instance', 1, "AddInstance")
| |
| table.insert(items, instance)
| |
| end
| |
| | |
| function content:AddConnection(connection)
| |
| -- Note: this function might get fooled by a fake connection, since there is no way to know for sure whether a value is a RBXScriptConnection without disconnecting it. And, anyways, I also want it to work with my Signal class, so anyways...
| |
| if not (type(connection) == 'userdata' and pcall(function() assert(type(connection.disconnect) == 'function' or type(connection.Disconnect) == 'function') end)) then
| |
| error("bad argument #1 to 'AddConnection' (connection expected, got " .. get_type(connection) .. ")", 2)
| |
| end
| |
| table.insert(items, connection)
| |
| end
| |
| | |
| function content:Clear()
| |
| for _, item in next, items do
| |
| if is_a(item, 'Instance') then
| |
| pcall(item.Destroy, item)
| |
| else
| |
| pcall(function() item:disconnect() end)
| |
| pcall(function() item:Disconnect() end)
| |
|
| |
| end
| |
| end
| |
| end
| |
| end)
| |
| |linenumbers=true
| |
| }}
| |