I was making a game where a 3d box moves into an outline and you have to press a certain key to hit the 3d box. It works perfectly using the Play button in roblox studio, but when I use a server, everything just stops working correctly. On the server screen, nothing is moving; but on the client screen, things are moving but input is completely ignored, as if these were two different programs.
Problem I noticed that local scripts only edit Clientside Workspace, which is the workspace that appears for you, which I found odd because usually it does not do this. It works if I change it to a global script, but I still cannot access keyboard input without using a local script. I tried using boolvalues that the local script would set true and the global script would detect so that it would run the functions for them but, as stated earlier, the local script affects the Clientside Workspace not the Server Workspace, so the values appeared true on the client screen but appeared false on the server screen.
Question How do I make functions that affect the Server Workspace when pressing a key on the keyboard?
global script -- used to do global work for localscript
wait(0.5) Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "keyXpressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key0pressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key1pressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key2pressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key3pressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key4pressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key5pressed" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key1lifted" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key2lifted" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key3lifted" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key4lifted" Instance.new("BoolValue", script.Parent.GuitarKeyScript).Name = "key5lifted" print("valuesmade") while true do if script.Parent.GuitarKeyScript.keyXpressed.Value == true then script.Parent.GuitarKeyScript.keyXpressed.Value = false if game.Workspace.Guitar.Overdrive.Value >= 50 then game.Workspace.Guitar.Overdrived.Value = true end end end
local script -- used to detect key presses on keyboard
wait(1) local mouse = game.Players:FindFirstChild(script.Parent.Name):GetMouse() workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable workspace.CurrentCamera:Interpolate(game.Workspace.Head.CFrame,game.Workspace.Head2.CFrame,0.5) script.Parent.Humanoid.WalkSpeed = 0 local keyX = "j" local key0 = "k" local key1 = "q" local key2 = "w" local key3 = "e" local key4 = "r" local key5 = "t" function press(key) key = string.lower(key) if key == keyX then script.keyXpressed.Value = true end if key == key0 then script.key0pressed.Value = true elseif key == key1 then script.key1pressed.Value = true elseif key == key2 then script.key2pressed.Value = true elseif key == key3 then script.key3pressed.Value = true elseif key == key4 then script.key4pressed.Value = true elseif key == key5 then script.key5pressed.Value = true end end function lift(key) key = string.lower(key) if key == key1 then script.key1lifted.Value = true elseif key == key2 then script.key2lifted.Value = true elseif key == key3 then script.key3lifted.Value = true elseif key == key4 then script.key4lifted.Value = true elseif key == key5 then script.key5lifted.Value = true end end mouse.KeyDown:connect(press) mouse.KeyUp:connect(lift)
ROBLOX has introduced separation between clients and the server as a form of protection from exploiters. In order to get around this, you must use RemoteEvents
or RemoteFunctions
.
These are Instances that you create and place inside ReplicatedStorage
, and it allows a client-side script to communicate with a server-side script, and vice versa.
Here is an article which may help:
RemoteEvents
allow for sending a one-way message, and RemoteFunctions
trigger a function on the opposite side and are given a return value.
In this situation, I think we can get away with using a RemoteEvent
going from the client to the server, triggering when input is given.
Because the server is the receiver, we will be using the method re:FireServer()
to send input and the event re.OnServerEvent
to get input, which will be connected to a function. (Note: replace re
with a variable containing the path to your RemoteEvent
)
0
--Client
local repstore = game:GetService("ReplicatedStorage") local sendkeys = repstore.SendKeys or repstore:WaitForChild("SendKeys") --REMOTE EVENT local uis = game:GetService("UserInputService") uis.InputBegan:Connect(function(obj) if obj.UserInputType == Enum.UserInputType.Keyboard then sendkeys:FireServer(obj.KeyCode.Name) end end)
--Server
local repstore = game:GetService("ReplicatedStorage") local sendkeys = repstore.SendKeys or repstore:WaitForChild("SendKeys") --REMOTE EVENT sendkeys.OnServerEvent:Connect(function(player, key) print(player.Name.." has pressed "..key) if key == "G" then print("You are a G ;)") end end)
In order to also detect when keys are released, you should use uis.InputEnded
which works identical to uis.InputBegan
. (Note: uis
is referring to UserInputService
, to properly define it please reference my Client
script above. Here are some more helpful links:
A local script runs only on the client. Changes to the client are not replicated to the server unless Filtering Enabled is off. The reason this works in studio play mode is because in play mode, the client is also the server. In server test mode the client and the server are separated. Changes to one client will only affect that one client and not the server or other clients. To answer your question of how to make the client effect the server, you could use a RemoteEvent
. I would suggest firing the event every time one of those values changes. On the client, you should call
event:FireServer()
And the server should wait for this to occur using
event.OnServerEvent:Connect()
Further documentation on RemoteEvents can be found here. If you need more assistance, feel free to contact me on Discord (Nitrousoxide#3667)
If my answer solved you problem, please remember to mark it as correct.
Pressing keys on Local scripts work because local scripts are local, they handle user input. The server doesn’t have a keyboard or mouse, or does it?
No. The clients do have a mouse and keyboard (unless they’re on console or mobile lol).
You use a server script when the changes you want to make are for all the players, and all the server. For example, changing the colour of a part. You’d want the entire server to see it. Not just one player.
Seeing your client code, you’re using Mouse.KeyDown
and Mouse.KeyUp
, which are deprecated. You’re also using :connect
when it’s :Connect
. Use UserInputService
to get user input. I will provide an example.
Do keep in mind that keys in UserInputService
are Enum
values, meaning you cannot access it with strings.
If you wanted to get input from user pressing E
, you wouldn’t make your variable like this:
local E = "E"
but like this:
local E = Enum.KeyCode.E
function onkeypress(input, chatting) if chatting then return -- if plr is chatting while pressing our key we will end function end print(input.KeyCode.Name) -- print name end game:GetService("UserInputService").InputBegan:Connect(onkeypress)