Skip to content

API

The official API for Tome giving basic examples for constructors, embedded systems and methods.


Constructors

Tome uses a single constructor to create a Tome object

Tome.new

Arguments

  1. metaprops: Metaprops? — The Metaprops object to use when instantiating the Tome.

Returns

  1. tome: Tome — Returns a new Tome object.

Creating a Tome is very easy.

local newTome = Tome.new()
local newTome: Tome.Tome = Tome.new()

Functions

Functions in Tome can be used directly from the module without instantiation.

Tome.Is

Arguments

  1. object: any — The object to check.

Returns

  1. isATome: boolean — Whether the object is a Tome.

Returns whether the provided object is a Tome object. This function will check against the direct metatable, and Tome:BindRenderStepped method (to track earlier versions)

1
2
3
4
5
local newTome = Tome.new()

print("#1 Is this object a Tome? ", Tome.Is({})) -- false
print("#2 Is this object a Tome? ", Tome.Is(newTome)) -- true
print("#3 Is this object a Tome? ", Tome.Is()) -- false

Tome.schedule

Arguments

  1. object: any — The object to schedule.
  2. lifeTime: number — The life time to give the object.
  3. destroyMethod: DestroyMethod? — The DestroyMethod to use when destroying the object.

Returns

  1. object: object — The same object that was passed in.

Adds the provided object into the Scheduler. The object will be destroyed after the provided life time has elapsed.

Tome.schedule(workspace.Part, 2.0) -- destroys the part after ~2 seconds

In this example, the 3rd argument lets Tome know how the object will be destroyed.

Tome.schedule(workspace.Part, 2.0, "Destroy") -- destroys the part after ~2 seconds

Tome.unschedule

Arguments

  1. object: any — The object to unschedule.

Returns

  1. object: object — The same object that was passed in.

Removes the provided object from the Scheduler. The object will not be destroyed.

1
2
3
4
5
Tome.schedule(workspace.Part, 2.0) -- destroys the part after ~2 seconds

task.wait(1)

Tome.unschedule(workspace.Part) -- we decide to change our mind

Tome.group

Arguments

  1. Tuple: ...any — The tuple set of objects to group.

Returns

  1. objects: Group<any> — The same objects that were passed in, in array form.

Groups together the provided tuple set of objects and puts them inside an array attached to a Tome group metatable to use as a symbol.

Grouping is currently only used for Tome.schedule and can be used to destroy objects as a group, rather than one by one. If you find yourself calling Tome.schedule a lot, you may benefit from this.

You can also call the group like a function, and it will destroy the objects as well.

1
2
3
local myParts: Tome.Group<BasePart> = Tome.group(workspace.Part, workspace.Part2)

Tome.schedule(myParts, 2.0) -- destroys the group (and both parts)
1
2
3
local myParts: Tome.Group<BasePart> = Tome.group(workspace.Part, workspace.Part2)

myParts() -- destroys the group (and both parts)

Variables

Get access to Tome internals to speed up certain methods manually.

Tome.FunctionType

Providing this as a DestroyMethod for methods like Tome:Add can significantly speed up adding functions into the Tome.

1
2
3
4
5
local newTome = Tome.new()

newTome:Add(function()

end, Tome.FunctionType) -- Tome will skip finding a DestroyMethod and use this instead.

Tome.ThreadType

Providing this as a DestroyMethod for methods like Tome:Add can significantly speed up adding threads into the Tome.

1
2
3
4
5
6
7
local newTome = Tome.new()

local myThread: thread = task.spawn(function()

end)

newTome:Add(myThread, Tome.ThreadType) -- Tome will skip finding a DestroyMethod and use this instead.

Tome.TweenType

Providing this as a DestroyMethod for methods like Tome:Add can significantly speed up adding tweens into the Tome.

This DestroyMethod will first call Tween:Cancel and then Tween:Destroy.

1
2
3
4
5
local newTome = Tome.new()

local tween: Tween = TweenService:Create(...)

newTome:Add(tween, Tome.TweenType) -- Tome will skip finding a DestroyMethod and use this instead.

Tome.Guess

This is usually only used in pair with Tome:AddFromDictionary. This is used as a value in the dictionary to let Tome know that it should calculate the DestroyMethod.

1
2
3
4
5
6
7
local newTome = Tome.new()

local objects: {[any]: Tome.DestroyMethod} = {
    [workspace.Part] = Tome.Guess,
}

newTome:AddFromDictionary(objects)

Tome.Scheduler

Returns the Scheduler that Tome is using. This can be (but not recommended) used to modify certain aspects of the Scheduler.

The majority of these functions should not be called outside debugging purposes. Changes to the Scheduler will affect the entire environment, not only the scope that made the changes.

At some point an API may be created to allow for multiple Schedulers to be created and used within a single scope.

Scheduler.startScheduler

This starts up the Scheduler (if it isn't already running) this is usually only called within Tome.

Scheduler.stopScheduler

This suspends the Scheduler in place. Meaning objects that are currently inside will not get destroyed, even if their life time is exceeded.

Scheduler.stepScheduler

Steps the Scheduler forward. This will check the first object within the Scheduler, and if it's ready to be destroyed, then it will be.

Scheduler.isScheduleEmpty

A more practical function that returns whether the Scheduler is empty; whether it has no objects.

Scheduler.isSchedulerRunning

Returns whether the Scheduler is currently running.

Scheduler.DefaultSchedulerSignalName

This determines what RunService signal to use for the Scheduler. The only options are:

"RenderStepped"
"Heartbeat"
"PostSimulation"
"PreAnimation"
"PreRender"
"PreSimulation"
"Stepped"

Every time the signal fires, the Scheduler will step.

If this variable is changed, the Scheduler must be reconciled with:

Tome.stopScheduler()
Tome.DefaultSchedulerSignalName = "PreAnimation" -- or your preferred signal kind
Tome.startScheduler()


Tome.VERSION

Returns the version of the Tome being used.

1
2
3
local TomeVersion: string = Tome.VERSION

print(TomeVersion) --> "v#.#.#.#"

Metamethods

Since Tome is a metatable-based library, it comes with some useful metamethods that help with debugging and general use. Some of these can also be found in other libraries, so woo! Extra transition support.


Tome.__call

Arguments

  1. Tuple: ...any — The arguments to pass into Tome:Destroy.

Destroys the Tome just like Tome:Destroy. Will also take in a tuple of arguments to pass into destroy callbacks for Tome:OnDestroy.

1
2
3
local newTome: Tome.Tome = Tome.new()

newTome() --> destroys the Tome

Tome.__add

Arguments

  1. object: any — The object to add into the Tome.

Returns

  1. object: object — Returns the same object passed in.

Adds in an object just like Tome:Add and returns it.

1
2
3
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome + workspace.Part

Tome.__sub

Arguments

  1. object: any — The object to remove from the Tome.

Returns

  1. object: object — Returns the same object passed in.

Removes an object just like Tome:Remove and returns it.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)

local part: BasePart = newTome - workspace.Part

Tome.__len

Returns

  1. objectCount: number — The amount of objects.

Returns the amount of objects inside the Tome.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)
newTome:Add(workspace.Part2)

print(#newTome) --> 2

Tome.__iter

Returns

  1. iterator: () -> (any, DestroyMethod) — A custom iterator.

Returns a custom iterator to use in for x in y do that will iterate through all the objects within the Tome.

local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)
newTome:Add(workspace.Part2)

for object: BasePart, destroyMethod: Tome.DestroyMethod in newTome do
    print(object, destroyMethod)
end

--> "Part", "Destroy"
--> "Part2", "Destroy"

Methods

Tome offers a variety of methods to use on a Tome object


Tome:Add

Arguments

  1. object: any — The object to add into the Tome. Usually an Instance, RBXScriptConnection or a class.
  2. destroyMethod: DestroyMethod? — Destroy method to use instead of Tome finding the destroy method.

Returns

  1. object: any — Returns the same object provided in argument #1.

The primary method of adding an object into the Tome.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part) -- adds the part into the Tome

newTome:Destroy()

Optimization & Finer control

Now if you need finer control over how to destroy the object, you can use the second argument. When using the second argument, Tome will skip over finding the destroy method and use what's provided instead.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part, function(part: BasePart)
    print("Going to destroy this part!", part:GetFullName())

    part:Destroy()
end)

newTome:Destroy()

Internally Tome will conclude "Destroy" as the destroy method for Instances. Tome is always unaware of the type of object you provide, so it has to come up with the destroy method at run time. Giving Tome a destroy method improves write speed signficantly in a lot of cases:

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part, "Destroy")

newTome:Destroy()


Tome:AddTuple

Arguments

  1. Tuple: ...any — Any number of tuple objects to add into the Tome.

Returns

  1. Tuple: ...any — Returns the same tuple (and retaining order) provided.

For adding any tuple amount of objects into the Tome. The objects will be returned in the same order they were provided in.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:AddTuple(workspace.Part, workspace.Part2, workspace.Part3) -- adds all 3 parts into the Tome

newTome:Destroy()
1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

-- variabalize both parts
local part: BasePart, part2: BasePart = newTome:AddTuple(workspace.Part, workspace.Part2)

newTome:Destroy()

Tome:AddFromArray

Arguments

  1. array: {any} — The array of objects to add into the Tome.

Returns

  1. array: {any} — Returns the same array that was provided in argument #1.

For adding an array of objects into the Tome. Useful in cases where it's preferable to call this instead of iterating through the array manually.

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

local myParts: {Part} = {workspace.Part, workspace.Part2, workspace.Part3}

newTome:AddFromArray(myParts) -- adds all 3 parts from 'myParts'

newTome:Destroy()


Tome:AddFromDictionary

Arguments

  1. dictionary: {[any]: DestroyMethod | Tome.Guess} — The dictionary of objects to add into the Tome.

Returns

  1. dictionary: {[any]: DestroyMethod | Tome.Guess} — Returns the same dictionary that was provided in argument #1.

In some cases you may want to optimize adding objects into the Tome. One way you can do this is by having a dictionary on a:

[key]: object
[value]: DestroyMethod
basis.

In some scenarios you may not know what destroy method to put as the value in the pair, this is where Tome.Guess comes in. Using this as the value will let Tome know to find the destroy method for the object.

local newTome: Tome.Tome = Tome.new()

local myParts: {[BasePart]: Tome.DestroyMethod} = {
    [workspace.Part] = "Destroy",
    [workspace.Part2] = function(part: BasePart)
        print("Going to destroy part2!")

        part:Destroy()
    end,
}

newTome:AddFromDictionary(myParts)

newTome:Destroy()

Imagine having to add hundreds of newly created objects into the Tome. Adding them one by one with Tome:Add will work fine, however adding them as a dictionary will improve performance significantly:

local newTome: Tome.Tome = Tome.new()

local myParts: {[BasePart]: Tome.DestroyMethod} = {}

for index: number = 1, 1_000 do
    local myPart: BasePart = Instance.new("Part")
    myPart.Position = Vector3.new(0, 20, 0)
    myPart.Parent = workspace

    myParts[myPart] = "Destroy"
end

newTome:AddFromDictionary(myParts)

newTome:Destroy()


Tome:AddPromise

Arguments

  1. promise: Promise — The Promise to add into the Tome.

Returns

  1. promise: Promise — Returns the same Promise that was provided in argument #1.

Adds in a standard Promise object into the Tome. The Promise must have :cancel, :finally and :getStatus as methods. Moreover, :getStatus must return "started" as a status when provided, otherwise an error will be thrown.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

local newPromise: Promise.Promise = Promise.new(function()
    return -- ... some yielding code
end)

newTome:AddPromise(newPromise)

newTome:Destroy() -- now when the Tome is destroyed, the Promise above will get cancelled


Tome:AddPage

Arguments

  1. name: string? — Providing a name will open up the ability to use other methods such as Tome:GetPage. Internally helps with debugging as well.
  2. metaprops: Metaprops? — Providing Metaprops will apply them to the new Page when constructing.

Returns

  1. page: Tome — Returns a new Page (Tome)

Instantiates a new Page (alias for Tome when referring to a Tome within a Tome) Unlike a regular object, a Page gets added to a seperate table internally, which allows for faster querying, and gives you control over how Pages are handled.

When the Tome that created the Page is destroyed, the Page will also destroy; cleaning up all the objects inside of it, and any sub-Pages.

Pages are not released on destruction

When a Page is added into the Tome, Tome doesn't see it as just another regular object, Tome will keep the Page alive until manually removed with Tome:RipPage or Tome:RipPages. Not freeing the Page will not result in a memory leak, at some point once the Tome is done being used, luau's garbage collector will automatically free it.

If you absolutely need a Page to be removed on destruction, you can manually pass it into the Tome as though it were an object:

local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:Add(Tome.new()) -- will get cleaned up once Tome is destroyed
This is not recommended, as you lose control over time in more complex systems. One-off cases are usually safe.

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage("MyPage")

newPage:Add(workspace.Part) -- adds the Part into the Page

newTome:Destroy() -- now when the Tome is destroyed, the Page gets destroyed, which also includes the Part
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage("MyPage")

newPage:Add(workspace.Part)

newTome:Destroy()

print(newTome:GetPage("MyPage")) --> 'newPage'

newTome:RipPage("MyPage")

print(newTome:GetPage("MyPage")) --> nil

Tome:Attach

Arguments

  1. object: Tome | Instance | RBXScriptSignal | {Connect: () -> ()} — The object that the Tome will attach to.

Returns

  1. attachment: Attachment — Returns an attachment which can be cleaned up to unattach the attachment.

Attaches the Tome to one of the few object types. Once attached, when either triggers are fired, the Tome will destroy itself.

Attachments are not cleaned up when the Tome is destroyed. For example, if a Signal is provided, and the Signal gets fired n times, the Tome will also be destroyed n times until the Signal is either destroyed, or the attachment is unattached.

It's also important to note that if an Instance that doesn't have a parent is attached, no attachment will be made and nothing is returned.

local newTome: Tome.Tome = Tome.new()

local part: BasePart = workspace.Part
newTome:Attach(newTome)

newTome:Add(function()
    print("Tome has been destroyed")
end)

part:Destroy() -- destroying the part will now destroy the Tome

In this example, an attachment is stored in the variable attachmentCleanup. This attachment can be "cleaned up" at any time, and once cleaned, will prevent the object from invoking Tome:Destroy again.

local newTome: Tome.Tome = Tome.new()

newTome:OnDestroy(function()
    print("Tome destroyed")
end)

local signal: Signal.Signal = Signal.new()
local attachmentCleanup: Tome.Attachment? = newTome:Attach(signal) -- attach the Signal

signal:Fire() --> "Tome destroyed (1x)"
signal:Fire() --> "Tome destroyed (2x)"
signal:Fire() --> "Tome destroyed (3x)"

if type(attachmentCleanup) == "table" then
    attachmentCleanup:Disconnect() -- disconnect the attachment
end

signal:Fire() --> nothing happens


Tome:AttachTuple

Arguments

  1. Tuple: ...(Tome | Instance | RBXScriptSignal | {Connect: () -> ()}) — The tuple of objects that the Tome will attach to.

Returns

  1. cleanUp: () -> () — The clean up function.
  2. attachments: {Attachment} — The array of attachments (shouldn't be mutated)

Works just like Tome:Attach however any amount of objects can be provided, and once all the objects are successfully connected, a single clean up function is returned, which when called, will free all the attachments at once.

It's important to note that this method internally calls Tome:Attach. The same warning(s) apply from Tome:Attach, to here.

local newTome: Tome.Tome = Tome.new()
newTome:OnDestroy(function()
    print("Tome destroyed")
end)

local part: BasePart = workspace.Part
local part2: BasePart = workspace.Part2

local cleanUp: () -> () = newTome:AttachTuple(part, part2)

part:Destroy() --> "Tome destroyed (1x)"
part2:Destroy() --> "Tome destroyed (2x)"
local newTome: Tome.Tome = Tome.new()
newTome:OnDestroy(function()
    print("Tome destroyed")
end)

local part: BasePart = workspace.Part
local part2: BasePart = workspace.Part2
local part3: BasePart = workspace.Part3

local cleanUp: () -> () = newTome:AttachTuple(part, part2, part3)

part:Destroy() --> "Tome destroyed (1x)"
part2:Destroy() --> "Tome destroyed (2x)"

cleanUp()

part3:Destroy() --> nothing happens

Tome:BindRenderStepped

Arguments

  1. name: string — The name of the render step binding.
  2. renderPriority: number — The name of the render step binding.
  3. listener: (deltaTime: number) -> () — The name of the render step binding.

Returns

  1. unbind: () -> () — The unbind function (manual clean up)

Calls the RunService:BindToRenderStep method. Tome adds a function inside of itself to unbind the render binding once the Tome is destroyed.

Optionally you can call the unbind() function returned to manually clean up the binding.

In this example, the binding will output the delta time each frame until 2 seconds have elapsed.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

local cleanUp: Tome.CallableRenderStepBinding = newTome:BindRenderStepped("test-binding", 201, function(deltaTime: number)
    print(deltaTime)
end)

task.wait(2)

cleanUp()


Tome:CanDestroy

Returns

  1. canDestroy: boolean — Whether the Tome can be destroyed at this moment in time.

Returns whether the Tome can be destroyed in this current moment of time. You only need to call this before using methods that throw an error when attempting to mutate the Tome during its destroy life cycle.

In this example, the Tome is running with SpawnDestroy = false, hence the task.defer. Adding a yielding function will temporarily halt the destroy thread, keeping the Tome in a destroying state.

local newTome: Tome.Tome = Tome.new()

task.defer(function()
    print(newTome:CanDestroy())
end)

newTome:Add(function()
    task.wait(2)
end)

newTome:Destroy()


Tome:Clone

Arguments

  1. object: any — The object to clone
  2. extendFunctionName: string? — The method to call on the object to clone it.

Returns

  1. clonedObject: any — The cloned object.

Clones the provided object using the object:Clone() as the clone method (unless overridden by the 2nd argument)

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local clonedPart: BasePart = newTome:Clone(workspace.Part)

newTome:Destroy() -- Destroys the cloned part

Tome:Connect

Arguments

  1. Signal: Signal — The Signal to connect to.
  2. listener: (...any) -> () — The listener function to connect with.

Returns

  1. Connection: {Disconnect: () -> ()} | RBXScriptConnection — The Connection object.

Connects to a Signal, and adding it into the Tome. Can be a custom-made Signal or an RBXScriptSignal.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Connect(workspace.ChildAdded, function(child: Instance)
    print(child:GetFullName())
end)

Tome:Once

Arguments

  1. Signal: Signal — The Signal to connect to.
  2. listener: (...any) -> () — The listener function to connect with.

Returns

  1. Connection: {Disconnect: () -> ()} | RBXScriptConnection — The Connection object.

Works exactly the same as Tome:Connect, however only connecting to a Signal once, and adding it into the Tome. Can be a custom-made Signal or an RBXScriptSignal.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Once(workspace.ChildAdded, function(child: Instance)
    print(child:GetFullName())
end)

Tome:Construct

Arguments

  1. class: {new: () -> ()} | () -> () — The class to construct.
  2. Tuple: ...any — The arguments to pass into the constructor.

Returns

  1. Class: any — The constructed class.

Constructs a class containing a Class.new() constructor function. Optionally you can pass in the constructor function if your class uses another name for construction.

Any amount of arguments can be passed in after the class/constructor, which will be passed into it. After construction, the class object is added into the Tome.

local newTome: Tome.Tome = Tome.new()

-- simulate a custom class
local Class = {
    new = function()
        return {}
    end,
}

local newClass: any = newTome:Construct(Class)
local newTome: Tome.Tome = Tome.new()

-- simulate a custom class
local Class = {
    create = function(name: string, health: number)
        return {
            name = name,
            health = health,
        }
    end,
}

local newClass: any = newTome:Construct(Class.create, "Tea", 100)

Tome:Delay

Arguments

  1. duration: number — The amount of time to delay.
  2. listener: (...any) -> ...any — The listener function to call after the delay.
  3. Tuple: ...any — The params to pass into the listener.

Returns

  1. thread: thread — The delayed thread.

Calls task.delay, adds the delayed thread into the Tome, and returns it.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Delay(2.0, function()
    print("Prints after 2 seconds")
end)
1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Delay(2.0, function(argument: number)
    print("The argument passed: ", argument)
end, 25)

Tome:extend

Duplicate of Tome:AddPage


Tome:Extend

Duplicate of Tome:AddPage


Tome:FastAdd

Arguments

  1. object: any — The object to add into the Tome.
  2. destroyMethod: DestroyMethod? — Destroy method to use instead of Tome finding the destroy method.

Returns

  1. object: object — The same object passed in.

The same as Tome:Add but executes without the majority of features in Tome. This method will skip over sanity checks like whether the Tome is currently being destroyed, tagging, and recursion mistakes with nested Tomes.

If you prioritize speed over features, then using this will benefit you.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:FastAdd(workspace.Part) -- adds the Part, just faster

newTome:Destroy() --> destroys the part as normal

Tome:Spawn

Arguments

  1. listener: (...any) -> ...any — The listener function to call when spawning.
  2. Tuple: ...any — The params to pass into the listener.

Returns

  1. thread: thread — The spawned thread.

Calls task.spawn, adds the spawned thread into the Tome, and returns it.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Spawn(function()
    print("Running in a spawned thread")
end)
1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Spawn(function(argument: number)
    print("The argument passed: ", argument)
end, 25)

Tome:Defer

Arguments

  1. listener: (...any) -> ...any — The listener function to call after the defer.
  2. Tuple: ...any — The params to pass into the listener.

Returns

  1. thread: thread — The deferred thread.

Calls task.defer, adds the deferred thread into the Tome, and returns it.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Defer(function()
    print("Running in a spawned thread")
end)
1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Defer(function(argument: number)
    print("The argument passed: ", argument)
end, 25)

Tome:DelayDestroy

Arguments

  1. duration: number — The amount of time (in seconds) to delay the destroy.

Returns

  1. thread: thread — The thread responsible for destroying the Tome.

Calls task.delay, with the 1st argument being 'duration'. Once that time has elapsed successfully, the thread will call Tome:Destroy internally.

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:Add(function()
    print("Tome destroyed")
end)

newTome:DelayDestroy(2.0)

Tome:Destroy

Arguments

  1. Tuple: ...any — Any amount of params to pass into the Tome:OnDestroy callbacks.

Internally calls Tome:DestroyAllObjects and Tome:DestroyAllPages. During both states of destruction, the Tome will enter a destroying state, where most attempts at mutation e.g. Tome:Add will throw an error. This state is usually very short lived (<0.00001s)

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:Add(function()
    print("Tome destroyed")
end)

newTome:Destroy()
1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:OnDestroy(function(argument: string)
    print(argument)
end)

newTome:Destroy("Hello, world")

Tome:DestroyAllObjects

Arguments

  1. __ignoreDestroyingProperty: boolean? — Internal argument to skip over checking whether the Tome is currently destroying.

Destroys all the objects inside the Tome. Doesn't destroy Pages.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)

newTome:DestroyAllObjects() --> destroys the part
1
2
3
4
5
6
7
8
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)

local newPage: Tome.Tome = newTome:AddPage("Test")
newPage:Add(workspace.Part2)

newTome:DestroyAllObjects() --> destroys only part 1, and doesn't destroy the Page

Tome:DestroyAllPages

Arguments

  1. __ignoreDestroyingProperty: boolean? — Internal argument to skip over checking whether the Tome is currently destroying.

Destroys all the Pages inside the Tome. Doesn't destroy objects.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage("Test")
newPage:Add(workspace.Part)

newTome:DestroyAllPages() --> destroys the Page "test" along with the part
1
2
3
4
5
6
7
8
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)

local newPage: Tome.Tome = newTome:AddPage("Test")
newPage:Add(workspace.Part2)

newTome:DestroyAllPages() --> destroys only the Page "test" alongside part 2

Tome:DestroyObject

Arguments

  1. object: any — The object to destroy.

Destroys the given object, only if it exists inside the Tome. Destroying it will remove it from the Tome as well.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)

newTome:DestroyObject(part) --> destroys the part

Tome:DestroyTuple

Arguments

  1. Tuple: ...any — Any amount of objects to destroy.

Destroys the given object(s), only if they exist inside the Tome. Destroying them will remove them from the Tome as well.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local part: BasePart, part2: BasePart = newTome:AddTuple(workspace.Part, workspace.Part2)

newTome:DestroyTuple(part, part2) --> destroys "part" and "part2"

Tome:DestroyObjectsWithTag

Arguments

  1. tag: string — The tag to use when querying Tome.

Destroys all objects with the given tag. This only works for Instances and the objects must be inside the Tome to be destroyed.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:AddTuple(workspace.Part)
part:AddTag("Test")

newTome:DestroyObjectsWithTag("Test") --> destroys "part"

Tome:DestroyObjectsOfType

Arguments

  1. typeName: string — The type of object(s) to destroy.

Destroys all objects that match the provided type. During querying Tome will search for the following in these types of objects

Instance: Instance:IsA(type)
table: table.__type == type

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)

newTome:DestroyObjectsOfType("BasePart") --> destroys "part"
1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)
local signal: Signal.Signal = newTome:Signal()

newTome:DestroyObjectsOfType("Signal") --> destroys only "signal"

Tome:Contains

Arguments

  1. object: any — The object to check.

Returns

  1. exists: boolean — Whether the object exists.

Returns whether the provided object exists inside the Tome

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)

print(newTome:Contains(part)) --> true
1
2
3
local newTome: Tome.Tome = Tome.new()

print(newTome:Contains(workspace.Part2)) --> false

Tome:Has

Arguments

  1. object: any — The object to check.

Returns

  1. exists: boolean — Whether the object exists.

The exact same as Tome:Contains.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)

print(newTome:Has(part)) --> true
1
2
3
local newTome: Tome.Tome = Tome.new()

print(newTome:Has(workspace.Part2)) --> false

Tome:FromExisting

Arguments

  1. instance: Instance — The object to Instance against.
  2. destroyMethod: DestroyMethod? — An optional override for the destroy method to use.

Returns

  1. object: Instance — The instantiated instance created from the 1st argument.

Creates an Instance from an existing one. See Instance.fromExisting for more information.

If the Instance is created successfully, the Instance will be added into the Tome.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:FromExisting(workspace.Part) -- creates a clone
part.Parent = workspace

newTome:Destroy()

Tome:GetObjects

Returns

  1. objects: {[any]: DestroyMethod} — The objects.

Returns the internal dictionary Tome uses to store objects. This table shouldn't be mutated freely, but if you know what you're doing, feel free.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)

print(newTome:GetObjects()) --> {[Instance(Part,FFFFF)] = "Destroy"}
1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local objects: {[any]: Tome.DestroyMethod} = newTome:GetObjects()

objects[workspace.Part] = "Destroy"

Tome:GetObjectsWithTag

Arguments

  1. tag: string — The tag to use.

Returns

  1. objects: {any} — The tagged objects.

Returns objects that have the provided tag. Only works for Instances

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)
part:AddTag("Test")

print(newTome:GetObjectsWithTag("Test")) --> {Instance(Part, FFFFF)}

Tome:GetObjectsOfType

Arguments

  1. objectType: string — The object type to query with.

Returns

  1. objects: {any} — The objects that match the type provided.

Returns objects that have the provided type.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)
part:AddTag("Test")

print(newTome:GetObjectsOfType("BasePart")) --> {Instance(Part, FFFFF)}
1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:Add(function()

end)

print(newTome:GetObjectsOfType("function")) --> {Function(FFFFF)}

Tome:GetPage

Arguments

  1. name: string — The name of the Page to get.

Returns

  1. page: Tome? — The Page that was fetched.

Returns a Page within the Tome from a given name. If the Page with the name doesn't exist, then nil is returned.

local newTome: Tome.Tome = Tome.new()

-- pretend we lose access to our Page "Test" due to being inside a deep scope
do
    newTome:AddPage("Test")
end

-- now we can fetch it

local myPage: Tome.Tome? = newTome:GetPage("Test")

print(myPage) --> Tome(Page("Test"))
1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local myPage: Tome.Tome? = newTome:GetPage("Test")

print(myPage) --> nil, because we never created a Page

Tome:GetParent

Returns

  1. parent: Tome? — The parent of the Tome.

Returns the parent Tome of the Tome that had this method invoked from. A Tome that has a parent is also referred to as a 'Page'.

If a parent doesn't exist, nil is returned.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local myPage: Tome.Tome = newTome:AddPage("Test")

print(myPage:GetParent()) --> Tome (newTome)
1
2
3
local newTome: Tome.Tome = Tome.new()

print(newTome:GetParent()) --> nil, because this Tome doesn't have a parent

Tome:GetTag

Returns

  1. tag: string? — The tag Tome uses for Tagging.

Returns the tag the Tome uses for tracking Instances when Tagging is enabled. If Tome:SetTag was not called to alter the tag, then a standard GUID is usually returned.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new({
    Tagging = true,
})

print(myPage:GetTag()) --> "9d2a0ed3-21db-43aa-8d47-3e06614ef6ae"
1
2
3
local newTome: Tome.Tome = Tome.new() -- create without Tagging enabled

print(myPage:GetTag()) --> nil, because tagging is disabled

Tome:GivePage

Arguments

  1. pageName: string — The name of the Page to give.
  2. newParent: Tome — The new parent of the Page.

Gives a Page from the Tome that was invoked, to another Tome. If the Page doesn't exist, nothing will happen.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()
local newTome2: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage("Test")

newTome:GivePage("Test", newTome2)

Tome:HookRunServiceSignal

Arguments

  1. signalName: RunServiceSignalName — The name of the Signal to hook to.
  2. listener: (deltaTime: number) -> () | (time: number, deltaTime: number) -> () — The listener function to call every step.

Returns

  1. connection: RBXScriptConnection — The connection between the Signal and listener.

Hooks to a RunService Signal, which can be any one of the following:

"RenderStepped"
"Heartbeat"
"PostSimulation"
"PreAnimation"
"PreRender"
"PreSimulation"
"Stepped"

When the RBXScriptConnection is created, it will be added to the Tome; disconnecting it once the Tome is destroyed.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

-- hooks to the RunService.RenderStepped Signal
newTome:HookRunServiceSignal("RenderStepped", function(deltaTime: number)
    print(deltaTime)
end)
1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

newTome:HookRunServiceSignal("RenderStepped", function(deltaTime: number)
    print(deltaTime)
end)

task.wait(1)

newTome:Destroy() -- will :Disconnect the RBXScriptConnection made above
local newTome: Tome.Tome = Tome.new()

-- RunService.Stepped is different from the others, in the sense that it responds with 2 number arguments
newTome:HookRunServiceSignal("Stepped", function(timeElapsed: number, deltaTime: number)
    print(timeElapsed, deltaTime)
end)

task.wait(1)

newTome:Destroy() -- will :Disconnect the RBXScriptConnection made above

Tome:Instance

Arguments

  1. instanceName: string — The name of the Instance to create.
  2. properties: {[string]: any} — The dictionary of properties to apply to the Instance.
  3. destroyMethod: DestroyMethod? — Optional DestroyMethod to use instead of `#!luau "Destroy".

Returns

  1. instance: Instance — The created Instance.

Creates a new Instance from a given name. The Instance will automatically be added into the Tome.

Optionally you can provide properties to apply to the Instance before returning it.

Properties are applied within a safe call. This means if you incorrectly apply a property, the error will be supressed. To avoid this, ensure you create the Tome with the metaprop Warnings set to true.

Optionally you can also provide a custom destroy method.

DEV-TODO

Currently there's no guarantee that the property properties.Parent will be set after all the other properties. This is important because setting properties after parenting is slower than setting them during creation.

This will be changed in the near future.

1
2
3
4
5
6
7
8
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Instance("Part", {
    Position = Vector3.new(0, 2, 0),
})
part.Parent = workspace -- setting the Parent out here

newTome:DelayDestroy(2.0)

Tome:IsDestroying

Returns

  1. destroying: boolean — Whether the Tome is currently destroying.

Returns whether the Tome is currently being destroyed.

local newTome: Tome.Tome = Tome.new()

-- fake adding something into the Tome from another block of code
task.delay(1, function()
    print(newTome:IsDestroying()) --> true
end)

newTome:Add(function()
    task.wait(5) --> halts the Tome, keeping it in a destroying state
end)

newTome:Destroy()

Tome:Move

Arguments

  1. object: any — The object to move from the Tome.
  2. tome: Tome — The Tome to move the object into.

Returns

  1. object: object — The object object passed in.

Moves the provided object into another Tome. Removing it from the Tome that this method was called from as well.

During the move, the object will keep the exact same destroy method inside the new Tome.

local newTome: Tome.Tome = Tome.new()

newTome:Add(workspace.Part)

local newTome2: Tome.Tome = Tome.new()

newTome:Move(workspace.Part, newTome2)

print(newTome:Contains(workspace.Part)) --> false
print(newTome2:Contains(workspace.Part)) --> true

Tome:Parent

Arguments

  1. tome: Tome — The new parent to live under.

Returns

  1. tome: Tome — Returns the Tome this method was called from.

Parents the Tome to another Tome. If the Tome already has a parent, then it will unparent from it first.

If the Tome doesn't have a name, the Tome will not be parented. To name a Tome you can do the following:

local newTome: Tome.Tome = Tome.new()
newTome:Rename("Drink water")

All Tomes that are created with Tome:AddPage, Tome:extend, Tome:Extend will come with a standard GUID name.

1
2
3
4
local newTome: Tome.Tome = Tome.new()

local newTome2: Tome.Tome = Tome.new()
newTome2:Parent(newTome) --> parents 'newTome2' under 'newTome'

Tome:Remove

Arguments

  1. object: any — The object to remove from the Tome.

Returns

  1. object: object — The same object that was passed in.

Safely removes the provided object from the Tome, if it exists inside it. Removing an object does not destroy it.

If the Tome has Tagging enabled and the object is an Instance, the object will have the Tome's tag removed as well.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)

print(newTome:Contains(workspace.Part)) --> true

newTome:Remove(part)

print(newTome:Contains(workspace.Part)) --> false

Tome:RemoveTuple

Arguments

  1. Tuple: ...any — The objects to remove from the Tome.

Returns

  1. Tuple: ...object — The same objects that were passed in.

The same as Tome:Remove with the one change of being able to provide a tuple of objects, instead of just one.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)
local part2: BasePart = newTome:Add(workspace.Part2)

newTome:RemoveTuple(part, part2)

Tome:RemoveFromArray

Arguments

  1. arrayOfObjects: {any} — The objects to remove from the Tome.

Returns

  1. arrayOfObjects: {any} — The same objects that were passed in.

The same as Tome:Remove with the one change of being able to provide an array of objects, instead of just one.

1
2
3
4
5
6
7
8
local newTome: Tome.Tome = Tome.new()

local array: {BasePart} = {
    newTome:Add(workspace.Part),
    newTome:Add(workspace.Part2),
}

newTome:RemoveArray(array)

Tome:RemoveObjectsWithTag

Arguments

  1. tag: string — The tag to use for getting the objects to remove.

Removes all objects from the Tome that have the specified tag. This only works for Instances.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)
part:AddTag("IShouldBeRemoved")

newTome:RemoveObjectsWithTag("IShouldBeRemoved")

Tome:RemoveObjectsOfType

Arguments

  1. type: string — The type to use for getting the objects to remove.

Removes all objects from the Tome that are of the specified type.

1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

local part: BasePart = newTome:Add(workspace.Part)

newTome:RemoveObjectsOfType("BasePart")
1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:Add(function()

end)

newTome:RemoveObjectsOfType("function")
1
2
3
4
5
local newTome: Tome.Tome = Tome.new()

newTome:Add(Tome.new())

newTome:RemoveObjectsOfType("Tome")

Tome:Rename

Arguments

  1. name: string — The new name for the Tome.

Renames the Tome internally. This is usually used for debugging. But can be used for other purposes too.

1
2
3
4
local newTome: Tome.Tome = Tome.new()
newTome:Rename("Test")

print(newTome:GetName()) --> "Test"

Tome:GetName

Returns

  1. name: string? — The name of the Tome.

Returns the name of the Tome. If the Tome doesn't have a name, nil is returned.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage("Test")
newPage:Rename("Test")

print(newPage:GetName()) --> "Test"

Tome:RipPage

Arguments

  1. nameOrPage: string | Tome — The name of a Page/Tome or the Page/Tome itself.

Returns

  1. tome: Tome — The Tome itself (for chaining purposes)

Removes the Page from the Tome permanently. Destroying itself before being removed.

If a Page doesn't exist, an error will be thrown. To avoid this, you can call Tome:GetPage before attempting to remove a Page.

1
2
3
4
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage()
newTome:RipPage(newPage) --> destroys, and removes the newPage from newTome
1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage("Test")
local newPage2: Tome.Tome = newTome:AddPage("Test2")

newTome:RipPage(newPage):RipPage(newPage2)

Tome:RipPages

Destroys all Pages inside the Tome, and removes them.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local newPage: Tome.Tome = newTome:AddPage()
local newPage2: Tome.Tome = newTome:AddPage()

newTome:RipPages()

Tome:SetTag

Arguments

  1. tag: string — The new tag to apply.

Returns

  1. tome: Tome — The Tome itself (for chaining purposes)

Sets a new tag for the Tome. This will remove the previous tag, which means all other objects that were tagged, will have their tag replaced with the new one. This will have to add and remove the tags for instances, which can be slow when used frequently, in mass.

This is mainly used for debugging, or very case-specific situations with Tagging.

local newTome: Tome.Tome = Tome.new({
    Tagging = true,
})
newTome:SetTag("Test")

local part: BasePart = newTome:Add(workspace.Part)
print(part:HasTag("Test")) --> true

newTome:SetTag("Test2")

print(part:HasTag("Test")) --> false
print(part:HasTag("Test2")) --> true

Tome:Signal

Returns

  1. signal: Signal — The created Signal

Creates a standard Signal implementation, and adds it to the Tome. This is from earlier versions of Tome.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

local signal: Tome.Signal = newTome:Signal()

signal:Connect(function(argument: string)
    print(argument)
end)

signal:Fire("Hello, world!") --> "Hello, world!"

Tome:UnbindRenderStepped

Arguments

  1. name: string — The name of the binding.

Manually unbinds the render step RunService binding.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

newTome:BindRenderStepped("Test", 201, function(deltaTime: number)
    print(deltaTime)
end)

task.wait(1)

newTome:UnbindRenderStepped("Test")

Tome:Tween

Arguments

  1. instance: Instance — The instance to tween.
  2. tweenInfo: TweenInfo — The tween info to use to mutate the instance.
  3. propertyTable: {[string]: any} — The properties to tween to.
  4. metadata: Metadata? — The metadata to mutate how to tween works.

Returns

  1. tween: Tween — The created tween.

Creates a Tween and adds it into the Tome. This method comes with some extra benefits, such as metadata:

Metadata changes how the tween works. See Tween Metadata for more information.

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:Tween(
    workspace.Part,
    TweenInfo.new(2),
    { Size = Vector3.new(2, 2, 2) }
):Play()

In this example, once the tween completes, the Tome gets destroyed. This is useful for creating timed events without creating new threads.

1
2
3
4
5
6
7
8
local newTome: Tome.Tome = Tome.new()

newTome:Tween(
    workspace.Part,
    TweenInfo.new(2),
    { Size = Vector3.new(2, 2, 2) },
    { Play = true }
).Completed:Once(newTome:WrapDestroy())

Tome:Table

Arguments

  1. table: {[any]: any}? — The table to use instead of creating a new one.

Returns

  1. table: table | {[any]: any} — The same table passed in, or the created table.

Adds (or creates) a table into the Tome. The table will have its destroy method as table.clear. Once the Tome gets destroyed, the table will clear itself.

This is useful in semi-round systems where you may track players within a sub-round, and need to clear them after the sub-round ends.

1
2
3
4
5
6
local newTome: Tome.Tome = Tome.new()

local parts: {BasePart} = newTome:Table({
    workspace.Part,
    workspace.Part2
})

Tome:OnDestroy

Arguments

  1. callback: (...any) -> () — The callback to add once the Tome destroys.
  2. onDestroyParams: OnDestroyParams — The params to mutate how the callback works.

Returns

  1. cleanUp: () -> () — A clean up function to remove the callback.

Adds a callback function into the Tome that listens for when the Tome gets destroyed. The callback will recieve the same arguments that were passed in Tome:Destroy. This can act as a sort of Signal.

Optionally you can provide OnDestroyParams that affect when and how the callback gets called.

Currently the supported parameters are: Synchronous: Will call the callback using task.spawn instead of directly calling it. This is useful if you know the callback will yield. Deferred: Will call the callback using task.defer. This takes priority over Synchronous, but Synchronous must be defined as true. RemoveOnDestroy: Will call the callback, and then remove it from the Tome. In cases like this, it's better to use Tome:Add which does the same thing, while being more inline with Tome.

By default, Synchronous is set to true. This is to prevent hard yielding. If for whatever reason you need the Tome callback thread to yield, you can manually set it to false.

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:OnDestroy(function()
    print("Hello, world!")
end)

newTome:Destroy() --> "Hello, world!"
1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:OnDestroy(function(myArgument: string)
    print(myArgument)
end)

newTome:Destroy("Hello, world!") --> "Hello, world!"

In this example, the callback will be deferred via !#luau task.defer.

1
2
3
4
5
6
7
8
9
local newTome: Tome.Tome = Tome.new()

newTome:OnDestroy(function(myArgument: string)
    print(myArgument)
end, {
    Deferred = true,
})

newTome:Destroy("Hello, world!") --> "Hello, world!" (a tiny bit later)

In this example, nothing happens because the callback was removed after it was called once. Hence the second time we call Tome:Destroy, nothing happens.

local newTome: Tome.Tome = Tome.new()

newTome:OnDestroy(function(myArgument: string)
    print(myArgument)
end, {
    RemoveOnDestroy = true,
})

newTome:Destroy("Hello, world!") --> "Hello, world!"
newTome:Destroy("Hello, world!") --> 

Tome:Yield

Arguments

  1. thread: thread? — The thread to yield.

Adds the provided thread into the Tome (or the current thread of a thread isn't provided) and uses coroutine.resume as the destroy method.

The current thread will then yield. Keep in mind, if the main thread is not resumed, you may encounter issues.

This will result in the thread resuming once the Tome is destroyed.

1
2
3
4
5
6
7
local newTome: Tome.Tome = Tome.new()

newTome:DelayDestroy(2.0)

newTome:Yield() -- stops the current thread

print("Hello, world!") -- prints after ~2 seconds