My state machine code is messy and doesn't have much functions to it

So I have been using this state machine for a while now, it functions just how I wants it to, but I find it to be a bit different from the other state machines I have seen around. The main point of my machine is to restrict doing an action if you haven’t met the criteria, it’s really simple but it works. I want to improve it by adding more functionalities / features but I don’t really know how and what to add. I have been in some situations that I had to resort to using a “hacky” way for the sake of my game.
Here’s my simple state machine

local FSM = {}

FSM.__index = FSM

local RepStorage = game:GetService("ReplicatedStorage")
local RemoteEvents = RepStorage:WaitForChild("RemoteEvents")

local all = {"idle", "sprint", "attack"}
local config = {
	init = "idle",
	states = {
	    ["sprint"] = {from = {"idle", "attack"}, to "sprint"},
        ["attack"] = {from = {"idle"}, to "attack"},
		["idle"] = {from = all, to = "idle"},
	},
}

local changedTable = {
	
}

local changedEvent = Instance.new("BindableEvent")

function FSM.Init()
	local self = setmetatable(config, FSM)
	
	self.currState = self.init
	
	local mt = setmetatable(FSM, {
		__index = function(tbl, key)
			return self[key]
		end,
		__newindex = function(tbl, key, val)
			changedEvent:Fire("onStateChanged", self.currState, val)
			self[key] = val				
			return self[key]
		end,
	})
	
	self.onStateChanged = {}
	
	local e
	
	function self.onStateChanged:Connect(callback)
		changedEvent.Event:Connect(function(eventName, oldState, newState)
			--print(oldState, newState)
			if eventName == "onStateChanged" then
				return callback(oldState, newState)
			end
		end)
	end

	return mt
end

function FSM:Transition(state)
	
	local suc = FSM:canTransition(state)
	
	if suc then
		self.currState = state
	end
	
	return suc
end

function FSM:canTransition(state)
	assert(typeof(state) == "string", "State must be a string")

	if not rawequal(self.currState, state) then
		local transition = {}

		for i, v in pairs((self.states[state])) do
			transition[i] = v
		end 	

		if typeof(transition.from) == "table" then
			if table.find(transition.from, self.currState) or transition.from["all"] then
				return true
			end
		end		
	end

	return false
end


function FSM:is(state)
	return rawequal(self.currState, state)
end

return FSM

Any help is appreciated

4 Likes