Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local RunService = game:GetService("RunService");
- local ReplicatedStorage = game:GetService("ReplicatedStorage");
- local Players = game:GetService("Players");
- local Remotes = ReplicatedStorage.Remotes;
- local StateRemote = Remotes.StateRemote;
- local Modules = ReplicatedStorage.Modules;
- local Utility = Modules.Utility;
- local TablesLibrary = require(Utility.TablesLibrary);
- local DefaultStates = require(script.DefaultStates);
- local FastSignal = require(Utility.FastSignal);
- local StateHandler = {};
- StateHandler.Characters = {};
- DEAD_CHARACTER_ERROR = "Character isn't alive";
- NOT_INITIALIZED_CHARACTER_ERROR = "Character isn't Initialized";
- ALREADY_INITIALIZED_CHARACTER_ERROR = "Character has already been Initialized";
- STATE_DOESNT_EXIST_ERROR = "State [%s] hasn't been found";
- TIMEOUT_WARNING = "[%s]'s state initialization await function has timed out!";
- --[[
- TODO: When calling a function, if character isn't initialized, make it await until Character has been initialized or it's been time out(10s)
- ]]
- --// PRIVATE
- local INIT_TIMEOUT = 10;
- local InitializationConnections = {};
- local function GetInternalState(CharacterIndex, stateIndex)
- end
- --// PUBLIC
- function StateHandler.Initialize(Character)
- assert(Character, DEAD_CHARACTER_ERROR);
- if StateHandler.Characters[Character] then
- warn(ALREADY_INITIALIZED_CHARACTER_ERROR)
- return;
- end
- StateHandler.Characters[Character] = TablesLibrary.DeepCopyTable(DefaultStates);
- local Data = StateHandler.Characters[Character];
- for StateName, StateData in pairs(Data) do
- Data[StateName].GetPropertyChangedSignal = function(PropertyName : string | nil)
- if Data[StateName].Connection then
- return Data[StateName].Connection;
- end
- Data[StateName].Connection = FastSignal.new();
- return Data[StateName].Connection;
- end
- end
- if InitializationConnections[Character] then
- InitializationConnections[Character]:Fire();
- end
- return Data;
- end
- function StateHandler:AwaitInitialization(CharacterIndex : model) : number
- if not StateHandler.Characters[CharacterIndex] then
- task.defer(function()
- task.wait(INIT_TIMEOUT);
- if not StateHandler.Characters[CharacterIndex] then
- warn( TIMEOUT_WARNING:format(CharacterIndex.Name) );
- end
- end)
- if InitializationConnections[CharacterIndex] then
- InitializationConnections[CharacterIndex]:Wait();
- else
- InitializationConnections[CharacterIndex] = FastSignal.new();
- InitializationConnections[CharacterIndex]:Wait();
- end
- end
- InitializationConnections[CharacterIndex] = nil;
- print("Initialized!");
- return 1;
- end
- function StateHandler:GetPropertyChangedSignal(CharacterIndex : Model, stateIndex : string | number | boolean, PropertyName : string | nil)
- assert(CharacterIndex, DEAD_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex], NOT_INITIALIZED_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex][stateIndex], STATE_DOESNT_EXIST_ERROR:format(stateIndex));
- return StateHandler.Characters[CharacterIndex][stateIndex].GetPropertyChangedSignal(PropertyName);
- end
- function StateHandler.Deinitialize(CharacterIndex)
- assert(CharacterIndex, DEAD_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex], NOT_INITIALIZED_CHARACTER_ERROR);
- StateHandler.Characters[CharacterIndex] = nil;
- end
- function StateHandler:GetData(CharacterIndex, stateIndex)
- assert(CharacterIndex, DEAD_CHARACTER_ERROR);
- if not StateHandler.Characters[CharacterIndex] then
- StateHandler:Initialize(CharacterIndex);
- end
- assert(StateHandler.Characters[CharacterIndex][stateIndex], STATE_DOESNT_EXIST_ERROR:format(stateIndex));
- if StateHandler.Characters[CharacterIndex][stateIndex].Duration then
- end
- return StateHandler.Characters[CharacterIndex][stateIndex].Value;
- end
- function StateHandler:ReturnState(CharacterIndex, stateIndex)
- assert(CharacterIndex, DEAD_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex], NOT_INITIALIZED_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex][stateIndex], STATE_DOESNT_EXIST_ERROR:format(stateIndex));
- return StateHandler.Characters[CharacterIndex][stateIndex];
- end
- if RunService:IsClient() then
- function StateHandler:UpdateState(CharacterIndex, stateIndex, stateValue)
- assert(CharacterIndex, DEAD_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex], NOT_INITIALIZED_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex][stateIndex], STATE_DOESNT_EXIST_ERROR:format(stateIndex));
- if StateHandler.Characters[CharacterIndex][stateIndex].Value == stateValue then return; end
- StateHandler.Characters[CharacterIndex][stateIndex].Value = stateValue;
- if StateHandler.Characters[CharacterIndex][stateIndex].Connection then
- coroutine.wrap(function()
- StateHandler.Characters[CharacterIndex][stateIndex].Connection:Fire(stateValue);
- end)();
- end
- return stateValue;
- end
- return StateHandler;
- elseif RunService:IsServer() then
- function StateHandler:UpdateState(CharacterIndex, stateIndex, stateValue, Duration, Priority)
- assert(CharacterIndex, DEAD_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex], NOT_INITIALIZED_CHARACTER_ERROR);
- assert(StateHandler.Characters[CharacterIndex][stateIndex], STATE_DOESNT_EXIST_ERROR:format(stateIndex));
- if StateHandler.Characters[CharacterIndex][stateIndex].Value == stateValue then return; end
- local oldStateValue = StateHandler.Characters[CharacterIndex][stateIndex].Value;
- StateHandler.Characters[CharacterIndex][stateIndex].Value = stateValue;
- if Duration and StateHandler.Characters[CharacterIndex][stateIndex].Duration then
- if (StateHandler.Characters[CharacterIndex][stateIndex].Priority > Priority and
- StateHandler.Characters[CharacterIndex][stateIndex].StartTime + StateHandler.Characters[CharacterIndex][stateIndex].Duration < os.clock())
- then
- return;
- end
- local StartTime = os.clock();
- StateHandler.Characters[CharacterIndex][stateIndex].Priority = Priority;
- StateHandler.Characters[CharacterIndex][stateIndex].Duration = Duration;
- StateHandler.Characters[CharacterIndex][stateIndex].StartTime = StartTime;
- task.delay(Duration, function()
- if (StateHandler.Characters[CharacterIndex][stateIndex].StartTime == StartTime and StateHandler.Characters[CharacterIndex][stateIndex].Priority == Priority)
- or StateHandler.Characters[CharacterIndex][stateIndex].Priority < Priority then
- StateHandler.Characters[CharacterIndex][stateIndex].Value = oldStateValue;
- end
- end)
- end
- if StateHandler.Characters[CharacterIndex][stateIndex].Connection then
- coroutine.wrap(function()
- StateHandler.Characters[CharacterIndex][stateIndex].Connection:Fire(stateValue);
- end)();
- end
- local Player = Players:GetPlayerFromCharacter(CharacterIndex);
- if Player then
- StateRemote:FireClient(Player, stateIndex, stateValue);
- end
- return stateValue;
- end
- return StateHandler;
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement