BetterLoops Module
Overview
The BetterLoops
module provides a way to manage and execute callbacks at regular intervals, with support for distance-based frame interval adjustments. Callbacks can be added with optional parameters to customize their behavior, and they can be removed using a unique identifier.
Functions
bindCallback(callback, player, target, framesInterval, minDistance, maxDistance, params)
Adds a callback to be executed periodically.
-
callback
:Function
- The function to be executed. -
player
:Instance
(optional) - APlayer
instance used for distance-based callback execution. -
target
:Instance
(optional) - ABasePart
instance representing the target for distance measurement. -
framesInterval
:Number
- The number of frames between callback executions (defaults to1
). -
minDistance
:Number
- The minimum distance for adjusting the frame interval (defaults to1
). -
maxDistance
:Number
(optional) - The maximum distance to limit frame interval adjustments. -
params
:Table
(optional) - Additional parameters to pass to the callback.
Returns: Number
- A unique identifier for the added callback.
unbindCallback(callbackId)
Removes a callback using its unique identifier.
-
callbackId
:Number
- The unique identifier of the callback to be removed.
Returns: Boolean
- true
if the callback was successfully removed, otherwise false
.
Example Usage
Adding a Callback
local BetterLoops = require(game.ServerScriptService.BetterLoops)
-- Define a callback function
local function myCallback(param1, param2)
print("Callback executed with params:", param1, param2)
end
-- Add the callback with parameters
local callbackId = BetterLoops.bindCallback(
myCallback,
game.Players.LocalPlayer, -- Player instance (optional for distance-based callback)
workspace.TargetPart, -- Target instance (optional for distance-based callback)
10, -- Frames interval
5, -- Minimum distance
50, -- Maximum distance
{ "Hello", "World" } -- Parameters to pass to the callback
)
Removing a Callback
-- Remove the callback using its unique identifier
local success = BetterLoops.unbindCallback(callbackId)
if success then
print("Callback successfully removed.")
else
print("Callback removal failed.")
end
The module
-- BetterLoops.lua
local RunService = game:GetService("RunService")
local BetterLoops = {}
local callbacks = {}
local nextId = 1
-- Adds a callback with configuration parameters and error handling
-- @param callback: Function to be executed
-- @param player: (Optional) Player instance for distance-based callback
-- @param target: (Optional) Target instance (BasePart) for distance-based callback
-- @param framesInterval: Number of frames between callback executions
-- @param minDistance: Minimum distance for distance-based frame interval adjustment
-- @param maxDistance: Maximum distance for distance-based frame interval adjustment
-- @param params: Additional parameters to be passed to the callback
-- @return: Unique identifier for the callback
function BetterLoops.bindCallback(callback, player, target, framesInterval, minDistance, maxDistance, params)
assert(type(callback) == "function", "The 'callback' parameter must be a function.")
local useDistance = player and target
local playerInstance = useDistance and player
local targetInstance = useDistance and target
if useDistance then
assert(typeof(playerInstance) == "Instance" and playerInstance:IsA("Player"), "The 'player' parameter must be an instance of type Player.")
assert(typeof(targetInstance) == "Instance" and targetInstance:IsA("BasePart"), "The 'target' parameter must be an instance of type BasePart.")
end
framesInterval = framesInterval or 1
assert(framesInterval > 0, "The 'framesInterval' parameter must be a positive value.")
minDistance = minDistance or 1
local callbackId = nextId
nextId = nextId + 1
local newCallback = {
id = callbackId,
callback = callback,
framesInterval = framesInterval,
currentFrame = 0,
useDistance = useDistance,
player = playerInstance,
target = targetInstance,
minDistance = minDistance,
maxDistance = maxDistance,
params = params or {} -- Stores additional parameters
}
table.insert(callbacks, newCallback)
return callbackId
end
-- Removes a callback by its unique identifier
-- @param callbackId: Unique identifier of the callback to be removed
-- @return: Boolean indicating if the callback was successfully removed
function BetterLoops.unbindCallback(callbackId)
for i = #callbacks, 1, -1 do
if callbacks[i].id == callbackId then
table.remove(callbacks, i)
return true
end
end
return false
end
-- Internal function optimized for executing callbacks
local function onRenderStep()
local numCallbacks = #callbacks
for i = 1, numCallbacks do
local data = callbacks[i]
if data.useDistance then
local character = data.player.Character
local primaryPart = character and character.PrimaryPart
local targetPosition = data.target and data.target.Position
if primaryPart and targetPosition then
local playerPosition = primaryPart.Position
local distance = (playerPosition - targetPosition).Magnitude
-- Update frame interval based on distance
data.framesInterval = math.max(math.floor(distance), data.minDistance)
-- Ensure maxDistance is valid and within range
if data.maxDistance and distance > data.maxDistance then
data.framesInterval = data.minDistance
end
end
end
data.currentFrame = data.currentFrame + 1
if data.currentFrame >= data.framesInterval then
local success, err = pcall(function()
data.callback(table.unpack(data.params)) -- Passes parameters to the callback
end)
if not success then
warn("Callback execution error: " .. tostring(err))
end
data.currentFrame = 0
end
end
end
-- Connect the RenderStepped event to the onRenderStep function
RunService.RenderStepped:Connect(onRenderStep)
return BetterLoops