Jump to content

Best way to ask for the player's data?


Cronoss

Recommended Posts

My script requires to ask the data from the user; it's constantly changing. I'm guessing this might cause problems if a player starts to spam the command, that's not the problem, I know how to disable the command for a couple of seconds but my question is, how should I ask this info if I don't want to get low fps for the players? I know it doesn't make sence that I ask this kind of stuff because I said "I know how to disable the command for a couple of seconds" but I meant that I know how to make my system work (a system that I don't really like), but I maybe there is a way to make it work ten times better, that's why I'm posting this, I need to know how to make this without asking the element data every time...

function example(thePlayer, cmd)
   local thingCheck = tonumber(getElementData(thePlayer, "thing")) --------get total "things" in player's data
   local thingCount = tostring(thingCheck) ---convert to string
   if (thingCheck>=1) then 
       outputChatBox("You have "..thingCount.. " thing(s).", thePlayer, 255,255,255) -----display the info that the player want to know
   else
       outputChatBox("You don't have anything.", thePlayer, 255, 255, 255)
   end
end
addCommandHandler("mythings", example)

 

Link to comment

You can use a table for this, if you don't have very complex code on the client side, I strongly recommend using a table.

example:

local playerThings = {} -- storage place for player things

function example(thePlayer, cmd)
   local thingCheck = playerThings[thePlayer] -- if player things are always going to be numbers then there is no need for "tonumber"
   --local thingCount = tostring(thingCheck) -- actually I think it is not needed because you convert it to string type with concatenation in outputChatBox function

   if (thingCheck and thingCheck >= 1) then 
       outputChatBox("You have "..thingCheck.." thing(s).", thePlayer, 255,255,255)
   else
       outputChatBox("You don't have anything.", thePlayer, 255, 255, 255)
   end
end
addCommandHandler("mythings", example)

 

Edited by Burak5312
  • Like 1
Link to comment

Sorry, I didn't respond; I understand the solution you made, and I appreciate it but in this case "the  player's thing" it's a number that is constantly changing (decreasing) so if I want to save that I should use setElementData I guess, because if the player quits and join again the script should show the last "thing count", isn't there a way to display this info without involving server-side ?

 

Link to comment
  • Moderators
3 minutes ago, Cronoss said:

isn't there a way to display this info without involving server-side ?

Saving the data on the client is possible (cookie). The downside is of course that the player could modify or delete it.

 

XML file:

https://wiki.multitheftauto.com/wiki/Client_Scripting_Functions#XML_functions
 

Regular file:

https://wiki.multitheftauto.com/wiki/Client_Scripting_Functions#File_functions

+ any format or the usage of JSON

 


 

Note: If something is decreasing in a linear way, the server can nearly precise compute what the value will be in the future.
It just needs to know:

  1. The start time.
  2. The start value.
  3. How much it decrease every <time interval>

When the player quits:

-- 
local startTime = getTickCount() -- 1.
local startValue = 50 -- 2.
local usageEachSecond = 1 -- 3.
--

-- time passes here...

-- on quit
local timeNow = getTickCount()
local timePassed = timeNow - startTime
local used = (timePassed / 1000) * usageEachSecond

local endValue = startValue - used
if endValue < 0 then
	endValue = 0
end

 

Link to comment

Update, I moved the "getElementData" thing into client-side, I just noticed that I should've just tell what I was trying to make instead of giving examples. I wanted to make a Fuel-System for vehicles, I moved all the getElementData and setElementData into client-side, and it works pretty good but I want to ask... using getElementData  for a "on client render" function could cause problems? The function "onclientrender" changes the color of the fuel-icon so if the player starts to get less than 50% the icon starts to turning red, that's why I need to get the "fuel value"

Link to comment
  • Moderators
2 hours ago, Cronoss said:

What do you mean with this part?

Clientside is located on the player their pc. When the game is not running, you are able to modify your downloaded files. Files which are defined by the server meta.xml are protected and will be validated (+reset if incorrect). But files created by Lua scripts are not.

 

59 minutes ago, Cronoss said:

getElementData  for a "on client render" function could cause problems?

As long as it is not setElementData, it is fine.

 

Building the fuel system fuel-value-management clientside is OK, but not great.

 



 

  • Confused 1
Link to comment

I don't want to be annoying with this topic but I really want to learn and make my script the best as I can

Quote

Building the fuel system fuel-value-management clientside is OK, but not great.

 

I want to make it in the right way

I've been trying with this in server-side:

function setG()
	veh = getPedOccupiedVehicle(source) 
    stateG = getVehicleEngineState(veh) 
	if (veh) then 
        if (stateG==true) then 
            plate = getVehiclePlateText(veh)
            x,y,z = getElementPosition(veh)
            fuelVeh = getElementData(veh, "Fuel") ---------setElementData is in another resource when the player buys the car (server-side)
            if (fuelVeh <= 0) then -----if the fuel it's 0 or less then the car engine turns off
        	   setVehicleEngineState(veh, false)
        	   setElementData(veh, "Fuel", 0) ----this fix some problems like "-0.023" numbers 
    	   else
                setElementData(veh, "Fuel", fuelVeh) ------if the fuel it's above 0 then the fuel recieved it's saved (this is because of the next function)
                vehMove() -------This function it's called
            end
        end
    end
end
addEvent("chekG", true)
addEventHandler("chekG", root, setG)

-------------------------------------------------------------------------------------
function vehMove() ---vehicle movement
	local dx,dy,dz = x+0.05, y+0.05,z+0.05 
	local fuelConsumption = 0.900
	if (fuelVeh) >= 1 then
        distance = getDistanceBetweenPoints3D(x,y,z,dx,dy,dz)
        newFuel = tonumber((fuelVeh - (fuelConsumption*distance)))
        iprint("Gas: "..newFuel)
        setElementData(veh, "Fuel", newFuel)
    else
          iprint("No fuel")
    end
end

And the client who calls the first function in server-side:

setTimer(function()
    if (vehicle) then 
        triggerServerEvent("chekG", localPlayer)
    end
end, 10000, 0) ------------10 seconds before it repeats

 

Edited by Cronoss
Link to comment
  • Moderators
44 minutes ago, Cronoss said:

I want to make it in the right way

 

Clientside

53 minutes ago, Cronoss said:
   if (vehicle) then 

Doing a live check:

if isPedInVehicle(localPlayer) then

 

Serverside

Add some more local's etc.

local veh = getPedOccupiedVehicle(source) 
local stateG = getVehicleEngineState(veh) 
	

And make use of arguments for the vehMove() function.

vehMove(veh, fuelVeh, x, y, z) -- in > arguments

-------------

function vehMove(veh, fuelVeh, x, y, z) -- out > parameters

That way you make sure that the data stays within the functions.

 

Adding a fallback for new vehicles (until there is data available from a database):

local fuelVeh = getElementData(veh, "Fuel") or 0 -- or set to max

 

This doesn't looks like a logic line, there is no value change so there is no need to set it:

setElementData(veh, "Fuel", fuelVeh) ------if the fuel it's above 0 then the fuel recieved it's saved (this is because of the next function)

 

  • Thanks 1
Link to comment
  • Moderators
11 hours ago, Cronoss said:

And I'm guessing this is the most optimized way to make a system like this?

You are not finished in the slightest + a lot of edge cases to look at.

 


 

The most significant optimisation will be applied when working with subscriber mode. This will stop sending element data to other players and only the ones that need it.

 

On vehicle enter:

addElementDataSubscriber(veh, "Fuel", thePlayer )

 

On vehicle exit:

removeElementDataSubscriber(veh, "Fuel", thePlayer )

 

https://wiki.multitheftauto.com/wiki/AddElementDataSubscriber

setElementData( veh, "Fuel", fuelVeh, "subscribe" )

https://wiki.multitheftauto.com/wiki/SetElementData

 

 

 

 

 

  • Thanks 1
Link to comment

Hey, I just have one more question because the wiki doesn't spicifies this or I didn't get the meaning of some words translated. If I set the data first in server-side from another resource I should use just "setElementData"? or also use "addElementDataSubscriber"? (Thanks for your patiente btw)

function addFuelToPlayer(thePlayer)
    addElementDataSubscriber(source, "Fuel", thePlayer)
    iprint("addfuel")
end
addEventHandler("onVehicleEnter", getRootElement(), addFuelToPlayer)

function removeFuelToPlayer(thePlayer)
    removeElementDataSubscriber(source, "Fuel", thePlayer)
    iprint("removefuel")
end
addEventHandler("onVehicleExit", getRootElement(), removeFuelToPlayer)

--------------------------SERVER SIDE FROM ANOTHER FUNCTION-------------------------------
vehicle = (createVehicle, 410, bla, bla, bla)
vehicleGas = setElementData(vehicle, "Fuel", 100, "subscriber")--or setElementData(vehicle, "Fuel", 100), or addElementDataSubscriber

 

Link to comment
  • Moderators
11 hours ago, Cronoss said:
setElementData(vehicle, "Fuel", 100, "subscriber")

Like this.

When adding a subscriber, the data will be automatic synced.

 

Here you have a test resource to see the behaviour of all stages. Very recommended to test it out, so that you do not add too much code.

Spoiler

meta.xml

<meta>
    <info author=""
          version="1.0.0"
          name=""
          type="script" />
    <script src="main_s.lua"
            type="server" />
    <script src="main_c.lua"
            type="client" />
</meta>

main_s.lua

local element = createElement( "test", "test-subscriber" )
setElementData( element, "test", 1, 'subscribe' )

iprint( 'set data to 1' )

setTimer( function()
	addElementDataSubscriber( element, "test", getRandomPlayer() )
	iprint( 'subscribe' )
end, 5000, 1 )

setTimer( function()
	removeElementDataSubscriber( element, "test", getRandomPlayer() )
	iprint( 'unsubscribe' )
end, 10000, 1 )

setTimer( function()
	setElementData( element, "test", 2, 'subscribe' )
	iprint( 'set data to 2' )
end, 15000, 1 )

setTimer( function()
	addElementDataSubscriber( element, "test", getRandomPlayer() )
	iprint( 're-subscribe' )
end, 20000, 1 )

main_c.lua

addEventHandler( "onClientRender", root, function()
	local element = getElementByID( "test-subscriber" )
	if element then dxDrawText( tostring( getElementData( element, "test" ) ), 300, 300 ) end
end )

 

 

  • Thanks 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...