Ban System/Custom Ban Command

and this to

if playerToBan and duration and reason then
  --code
end

it will check three thing without doing that huge if statement

6 Likes

How would I convert the duration variable to days in real time instead of UNIX time? I’m making a gui and having the time a player is banned for would be nice.

2 Likes

os.time() is in real time though, it uses UTC unlike tick() which is in unix

3 Likes

I meant something easily readable like

“You have been banned for 3 days” or something

2 Likes

Use math.abs to determine the remaining days between the start and the end.

2 Likes

I separated it so that it could print within SUccess and not success and result

2 Likes

There are plenty of time formatting modules that you can find in #resources:community-resources - just do some research by examining the source code etc. to figure out how to craft your own.

2 Likes

Your getting the players userid so you will use tonumber

2 Likes

Not actually, the player’s userid is already an int/number, and we’re converting it into a string because that’s what we’ll be using for the name, and what we’re searching for any key entry/data for the player upon joining.

3 Likes

I’m making a UI based off of this, by the way! I need to do a bit more polishing first.

There’s two things wrong with this that my UI fixes:

  1. You can’t unban a user without using “/ban name 0 a” and it’s pretty weird.
  2. You put the < sign the wrong way here

My UI also adds a warning message after your ban is over :smile:

3 Likes

Yeah it’s correct. It’s supposed to be < instead of >. Kind of put it in the wrong way with my half-awake self. I’ll be working on an unban soon.

3 Likes

Good tutorial. I had a admin system and I was trying to make a ban sytem and this tutorial made it easier and better. Thanks!

3 Likes

Glad to see I was actually able to help, awesome. (You’re welcome)

Feel free to PM me when you have any inquiries, questions about anything, and all that good stuff. I try to be as active as I can on the DevForums, and I’m looking forward to making some friends on it as well.

4 Likes

I’ve uploaded the gui on a seperate post!

7 Likes

I keep getting this weird error?

ServerScriptService.Script:63: invalid argument #2 to ‘sub’ (number expected, got nil)

2 Likes

What is the format for the command? I cant seem to get the command right

1 Like

You should change the # thing with 4.

/ban

1 Like

It’s good but the time wont work, if I do for example /ban 100 test it would say banned 00 test and nothing else, no time. so as a result it doesn’t actually ban people, just kicks them

I actually got the same error too and it was coming from this line:

local duration = string.sub(message, string.find(message, numbers));

Probably because the number in string.find() was nil.

Edit: When you tested it out, did you enter the length of the duration in your message or just the username itself?

1 Like

Nice tutorial, congratulations.

Just a quick comment/suggestion for anybody (with at least some scripting understanding; you may skip if not) reading this:

According to the Data Stores official documentation page, the Scopes feature is now a legacy feature and its use is no longer recommended.
According to this Data Stores article’s section, The new recommendation is to follow a more explicit approach to scoping by (in general terms) concatenating the actual scope to the DataStore key. This new approach enhances the use of DataStore:ListKeysAsync()'s first parameter which handles this new approach (and surely more methods yet to be introduced). Besides the fact that you may use multiple scopes with this new approach.
For instance:

Example 1 (simple scoping)

Scope: slot

New scoping:

local slot = "1"
local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")
local slotDataStoreKey = string.format("%s/slot_%s", userId, slot) -- "userId/slot_1"
-- I use the '/' separator for convenience, nevertheless it may be any character

Legacy scoping:

local slot = "1"
local playerInventoryDataStore = DataStoreService:GetDataStore("PlayerDataStore", slot)
local slotDataStoreKey = tostring(userId) -- "userId"

At this point (in this example), it doesn’t seem terribly different. That’s because simple scoping is supported for both, but the concept multiple scoping is more complex for the legacy format (check out Example 2).

Example 2 (multiple scopes)

Scopes: slot, gold
New scoping:

local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")
local slot = "1"
local goldDataStoreKey = string.format("%s/slot_%s/gold", userId, slot) -- "userId/slot_1/gold"

Legacy scoping:

Having more than 1 scope is practically impossible without making an extra call to DataStoreService:GetDataStore(), which isn’t desirable in any case because there would be more as minimum 2 separate DataStore calls for the same DataStore, which, in the long run, will overcomplicate everything.

As you may have noticed, a multi-scoped key follows the same format as a simple-scoped key. The new approach’s format is universal for every scope quantity! (Unlike the legacy approach).


I’m not saying that the use of the legacy scoping is “wrong”, nevertheless, the use of the new approach is encouraged because new methods may not support legacy approaches. But it’s up to you! You may use whichever approach you feel more comfortable with.

Hope this helps! :four_leaf_clover: Happy coding.

2 Likes