11using CommandSystem ;
22using JetBrains . Annotations ;
33using LabApi . Features . Permissions ;
4+ using LabApi . Features . Wrappers ;
45using RemoteAdmin ;
56using SER . Code . Helpers . Exceptions ;
67using SER . Code . Helpers . Extensions ;
78using SER . Code . Helpers . ResultSystem ;
89using SER . Code . ScriptSystem ;
910using SER . Code . ScriptSystem . Structures ;
1011using SER . Code . TokenSystem ;
12+ using SER . Code . TokenSystem . Tokens ;
1113using SER . Code . ValueSystem ;
1214using SER . Code . VariableSystem . Bases ;
1315using SER . Code . VariableSystem . Variables ;
@@ -81,6 +83,12 @@ public class CustomCommandFlag : Flag
8183 "You can provide multiple ranks, and if the player has any of the listed ranks, they will be able to use the command." ,
8284 AddNeededRank ,
8385 false
86+ ) ,
87+ new (
88+ "cooldown" ,
89+ "The time the player has to wait before being able to use the command again." ,
90+ AddCooldown ,
91+ false
8492 )
8593 ] ;
8694
@@ -169,6 +177,8 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s
169177 public ConsoleType ConsoleTypes { get ; set ; } = ConsoleType . Server ;
170178 public string [ ] Usage { get ; set ; } = [ ] ;
171179 public string [ ] NeededRanks { get ; set ; } = [ ] ;
180+ public TimeSpan PlayerCooldown { get ; set ; } = TimeSpan . Zero ;
181+ public Dictionary < Player , DateTime > NextEligableDateForPlayer { get ; } = [ ] ;
172182 public string GetHelp ( ArraySegment < string > arguments )
173183 {
174184 return $ "Description: { Description } \n " +
@@ -180,18 +190,14 @@ public string GetHelp(ArraySegment<string> arguments)
180190
181191 public CustomCommand Command = null ! ;
182192
183- public static Result RunAttachedScript ( CustomCommand requestingCommand , ScriptExecutor sender , string [ ] args )
193+ public static Result RunAttachedScript ( CustomCommand cmd , ScriptExecutor sender , string [ ] args )
184194 {
185- if ( requestingCommand . NeededRanks . Any ( ) && sender is IPlayerExecutor { Player : { } player } )
195+ if ( sender is IPlayerExecutor { Player : { } player } && HandlePlayer ( cmd , player ) is { } plrErr )
186196 {
187- if ( player . UserGroup is not { } group || requestingCommand . NeededRanks . All ( rank => group . Name != rank ) )
188- {
189- return "This command is reserved for players with a rank: " +
190- $ "{ requestingCommand . NeededRanks . JoinStrings ( ", " ) } ";
191- }
197+ return plrErr ;
192198 }
193199
194- if ( ! ScriptCommands . TryGetValue ( requestingCommand , out var flag ) )
200+ if ( ! ScriptCommands . TryGetValue ( cmd , out var flag ) )
195201 {
196202 return "The script that was supposed to handle this command was not found." ;
197203 }
@@ -203,16 +209,16 @@ public static Result RunAttachedScript(CustomCommand requestingCommand, ScriptEx
203209 }
204210
205211 var slices = outSlices . ToArray ( ) ;
206- if ( slices . Length < requestingCommand . Usage . Length )
212+ if ( slices . Length < cmd . Usage . Length )
207213 {
208214 return "Not enough arguments. " +
209- $ "Expected { requestingCommand . Usage . Length } but got { slices . Length } .";
215+ $ "Expected { cmd . Usage . Length } but got { slices . Length } .";
210216 }
211217
212- if ( slices . Length > requestingCommand . Usage . Length )
218+ if ( slices . Length > cmd . Usage . Length )
213219 {
214220 return "Too many arguments. " +
215- $ "Expected { requestingCommand . Usage . Length } but got { slices . Length } .";
221+ $ "Expected { cmd . Usage . Length } but got { slices . Length } .";
216222 }
217223
218224 if ( Script . CreateByScriptName ( flag . ScriptName , sender )
@@ -221,10 +227,10 @@ public static Result RunAttachedScript(CustomCommand requestingCommand, ScriptEx
221227 return error ;
222228 }
223229
224- for ( var index = 0 ; index < requestingCommand . Usage . Length ; index ++ )
230+ for ( var index = 0 ; index < cmd . Usage . Length ; index ++ )
225231 {
226232 var slice = slices [ index ] ;
227- var argVariable = requestingCommand . Usage [ index ] ;
233+ var argVariable = cmd . Usage [ index ] ;
228234 var name = argVariable [ 0 ] . ToString ( ) . ToLower ( ) + argVariable [ 1 ..] ;
229235
230236 if ( Tokenizer . GetTokenFromSlice ( slice , null ! , 0 )
@@ -243,6 +249,30 @@ public static Result RunAttachedScript(CustomCommand requestingCommand, ScriptEx
243249 script . Run ( RunContext . Command ) ;
244250 return true ;
245251 }
252+
253+ private static string ? HandlePlayer ( CustomCommand cmd , Player plr )
254+ {
255+ var hasRank = plr . UserGroup is not { } group || cmd . NeededRanks . All ( rank => group . Name != rank ) ;
256+ if ( cmd . NeededRanks . Any ( ) && hasRank )
257+ {
258+ return "This command is reserved for players with a rank: " +
259+ $ "{ cmd . NeededRanks . JoinStrings ( ", " ) } ";
260+ }
261+
262+ if ( cmd . PlayerCooldown <= TimeSpan . Zero )
263+ {
264+ return null ;
265+ }
266+
267+ if ( cmd . NextEligableDateForPlayer . TryGetValue ( plr , out var nextEligableDate ) && nextEligableDate < DateTime . UtcNow )
268+ {
269+ return $ "You are on cooldown! You can use this command in " +
270+ $ "{ ( nextEligableDate - DateTime . UtcNow ) . Seconds } seconds.";
271+ }
272+
273+ cmd . NextEligableDateForPlayer [ plr ] = DateTime . UtcNow + cmd . PlayerCooldown ;
274+ return null ;
275+ }
246276
247277 private Result AddArguments ( string [ ] args )
248278 {
@@ -288,4 +318,23 @@ private Result AddNeededRank(string[] args)
288318 Command . NeededRanks = args ;
289319 return true ;
290320 }
321+
322+ private Result AddCooldown ( string [ ] args )
323+ {
324+ switch ( args . Length )
325+ {
326+ case < 1 : return "Cooldown requires a duration value." ;
327+ case > 2 : return $ "Cooldown expects only a single duration value, got given { args . Length } instead.";
328+ }
329+
330+ var rawValue = args [ 0 ] ;
331+ if ( Tokenizer . GetTokenFromString ( rawValue , null , null ) . HasErrored ( out _ , out var token )
332+ || token is not DurationToken durationToken )
333+ {
334+ return $ "Value '{ rawValue } ' is not a valid duration.";
335+ }
336+
337+ Command . PlayerCooldown = durationToken . Value ;
338+ return true ;
339+ }
291340}
0 commit comments