Hi everyone! I have a relatively simple question, but I can’t figure it out. I have a ServerScript that adds a Boolean attribute once the player joins:
Works perfectly, I can see the attribute on the player afterwards. However, when I change the state of the Boolean (either through a script, or just ticking/unticking the attribute in Studio) my ServerScript doesn’t see the actual status of that. It holds on to the initial ‘false’ (or ‘true’ if I set it to that, I’ve tried). So when I do this in a ServerScript:
local pService = game:GetService("Players")
local playerList = pService:GetPlayers()
for _, foundPlayer in ipairs(playerList) do
print("Found a player named " .. foundPlayer.Name)
if foundPlayer:GetAttribute("afk") == nil then
print("I can't find the afk status")
end
if foundPlayer:GetAttribute("afk") == true then
print("The afk status is true")
end
if foundPlayer:GetAttribute("afk") == false then
print("The afk status is false")
end
end
(I know this script is not perfect, once it works I’ll rebuild it with elseifs etc, this is just for my clarity for now)
No matter what I try, I get the BoolValue that I initially set in the script. So if the value is ‘true’ when I create the attribute, it remains true no matter what. And the same for false. It appears to me like the ServerScript can’t see the real time value, if you know what I mean. Perhaps I’m looking at a wrong Playerlist or something?
However, a LocalScript does see the real time value, which I tried just to check. What am I doing wrong?
I looked through the Attribute manual, searched on here, but I can’t find the answer. I would be so thankful if you could help me. Sorry for the long post but I wanted to be a thorough as possible. I hope I made my problem clear.
I’m guessing the above code runs as soon as the game starts, and because this code doesn’t appear to be inside a loop or event, this code will only run once.
Since it runs only one time at the beginning of the game, it’s not going to be able to detect changes to the attribute that happen later on in the game.
If this script is inside a loop or event, then my second guess would be that there’s an issue with how you are changing the attribute’s value. Because of Roblox’s Client-Server model, changes to attributes that are made on the client will not be able to be seen by the server, meaning ServerScripts will not see real-time changes to attributes if those changes are being made on the client.
Before changing the attribute, head over to the “Test” tab and make sure you are in the “Server” view and not “Client”. You’ll know when you are in Server view as there will be a thin green outline around your game view frame.
Let me know if you have anymore questions or need some more clarification!
Ok, first of all, you’re brilliant! Thank you so much! When I run it in a Server View (at least I think, I simply click Start with 2 players and a local server) then it works as it should. I changed the value for Player2 and didn’t touch Player1. And they got the values as they should! So apparently it does work!
To answer your question, the script part I showed you, where it checks for the afk Boolean, runs in a function that gets fired by a remote event, so not just once after start (to elaborate; it’s a voting screen/script that shouldn’t show when you’re AFK).
Now my new question is; Why does it work in Server View, but not when I simply hit ‘play’ in Studio on my own character. Is that because when I hit play I am both the client and the server at the same time? Just trying to learn an understand it here. But this already helped a lot, I didn’t know about this feature yet! So thank you!
When you press play and you are controlling your character, you are currently play-testing your game as a client, or how a normal player would play your game. Roblox’s Client-Server Model has security checks in place that prevent a lot of changes that might occur to someone on their client from replicating to the server.
For example, without the Client-Server model, an exploiter could delete a baseplate and this change would replicate to everyone in the server. With the Client-Server model, this change would only occur on the exploiter’s client because the server doesn’t trust changes coming in from the client.
This is why if you want to make changes that everyone on a server will see, or changes that your serverscript can read, you have to make these changes on the server, so the server knows it can trust these changes.
To sum it up, the server can’t trust changes the client makes (unless it has to do with physics but that’s a whole other explanation), and because of this any changes you want the server to see or you want your serverscripts to detect, will have to be made on the server (you can use remote events which I’m guessing you probably know a little about since you are already using them).
Edit: To provide a straight answer to your question, you are only the client when you press play in studio. You can never be the client and server at the same time.
That perfectly makes sense. That at least explains why my LocalScript sees the change and the server doesn’t. I’ve considered keeping track of the AFK status through a DataStore, but initially I try to follow the KISS principle. But maybe it’s not such a bad idea after all, since I do want other players to know about the status.
DataStores are used for storing data, so if you wanna have a system where the player leaves a game while they are AFK and then come back and still be labeled as AFK, then I could see a use for datastores in your system.
If you don’t care about the feature I mentioned above, then you actually don’t need to use datastores, and I would actually recommend not using them as they would only add more complexity to your system which you don’t want.
Keeping track of when a player is AFK through your use of attributes I think is a great process.
Edit: I would highly recommend familiarizing yourself with the Client-Server model and how data transportation and networking works. Once you understand those concepts, you’ll have a great understanding of the engine!