Skip to content

Utilities Package

Sky edited this page Dec 24, 2021 · 2 revisions

This package provides various utility methods used throughout the system by both server and client packages.

Special Objects

Services

Utilities.Services is a metatable which acts as a stand-in for game:GetService(). It maintains it's own cache of known services, updated any time a new service is requested. Since this uses game:GetService() when initially retrieving a service, and then also caches the result, this method of service retrieval is not affected by changes to service names. When creating packages, this is the preferred way to obtain any Roblox services.

local service = Utilities.Services
local scriptService = service.ServerScriptService
local storage = service.ServerStorage
local players = service.Players

Events

Events are used heavily throughout the system. The 'Events' object in Utilities facilitates the connection and firing of these events. Events are created as they're connected, so calling :Connect() on a previous non-existent event will create it. Calling :Fire() will not create an event and will effectively do nothing if the event has not been connected elsewhere.

It's basic usage is as follows:

--// Connect to our event.
local connection = Utilities.Events.ExampleEvent:Connect(function(testData)
	print(testData) --> "This is a test fire"
end)

--// Fire our event (this can be triggered from anywhere in the system.)
Utilities.Events.ExampleEvent:Fire("This is a test fire")

--// Disconnect our event connection if we no longer need it.
--// If you no longer need an event, you should disconnect it when you're finished with it.
connection:Disconnect()


--// If for some reason you want to destroy an event, effectively breaking existing connections, you can do so using :Destroy().
--// The following will call :Destroy() on the underlying BindableEvent object and will remove the event from the known events table.
--// *Note: This event will be created again if it connected again. This will break all existing connections for this event.*
Utilities.Events.ExampleEvent:Destroy()

MemoryCache

A MemoryCache is a special object which facilitates easy data caching with definable expiration. A MemoryCache should be used any time you want to store data for a set amount of time.

MemoryCache Creation

local newCache = Utilities:MemoryCache({
	Cache = {}, --// The underlying table that will be used to store cache values, if this is not provided it will default to a new, empty, table. (Default: {})
	Timeout = 0, --// Default timeout value (in seconds) for data added to this cache. A value of 0 indicates an infinite timeout (as in, never.) (Default: 0)
	AccessResetsTimer = false, --// Whether or not accessing data should reset the timeout timer for that data. (Default: false)
})

--// Sets data within the cache. Third parameter is an optional table containing cache settings to use for this specific cache item.
--// Note: Calling SetData for a given key will always set the timer for that key.
newCache:SetData("DataKeyHere", "SomeDataHere", {
	Timeout = 60, --// Overrides the default timeout value for this specific item only
	AccessResetsTimer = true, --// Overrides the default AccessResetsTimer value for this specific item only
})

--// Retrieves data from the cache. 
--// If AccessResetsTimer is true, the timer for the desired key will be reset.
local cachedData = newCache:GetData("DataKeyHere")
print(cachedData) --> "SomeDataHere"

--// Forces a cache clean: Iterates through cached data and removes anything that has expired. 
--// Note: This happens automatically and generally should not be performed manually, unless you are caching large amounts of data and are concerned about memory leaks. This method is called every time SetData is called.
newCache:CleanCache()

Wrapping

Instance wrapping is occasionally within the system to expand the functionality of certain objects when we lack the ability to directly change said objects. For example, the Window GUI (in the DefaultUI package) uses wrapping to provide new methods and properties that allow additional functionality not provided by the base ScreenGui object, while still retaining all existing ScreenGui properties and methods.

local original = Instance.new("ScreenGui")
local wrapped = Utilities.Wrapping.Wrap(original)

--// Set name
original.Name = "SomeGui"

--// Set method that prints the underlying object's name
wrapped:SetSpecial("PrintName", function(self) print(self.__Object.Name) end)

--// Call :PrintName()
wrapped:PrintName() --> "SomeGui"

--// Check if object is a wrapped object
print(Utilities.Wrapping.IsWrapped(wrapped)) --> true

--// Get the original object without the wrapper (needed if you intend to use it with methods/properties that are expecting an Instance, otherwise an error will occur since the wrapper is not an actual instance)
local unwrapped = Utilities.Wrapping.UnWrap(wrapped)

--// Check if two objects are the same object, ignoring any wrapping
print(Utilities.Wrapping.RawEqual(original, wrapped)) --> true

Tasks

Provides various methods for tracking and controlling tasks and their execution. Currently not utilized in the current code-base and may be removed in a future update. Further documentation pending changes.

Basic Methods

Utilities:RandomString(Length: number, CharSet: string)

Returns a random string of length using characters provided in CharSet. If Length is not a provided, a default of 9 will be used. If CharSet is not provided, a default character set will be used consisting of numbers 0-9 and characters A-Z (no lowercase.)

EditInstance(Object: Instance, Properties: Table or Instance)

Updates information about the Instance Object using data provided within the Properties table. If Properties is an instance, it will be set as the object's parent.

local newPart = Instance.new("Part")
local partObj, connections = Utilities:EditInstance(newPart, {
	Parent = Utilities.Services.Workspace, --// If Parent is included, it will be set ***after*** all other properties to avoid unnecessary replication overhead.

	--// Basic part properties
	Name = "SomePart",
	BrickColor = BrickColor.new("Really red"),
	
	--// If a table named Children is provided, the instances within this table will be parented to the target instance.
	Children = {
		Instance.new("Fire"),
		Instance.new("Sparkles"),
	},

	--// If a table named Attributes is provided, all attributes defined within the table will be set on the object.
	Attributes = {
		SomeAttribute = "SomeValue"
	},

	--// If a table named Events is provided, the specified events will be connected to the specified functions and their signal connection objects will be returned as part of the connections table (the second value returned by EditInstance, after the instance object.)
	--// Note: Events are connected last, after *Parent* has been set (if provided.)
	Events = {
		Touched = function(p)
			print(p.Name .." touched our new part")
		end
	}

})

CreateInstance(ClassName: string, Properties: Table or Instance)

Acts as a shorthand to Utilities:EditInstance(Instance.new(ClassName), Properties)

IsServer()

Returns true if this is running on the server, otherwise false.

IsClient()

Returns true if this is running on the client, otherwise false.

GetTime()

Returns os.time()

GetFormattedTime(Time: number, WithDate: boolean)

Returns a formatted time string optionally with date. If Time is not supplied, the value returned by Utilities:GetTime() will be used.

FormatNumber(Number)

Given a number, returns a formatted string representation of that number.

print(Utilities:FormatNumber(100000)) --> "100,000"

FormatPlayer(Player, WithUserId: boolean)

Formats a Player's name as such: 'Username (@DisplayName)' or '@UserEqualsDisplayName' Optionally appends the player's UserId in square brackets.

FormatStringForRichText(string)

Sanitizes a string to be used with RichText.

AddRange(table1, table2, table3, table4, ...)

Given table1 and one or more subsequent tables, appends the content of all subsequent tables into table1 in order of appearance from left to right.

MergeTables(table1, table2, table3, table4, ...)

Given table1 and one or more subsequent tables, merges indexes of subsequent tables with their values into table1 such that table2.SomeIndex will overwrite table1.SomeIndex. Each next table will overwrite values set from previous tables in order of appearance from left to right.

CountTable(table)

Returns the number of elements in the provided table.

ReverseTable(table)

Given an ordered table, returns a new table containing the original table's value in reversed order.

Encrypt(string, Key: string, Cache: Optional Table)

Given a string and a key, returns a weakly encrypted version of the input string. Optionally supports caching to improve the speed of future encryption using the same input string and key. This is primarily used for basic trust checking within the system and minor data/key obscurity and should not be relied on to secure sensitive information. The encryption method used is intended to be fast, not secure.

Decrypt(string, Key: string, Cache: Optional Table)

Performs decryption on strings encrypted using Utilities:Encrypt().

Attempt(tries: number?, timeBeforeRetry: number?, func: (number)->any, errAction: (string)->any, sucessAction: (any)->any)

Advanced alternative to xpcall with multiple retry logic & post-success result processing.

MakeLoop(exeDelay: number?, func: (number)->(), dontStart: boolean?)

Creates a new coroutine-based loop with specified delay. Returns a function which can be called to start the loop.

Iterate(tab: {any}|Instance, func: (any, number)->any, deep: boolean?): any?

Iterates through a table or an Instance's children, passing value-key pairs to the callback function. Breaks if/when the callback returns, returning that value. If third argument is true, the iteration will include all the table's subtables/Instance's descendants.

RunFunction(Function, ...)

Runs the given function with the provided parameters. Performs an xpcall call on the supplied function and returns the result. Creates a warning if Function errors.

CheckProperty(obj: Instance, prop: string): (boolean, any)

Returns true along with the value of the requested property if the provided instance has it, otherwise returns false.

IsDestroyed(object: Instance)

Attempts to check if the provided instance has been destroyed, returning true if it was destroyed or otherwise false if not.

Only suitable for instances with a changeable Parent property.