Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

why does Localscript not edit Server Workspace but Clientside Workspace?

Asked by
CJ4 2
6 years ago

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)
0
You answered your question in the title! T0XN 276 — 6y

3 answers

Log in to vote
1
Answered by
amanda 1059 Moderation Voter
6 years ago
Edited 6 years ago

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:

Remote Functions and Events

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:

Ad
Log in to vote
0
Answered by
oreoollie 649 Moderation Voter
6 years ago
Edited 6 years ago

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.

Log in to vote
0
Answered by 6 years ago

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)

Answer this question