Forest Logo
search
package_2

jinx

By @itzmrratsp

Roblox

Mirrored

Jinx

A lightweight and flexible StateMachine library for Roblox Luau.

Jinx is a StateMachine framework created for Roblox development. It provides a clean and structured way to organize behaviors by separating logic into independent states.

Instead of managing complex behavior through large conditional statements, Jinx allows developers to create reusable states with their own lifecycle, validation, and update logic.

Jinx supports:

  • State modules
  • Direct state tables
  • State lifecycle callbacks
  • State validation
  • Shared state data through Blackboard
  • State change signals

Features

  • โšก Lightweight StateMachine implementation
  • ๐Ÿงฉ Modular state architecture
  • ๐Ÿ“ฆ Supports ModuleScript states
  • ๐Ÿ”„ State enter, update, and exit lifecycle
  • โœ… State transition validation
  • ๐Ÿง  Built-in Blackboard system
  • ๐Ÿ“ก State change signals
  • ๐Ÿ”’ Strict Luau type support
  • ๐Ÿ”ค Case-insensitive state names
  • โž• Dynamic state registration
  • โž– Dynamic state removal

Installation

Require Jinx:

local Jinx = require(path.To.Jinx)

Create a StateMachine:

local Machine = Jinx()

Creating States

Jinx supports two ways of creating states:

  1. State tables
  2. ModuleScripts

State Tables

A state can be created as a normal Luau table.

local Idle = {
	enter = function()
		print("Entered Idle")
	end,

	update = function(dt)
		print("Updating Idle:", dt)
	end,

	exit = function()
		print("Exited Idle")
	end,
}

ModuleScript States

States can also be stored inside ModuleScripts.

Example:

States
โ”œโ”€โ”€ Idle
โ”œโ”€โ”€ Running
โ””โ”€โ”€ Jumping

Idle ModuleScript:

return {
	enter = function()
		print("Idle started")
	end,

	update = function(dt)
		print("Idle:", dt)
	end,

	exit = function()
		print("Idle ended")
	end,
}

Then pass them when creating the StateMachine:

local Machine = Jinx({
	Idle = States.Idle,
	Running = States.Running,
})

Jinx automatically detects ModuleScripts and requires them internally.


Creating a StateMachine

The constructor accepts an optional state dictionary.

local Machine = Jinx({
	Idle = IdleState,
	Running = RunningState,
})

States are automatically registered during creation.


Constructor

Jinx(
	states?: {[any]: State | ModuleScript},
	enterExactState?: boolean,
	silence?: boolean
)

states

A table containing the initial states.

Supports:

{
	StateName = StateTable
}

or:

{
	StateName = ModuleScript
}

Example:

local Machine = Jinx({
	Idle = IdleState,
	Running = RunningState,
})

enterExactState

Allows entering the same state multiple times.

Default:

false

Example:

Machine:switch("Idle")
Machine:switch("Idle")

With enterExactState enabled, both transitions will execute.


silence

Disables internal Jinx logging.

Default:

false

Example:

local Machine = Jinx(nil, false, true)

State Lifecycle

Each state can define these callbacks:


enter()

Called when the state becomes active.

enter = function(...)
	print("State entered")
end

update()

Called every update cycle.

update = function(dt)
	print(dt)
end

You must update the StateMachine manually.

Example:

RunService.Heartbeat:Connect(function(dt)
	Machine:update(dt)
end)

exit()

Called when leaving a state.

exit = function(...)
	print("State exited")
end

canEnter()

Determines if the state is allowed to start.

canEnter = function(...)
	return true
end

Returning false prevents entering.


canExit()

Determines if the state is allowed to stop.

canExit = function(...)
	return true
end

Returning false prevents leaving.


Complete Example

local Jinx = require(path.To.Jinx)
local RunService = game:GetService("RunService")


local Machine = Jinx({
	Idle = {
		enter = function()
			print("Idle")
		end,

		update = function(dt)
			print("Idle update", dt)
		end,

		exit = function()
			print("Leaving idle")
		end,
	},

	Running = {
		enter = function()
			print("Running")
		end,

		update = function(dt)
			print("Running update", dt)
		end,
	},
})


Machine:switch("Idle")


RunService.Heartbeat:Connect(function(dt)
	Machine:update(dt)
end)

Blackboard

Every StateMachine has its own Blackboard instance.

The Blackboard can be used to store shared data between states.

Example:

Machine.blackboard:Set("Speed", 20)

Another state:

local speed = Machine.blackboard:Get("Speed")

This allows states to communicate without directly depending on each other.


State Change Signal

Jinx provides a changed signal.

Machine.changed:Connect(function(stateName)
	print("Changed to:", stateName)
end)

Example output:

Changed to: running

Adding States

States can be added after creation.

Machine:add("Jumping", JumpState)

Removing States

States can be removed dynamically.

Machine:remove("Jumping")

If the state is currently active, Jinx will attempt to exit it before removal.


API Reference

Jinx()

Creates a new StateMachine.

Jinx(
	states?,
	enterExactState?,
	silence?
)

Returns:

StateMachine

StateMachine:add()

Adds a state.

Machine:add(
	name,
	state
)

StateMachine:switch()

Changes the active state.

Machine:switch(
	name,
	...
)

StateMachine:update()

Updates the active state.

Machine:update(dt)

StateMachine:remove()

Removes a state.

Machine:remove(name)

StateMachine:exit()

Attempts to exit the current state.

Machine:exit(...)

Recommended Usage

Jinx works well for:

  • Character controllers
  • NPC AI
  • Enemy behavior
  • Animation controllers
  • Weapon systems
  • Ability systems
  • UI navigation
  • Game progression systems

Example:

CharacterController

โ”œโ”€โ”€ Idle
โ”œโ”€โ”€ Walking
โ”œโ”€โ”€ Running
โ”œโ”€โ”€ Jumping
โ””โ”€โ”€ Falling

Each state manages only its own behavior, making systems easier to maintain.


Design Philosophy

Jinx follows one simple rule:

A state should only manage its own behavior.

Instead of:

if state == "Idle" then
	-- idle logic
elseif state == "Running" then
	-- running logic
end

Jinx separates behavior:

Idle.update()

Running.update()

This keeps code cleaner, more scalable, and easier to debug.


Creator

Created by ItzMrRatsP

Jinx was created for educational purposes and private Roblox development.


License

Jinx is not currently licensed for public redistribution.

Sharing or modifying this package outside approved usage is not permitted.

Package Details

Install command (Click to copy)


Version

0.1.3

License

MIT

check_circle

Safe for commercial use

infoThe package archive does not include its license text; the license is declared in its manifest metadata.

Automated license review โ€” not legal advice.