What is the best and most efficient way to take a variable from the server and make it so either a client can ask for it or the server changes it for chosen player.
If this example isnt what you’re looking for then go ahead and explain in more detail what you need but:
Say you want to set the money of a player so he can purchase things from a serverside shop and have money deducted from him, a lot of people would tell you to use NWInts, the problem with NWInts is that they are broadcast to every entity on the server, including the server itself, which is unnecessary CPU because you only need the server to know about it.
So use usermessages!
In cl_init.lua we define a local, clientside variable, then let a usermessage function set that variable:
local Money = 0 --Define a clientside variable (Clientside scripts are run per client, which means this number is unique to the player it is defined on.
function SetMoneyCL(um) --Define a function that will set the Money variable to w/e the usermessages int is.
Money = um:ReadLong() --Sets the clientside money variable to the long (integer) sent to the client in the usermessage.
usermessage.Hook(“SetMoney”, SetMoneyCL) --Hooks the function so that when the client recieves the umsg: “SetMoney” the function is ran.
In init.lua we create the usermessage and hook it to PlayerInitialSpawn. We’ll send a float of 500 to the client in a usermessage, which will be recieved and set the clientside variable to 500.
function GM:PlayerInitialSpawn(pl) --We put the umsg inside InitialSpawn so when the player first joins the server his money loads.
umsg.Start(“SetMoney”, pl) --Sends the umsg: “SetMoney” to the pl called by this function.
The clientside script sets a variable unique to the player, then creates a function hooked to a usermessage, that sets the players “money” to whatever the long is that is included in the usermessage.
In the serverside script, we send the usermessage we hooked to in the clientside file, when the player first joins the game. In the usermessage we send the long, 500, which will be recieved and read by the player that reads it.
Essentially this all sets the player’s money to 500. To send the money to the server, say, when you purchase something, use a console command:
function BuyBall(pl, cmd, args) --Create a function linked to a console command that takes multiple parameters (The first parameter (args) = the player’s money)
if args >= 100 then --args means the first parameter coming after the console command itself. “sv_gravity” is the console command, and “600” is the first parameter. “sv_gravity 600”
pl:Give(“AFuckingBall”) --Give the player his useless toy
umsg.Start(“SetMoney”, pl) --Call the usermessage and set the players money again
umsg.Long(args - 100) --Set the users money to his current money, minus 100 (The assumed cost of the useless ball)
else print(“You cannot afford this.”) end --If he doesnt have enough money then tell him.
concommand.Add(“BuyABall”, BuyBall) --I shouldnt have to explain.
DButton.DoClick = function() --This is just an example of calling the concommand, lets pretand you created a button called “DButton” for this example.
RunConsoleCommand(“BuyABall”, Money) --Call the function to buy a ball, with your money as the first parameter.
The code should be MORE than enough for your needs, hopefully you choose my slightly complicated version over the sloppy NWInt method.
The above code is fine, but I feel I should point this function out: **[DButton.SetConsoleCommand
Assuming you only need a single argument, if any at all. While the Wiki says it takes any number of arguments, it only accepts one if you look at the source for the function.
Hm, I never saw that, thanks. Not as if making a manual button work was a big deal but I’m sure it’ll come in handy when I make something that has a lot of buttons.
I understand what you are saying and this way seems the best way for most things that are per player and this helps alot. The thing is I also need one for all players. So what would be the best way to send a variable to all players? I want to create a count down timer that all players would see.
Do you mean a variable unique to each player that all players can see? That’d be a NWVar
If you mean a variable that everyone sees, say a gamemode timer, you’d do:
local TimeLeft = 10
timer.Create(“RoundTimer”, 1, 0, function(pl) --Create a serverside timer that runs the function every second, and runs infinite times.
TimeLeft = TimeLeft - 1
umsg.Start(“UpdateTimer”, pl) --Sends the umsg “UpdateTimer” to the player
umsg.Long(TimeLeft) --Sends the updated round time as the long
local RoundTimeCL = 10 --The CL at the end of the variable identifier isnt necessary, I just like to differentiate between clientside and serverside variables
RoundTimeCL = um:ReadLong()
usermessage.Hook(“UpdateTimer”, UpdateRoundTimer) --When “UpdateTimer” is recieved, run UpdateRoundTimer
Then just draw your timer with HUDPaint and the draw or surface libraries (I recommend Draw) and set the text of the timer to display the clientside variable.
Thanks alot. Drop me your steam if you want and i can show you the dev as we go on.