An object to handle the execution of commands or the execution of subtasks (which then go onto execute commands)
Can work on server and client
Provides wrappers and utility, such as thread tracking, maids, agents, etc
Combined with TaskService on the server manage most-to-all modifiers
Overview
Tasks can be split up into three core components
task:begin() - this determines all modifiers, then runs them in order, call task:execute() for each operation. if no modifiers, simply call execute once. after running all modifiers, call task:end
task:execute - decides what jobs to run based upon its given properties (such as invoking a command, splitting the task into subtasks). try and pretermine this, e.g. task.splitsIntoSubtasks = true, for these subtasks then have task.parentTask
task:end - if any commands active commands calls revoke, if any active subtasks calls end, then cleansup everything via the maid
To-do
Initial upgrades
[x] Improve setting like task.command
[x] Setup task:track and make it work for tweens
[x] Do not update task (originally thisExecution) with command properties
[x] Ensure :invoke/revoke is called on commands instead of .invoke/revoke
[x] Introduce a task.splitIntoSubtasks bool property (based upon qualifiers, player, global, etc) that determines its job when executed
task:begin
[x] Ensure all action (non-pre-action) modifiers are ordered correctly
[x] Have given modifiers ordered
[x] complete spawn modifier and strongly consider having thread:disconnect()after the given function has executed (instead of before)
[x] also ensure the thread methods have to wait at least 1 heartbeat before finishing (although the initial function doesn't have to)
[x] Important: all modifiers atm act as standalone and don't consider each other. Ensure that modifiers work together when combined (e.g. delay and loop, epoch and delay, etc)
[x] Setup task:begin so it either executes through all present modifiers in order, or calls execute once if no modifiers present. If multiple executes, wait until the previous execute has ended (this is likely where promises come into play)
[x] It's important these utilise task:track and Thread so if the task is ended early then the modifiers also stop (OR DO THEY?! strongly think about not doing this or at least think about self.totalThreads)
[x] Complete all action modifiers
[x] Call task:end when finished
[x] Within task:end/destroy, if isa server task and not a perm task, then call taskservice.removetask
[x] Make sure to end all present threads
task:execute
[x] If splitIntoSubtasks == true then generate an array of players based upon the given qualifier(s), split into subtasks, set these subtasks taskParent to self, then call :begin() on them
task:end
[x] Provide alias .destroy and .Destroy
[x] should there be two separate maids, one for the task and one for executions?
[x] for commands like icefreeze, walkspeed, paint, neon, spin, title, clone etc, when should the task end, and how?? Maybe on death, maybe persist on respawn
[x] listen for player removing (if userid), and call task:kill if fired
[x] introduce a command.persistence enum
[x] none
[x] untilDeath - character.humanoid.died
[x] untilRespawn - targetplayer.characteradded, but also consider how this impacts other things. for instance, maybe add a heartbeat wait to the spawn modifier
[x] untilLeave - a task is automatically removed when a player leaves, so also ignore
[x] untilRevoke - simply ignore the task:kill at the end of begin
[x] what happens if command.persistence.untilDeath or untilRespawn and 'spawn' modifier applied?
task:filterTextArgs
[x] consider setting 'filterText' for args such as 'Text/String'
[x] within the task constructor, determine the original Arg module table from commandName, iterate over all args, then if argtable isa filter/text command, then filter the value on a player specific basis (maybe utilise thread/promise since it asynchronous)
[x] filter over all args and if needs filtering convert with the new ChatUtil methods
[x] once all items have been filtered set a property and call a signal
[x] within execute, if this property is false then wait for signal to fire before continuing
[x] with the things learned from chatutil, apply them to other promises such as that in banservice, timeservice (which should be converted to TimeUtil then tested)
Networking/ClientCommands
[x] task:invokeClient/nearbyClients/allClients - use the client commnd remote to achieve this, note down the sent clients, and (IF PERSISTENCE IS NONE, THEN 60 OTHERWISE 0), passing through the taskId and ...
[x] also consider passing through {details} instead of just taskid which contains 'killAfterExecition'
[x] When sending off to clients for clientcommand, invoke all clients and only end task when heard back from all, OR timeout exceeded, OR heard back from 90% or more and exceeded 3 seconds
[x] Consider tailoring the timeout variable for the average upper limits of responses for that patticular command (instead of 60)
[x] within task.kill make sure to cleanup the client (if client present and has not ended) on end
[x] -If not needed, remove main.services.CommandService.Client.new
[x] if task:pause/resume/kill called on server, also call if for all relavent clients
[x] now handle command invocation on the client (clientcontroller receiver, find client command, etc)
[x] now handle command revocations on the client (same as above, then kill corresponding task)
[x] now handle pause and resume on the client
[x] task:revokeClient/AllClients - revokes (i.e. ends and cleanups) all specified 'sent clients)
[x] if a client remote request is blocked (exceeded) then send a follow up warning to the client. do this for both invokeserver and fireserver (for invoke consider promises on the client) and setup a remote object on both client and server to send/receive these errors. then set a function from the modules.remote moduler
[x] introduce a param for serverremote 'datalimit' which blocks all requests past a certain size
[x] move remotes from CommandService to TaskService
[x] setup TargetPool enum
[x] for each enum item, have a function which returns the pool of players (have an option to pass through a list of narrowed players, which can be a dictionary or an array)
[x] complete each enum item
[x] for invokeNearbyClients replace with the nearby enum value
[x] task:replicateTo/ToNearby/ToAll/ToServer - set a limit of 12 requsts per second and 200 bytes, fire to server (which checks the client command has the .replicateEffect method and the player client matches the task.player, then records task.replicationsThisSecond) then fire to desired clients and call replicateEffect.
[x] Command.preReplication(task, ...) - if false returned then block - e.g. for lasereyes block more than 3 requests a second, if piano cap the max/min pitch and volume
[x] Have a setting which prevents the same command name being used on the same user until the previous has expired (first check command tristatesetting, if default, use settingservice value
[x] if revokerepeat true, remove all tasks of same commandname prior to creating (ensure user specific if user present)
[x] Complete the pre-action modifiers within CommandService
Final components
[x] CHECKOUT AND FIX ENUM (also remove the tostring requirement so thingy can work maybe)
[x] Consider changing task.caller to task.callerUser and introducing task.callerUserId (or just outright remove task.caller)
[x] Improve PlayerUtil so functions like 'getHumanoid' also take a userid which checks for getPlayerByUserId
[x] Setup events/signals for command/task/role added/removed/changed
[x] Consider replacing MessageService methods 'like hint, message, etc' 'All' with the target enum thingy
[x] Consider renaming batch (like from executeBatch) to statement
[x] Finish CommandService invokeCommand and revoke
[x] Important: Improve State tables
[x] Investigate State missing table bug mentioned by Raza (see pinned .txt in team discord)
[x] Instead of checking for .new, have a param to inherit descendant tables and set to off by default
[x] Update System handlers so they utilise this new param (they need it to be true, not nil)
[x] Complete Agent/Aurora/Buff
[x] Complete Clone
Test all of Task (including CommandService and TaskService)
[x] Test the initiation process of creating a task
[x] Buff values are not resetting correctly??
[x] Ensure tasks remain for their specified durations (thoroughly test Command.persistence)
[x] update new persistence enums and introduce new enum 'UntilCallerLeave'
[x] Test command.persistence for server commands
[x] Thoroughly test task behaviours (maid give for example)
[x] Test buffs on server
[x] Ensure client commands work at a basic level
[x] test leaving during a client command invoke
[x] Test client commands with different persistences
[x] Ensure the ... is passed correctly
[x] Consider introducing a task method along the lines of task:invokeFutureClients()
[x] ensure the preReplication method works correctly (and blocks accoridngly)
[x] a property or something to prevent clone standing on your head when it follows
[x] Test buffs on client (including the dynamic agents)
[x] a way to track objects given to the task then anchor/unanchor (if previously anchored) when the task is frozen/resumed
[x] introduce a task:tween method which abstracts task:give(TweenService:Create)
[x] Test pausing/resuming on server (this includes tweening, and a mix of player-specific and server commands)
[x] Test pausing/resuming on client
[x] Test pausing/resuming on client via server
[x] Create the following commands:
[x] Before doing this determine two things
[x] How to detect the player specified 'nil' for the playerArg - maybe a property within tasks?
[ ] Tasks must remember the the highest role of the player calling them. They can then only be paused/resumed/cleared by users of equal or higher roles. Consider a setting for this? (for juniors and equals)
[ ] Ensure sounds (aka music) are pausable and resumable (consider adding some methods to Sound object). Also ensure sounds gets tracked like instances when 'given' to maid
[ ] ;pause (playerArg) - ensure can only modify tasks of equal/lower role
[ ] ;resume (playerArg) - ensure can only modify tasks of equal/lower role
[ ] ;clear, refresh, re (playerArg) - ensure can only modify tasks of equal/lower role
[ ] ;clearServer, clearAll - ensure can only modify tasks of equal/lower role
[x] Test all server to client methods
[x] Test all replication methods
[x] ensure the invoke timeout works correctly
[x] ensure the replications work correctly
[ ] Test ;global where the command args are both 'player' and 'players' (see line 300 task for testing)
[ ] Test sub tasks
[x] ;kill (which does ;kill me)
[ ] ensure qualifiers 'users' and args 'players' utilise the getPlayerFromString method and perform correctly (ensure user qualifiers checking for correct displayname/username)
[ ] integrate and test razas parser
[ ] complete args
[ ] thoroughly test all args
[ ] thoroughly test all modifiers and the splitting of users within commandservice
[ ] test all qualifiers
Additional
[ ] Consider how the following will integrate with the Parser and contact raza
[ ] Command.opposites
[ ] Command.prefixes
[ ] Setup and test these
[ ] Command.opposites
[ ] Command.prefixes
[ ] modify command.cooldown so it prevents the caller from executing that command again for another 120 seconds. the cooldown begins as soon as the task finishes executing (or maybe as soon as called)? make sure the cooldown saves in case player swaps servers. also consider introducing a role setting which bypasses command cooldown
[ ] rename to callerCooldown
[ ] introduce serverCooldown which prevents anyone from executing that command again until cooldown expired.
Additional Buffs/Agent
[x] Accessories?
[ ] Face, shirts and pants, but they're libraryIds not catalogIds
[ ] A 'BuffEffects' extensions folder
Additional Role Stuff
[ ] setup a roleservice method RoleService.verifyCanUseModifiers(user, commandName, modifiersDict) for role setting roleModifiersToOnlyRoleCommands
[ ] this will likely involve verifySettings returning the role where the value is present, then if setting above is true, check against all returned roles and their commands, else if not some true, then just easy check.
Goals
Overview
Tasks can be split up into three core components
task:execute()
for each operation. if no modifiers, simply call execute once. after running all modifiers, calltask:end
To-do
Initial upgrades
task:begin
thread:disconnect()
after the given function has executed (instead of before)task:execute
taskParent
to self, then call :begin() on themtask:end
task:filterTextArgs
Networking/ClientCommands
task.kill
make sure to cleanup the client (if client present and has not ended) on endmain.services.CommandService.Client.new
invokeNearbyClients
replace with the nearby enum valueOther modules
Final components
.new
, have a param to inherit descendant tables and set to off by defaultTest all of Task (including CommandService and TaskService)
task:invokeFutureClients()
task:tween
method which abstractstask:give(TweenService:Create)
Additional
command.cooldown
so it prevents the caller from executing that command again for another 120 seconds. the cooldown begins as soon as the task finishes executing (or maybe as soon as called)? make sure the cooldown saves in case player swaps servers. also consider introducing a role setting which bypasses command cooldowncallerCooldown
serverCooldown
which prevents anyone from executing that command again until cooldown expired.Additional Buffs/Agent
Additional Role Stuff
RoleService.verifyCanUseModifiers(user, commandName, modifiersDict)
for role settingroleModifiersToOnlyRoleCommands
verifySettings
returning the role where the value is present, then if setting above is true, check against all returned roles and their commands, else if not some true, then just easy check.