Jump to content

[Important-Help]Respawn Vehicle


amirmahdi

Recommended Posts

Hello amirmahdi,

this is done in two simple steps. (serverside)

  • First we calculate the nearest vehicle of the player. This can be done by getting all vehicles on the server and using the distance metric to find the vehicle with the smallest distance and return it.
local function findClosestVehicle(elem)
    local vehicles = getElementsByType("vehicle");
    
    local elem_x, elem_y, elem_z = getElementPosition(elem);
    
    local closest_veh = false;
    local closest_dist = false;
    
    for m,veh in ipairs(vehicles) do
        local veh_x, veh_y, veh_z = getElementPosition(veh);
        
        local dist = getDistanceBetweenPoints3D(elem_x, elem_y, elem_z, veh_x, veh_y, veh_z);
        
        if not (closest_dist) or (closest_dist > dist) then
            closest_dist = dist;
            closest_veh = veh;
        end
    end
    
    return closest_veh;
end
  • Next we create a command handler "rscar" which uses our new function to respawn the closest vehicle.
addCommandHandler("rscar",
    function(player)
        local veh = findClosestVehicle(player);
        if not (veh) then
            outputChatBox("could not find close vehicle", player);
            return;
        end
        -- TODO: use respawnVehicle to place the vehicle on the map again.
    end
);

Good luck!

  • Thanks 1
Link to comment

Hello again my friend

Thank you for your great help 

3 hours ago, The_GTA said:

Hello amirmahdi,

this is done in two simple steps. (serverside)

  • First we calculate the nearest vehicle of the player. This can be done by getting all vehicles on the server and using the distance metric to find the vehicle with the smallest distance and return it.
local function findClosestVehicle(elem)
    local vehicles = getElementsByType("vehicle");
    
    local elem_x, elem_y, elem_z = getElementPosition(elem);
    
    local closest_veh = false;
    local closest_dist = false;
    
    for m,veh in ipairs(vehicles) do
        local veh_x, veh_y, veh_z = getElementPosition(veh);
        
        local dist = getDistanceBetweenPoints3D(elem_x, elem_y, elem_z, veh_x, veh_y, veh_z);
        
        if not (closest_dist) or (closest_dist > dist) then
            closest_dist = dist;
            closest_veh = veh;
        end
    end
    
    return closest_veh;
end
  • Next we create a command handler "rscar" which uses our new function to respawn the closest vehicle.
addCommandHandler("rscar",
    function(player)
        local veh = findClosestVehicle(player);
        if not (veh) then
            outputChatBox("could not find close vehicle", player);
            return;
        end
        -- TODO: use respawnVehicle to place the vehicle on the map again.
    end
);

Good luck!

I just had one more question

For example, you can create a file in the resource if it is deleted or changed. Do not continue to use that resource

Something like the following resource?

This https://www.mediafire.com/file/i5vsu0fxu8oyvdc/HUD.rar

When the LICENSE file is deleted or changed, the resource will no longer work

Link to comment
13 hours ago, amirmahdi said:

When the LICENSE file is deleted or changed, the resource will no longer work

I think you are talking about plausible self protection logic in resources. I recommend you to compile the scripts which come with such protective steps. You can prevent the loading of a script under a certain condition by putting the check at the very top of the script, above everything else. For example, let's check for the existence of a file called "LICENSE".

do
    local doesLicenseFileExist = fileExists("LICENSE");

    if not (doesLicenseFileExist) then
        error("FATAL ERROR: LICENSE file missing!");
    end

    -- TODO: calculate the MD5 of the LICENSE file and put it here as constant.
    local md5_of_license = string.toupper("");

    local fh = fileOpen("LICENSE");

    if not (fh) then
        error("FATAL ERROR: failed to open LICENSE file for checksum verification!");
    end

    local fcontent = fileRead(fh, fileGetSize(fh));
    
    fileClose(fh);
    
    local fcontent_md5 = md5(fcontent);
    
    if not (fcontent_md5 == md5_of_license) then
        error("FATAL ERROR: LICENSE file has changed! (MD5 found " .. fcontent_md5 .. ", expected " .. md5_of_license .. ")");
    end
end

...

By using checksum verification you leave open a small window of chance that the attacker does modify your license in such a way that he created a different LICENSE file with the same hash as your original. But doing so should create a LICENSE file which does not feasibly originate from you so it is easy to argument your way out of it in a trial.

The attacker could hijack the fileOpen, fileRead, fileExists, fileGetSize, fileClose and md5 functions by providing own implementations. This hijack would not be detectible and would circumvent your protection. That is why there is no perfect protection but putting these steps does present the argument that you want your code protected which is enough in a trial.

Edited by The_GTA
simplification for beginners, added helpful MD5 feedback
  • Thanks 2
Link to comment
1 hour ago, The_GTA said:

I think you are talking about plausible self protection logic in resources. I recommend you to compile the scripts which come with such protective steps. You can prevent the loading of a script under a certain condition by putting the check at the very top of the script, above everything else. For example, let's check for the existence of a file called "LICENSE".

do
    local doesLicenseFileExist = fileExists("LICENSE");

    if not (doesLicenseFileExist) then
        error("FATAL ERROR: LICENSE file missing!");
    end

    -- TODO: calculate the MD5 of the LICENSE file and put it here as constant.
    local md5_of_license = "";

    local fh = fileOpen("LICENSE");

    if not (fh) then
        error("FATAL ERROR: failed to open LICENSE file for checksum verification!");
    end

    local fcontent = fileRead(fh, fileGetSize(fh));
    
    fileClose(fh);
    
    local fcontent_md5 = md5(fcontent);
    
    if not (fcontent_md5 == md5_of_license) then
        error("FATAL ERROR: LICENSE file has changed!");
    end
end

...

By using checksum verification you leave open a small window of chance that the attacker does modify your license in such a way that he created a different LICENSE file with the same hash as your original. But doing so should create a LICENSE file which does not feasibly originate from you so it is easy to argument your way out of it in a trial.

The attacker could hijack the fileOpen, fileRead, fileExists, fileGetSize, fileClose and md5 functions by providing own implementations. This hijack would not be detectible and would circumvent your protection. That is why there is no perfect protection but putting these steps does present the argument that you want your code protected which is enough in a trial.

sorry

It is possible to look at my file to see where the problem comes from?

Because in the console it gives me the following error

Although I did the steps you mentioned

 

my resource :  https://www.mediafire.com/file/u1cdn3wnozwhqij/Fly.rar

error : [18:30:16] ERROR: Fly\server.lua:24: FATAL ERROR: LICENSE file has changed!

Link to comment
1 hour ago, amirmahdi said:

error : [18:30:16] ERROR: Fly\server.lua:24: FATAL ERROR: LICENSE file has changed!

You have used the following MD5 checksum:

Quote

d9a9cfa236582696ec816dc8dfdd9c97

but MTAs md5 function does return an upper-case md5 string, thus you should turn it into...

Quote

D9A9CFA236582696EC816DC8DFDD9C97

Does that fix your problem?

HINT: you can use the string.upper Lua function to turn a lower-case string to upper-case.

Edited by The_GTA
  • Thanks 1
Link to comment
6 hours ago, The_GTA said:

You have used the following MD5 checksum:

but MTAs md5 function does return an upper-case md5 string, thus you should turn it into...

Does that fix your problem?

HINT: you can use the string.upper Lua function to turn a lower-case string to upper-case.

No, unfortunately not?

Link to comment
10 hours ago, amirmahdi said:

No, unfortunately not?

You might be using a faulty MD5 hasher that treats line-endings differently (the COPY & PASTE process adds or removes CRLF and turns it into LF only, etc). For that reason it is important that you use the MTA provided md5 function instead of random online MD5 hashing services. You can easily modify the above code like the following to obtain the MTA generated MD5 string:

    ...
    
    local fcontent_md5 = md5(fcontent);
    
    if not (fcontent_md5 == md5_of_license) then
        error("FATAL ERROR: LICENSE file has changed! (MD5 found " .. tostring(fcontent_md5) .. ")");
    end
end

...

This way the error message will contain the expected MD5 value. How about you try adjusting the code and setting the constant to the one from the new error message?

HINT: the expected MD5 is EE519C0C252F9064053A7354A595D416

Edited by The_GTA
  • Thanks 1
Link to comment
18 hours ago, The_GTA said:

You might be using a faulty MD5 hasher that treats line-endings differently (the COPY & PASTE process adds or removes CRLF and turns it into LF only, etc). For that reason it is important that you use the MTA provided md5 function instead of random online MD5 hashing services. You can easily modify the above code like the following to obtain the MTA generated MD5 string:

    ...
    
    local fcontent_md5 = md5(fcontent);
    
    if not (fcontent_md5 == md5_of_license) then
        error("FATAL ERROR: LICENSE file has changed! (MD5 found " .. tostring(fcontent_md5) .. ")");
    end
end

...

This way the error message will contain the expected MD5 value. How about you try adjusting the code and setting the constant to the one from the new error message?

HINT: the expected MD5 is EE519C0C252F9064053A7354A595D416

yes i m using an online hash

My problem was solved while using your code

The new code gave me the text in the license file as a hash and my problem was solved

Thank you for taking the time to help me, brother

 

 

Link to comment
17 hours ago, The_GTA said:

You're welcome! I like helping people that really need my experience and insight. ?

Hi Again ?

 

Is it possible to specify in the resource if this resource is run on another IP server, give an error?

I mean the resource only works on the IP we define

Link to comment
8 minutes ago, amirmahdi said:

I mean the resource only works on the IP we define

If you link a script to a fixed IP you imply that the script is meant to be run on the specified IP only. I think this is an interesting idea. You can use this IP check in serverside scripts if you have defined the IP inside the mtaserver.conf file. Please note that I have no experience with the practicability of such a check!

Look at the getServerConfigSetting function wiki entry for further details.

Add the following statement to the top do-end block of your script:

local run_server_ip = ""; -- put server IP here (example: 127.0.0.1)

if not (getServerConfigSetting("serverip") == run_server_ip) then
  error("FATAL ERROR: script not licensed to run on this server!");
end
Edited by The_GTA
  • Thanks 1
Link to comment
On 20/10/2021 at 03:04, The_GTA said:

Hello amirmahdi,

this is done in two simple steps. (serverside)

  • First we calculate the nearest vehicle of the player. This can be done by getting all vehicles on the server and using the distance metric to find the vehicle with the smallest distance and return it.
local function findClosestVehicle(elem)
    local vehicles = getElementsByType("vehicle");
    
    local elem_x, elem_y, elem_z = getElementPosition(elem);
    
    local closest_veh = false;
    local closest_dist = false;
    
    for m,veh in ipairs(vehicles) do
        local veh_x, veh_y, veh_z = getElementPosition(veh);
        
        local dist = getDistanceBetweenPoints3D(elem_x, elem_y, elem_z, veh_x, veh_y, veh_z);
        
        if not (closest_dist) or (closest_dist > dist) then
            closest_dist = dist;
            closest_veh = veh;
        end
    end
    
    return closest_veh;
end
  • Next we create a command handler "rscar" which uses our new function to respawn the closest vehicle.
addCommandHandler("rscar",
    function(player)
        local veh = findClosestVehicle(player);
        if not (veh) then
            outputChatBox("could not find close vehicle", player);
            return;
        end
        -- TODO: use respawnVehicle to place the vehicle on the map again.
    end
);

Good luck!

hi again :)

Honestly, this is the reason why I am annoyed

When the car is healthy, one of the car wheels disappears.

And that if we have two cars and they both explode.

When we repair the first car, the second car is repaired in the place of the first car instead of being spun in the same place of explosion.

 

Edit : Of course, the problem of the wheels is not very important

Edited by amirmahdi
edit
Link to comment
6 hours ago, amirmahdi said:

hi again :)

Honestly, this is the reason why I am annoyed

When the car is healthy, one of the car wheels disappears.

And that if we have two cars and they both explode.

When we repair the first car, the second car is repaired in the place of the first car instead of being spun in the same place of explosion.

 

Edit : Of course, the problem of the wheels is not very important

Could you show me your code? It is hard to judge if you give me nothing.

  • Thanks 1
Link to comment

 

 

This is my code and I mentioned the problems above

9 hours ago, The_GTA said:

Could you show me your code? It is hard to judge if you give me nothing.

---- Serverside !


local function findClosestVehicle(elem)
    local vehicles = getElementsByType("vehicle");
    local elem_x, elem_y, elem_z = getElementPosition(elem);
    local closest_veh = false;
    local closest_dist = false;
    for m,veh in ipairs(vehicles) do
        local veh_x, veh_y, veh_z = getElementPosition(veh);
        local dist = getDistanceBetweenPoints3D(elem_x, elem_y, elem_z, veh_x, veh_y, veh_z);
        if not (closest_dist) or (closest_dist > dist) then
            closest_dist = dist;
            closest_veh = veh;
        end
    end
    return closest_veh;
end
addCommandHandler("repaire",
    function(player)
        local veh = findClosestVehicle(player);
		if getPlayerName(player) == getElementData(veh, "owner") then
			local getfueldb = tonumber(getElementData(vehSys:getVehicleData(veh),"vFuel"))
			respawnVehicle(veh,veh_x, veh_y, veh_z,0,0,200)
			setElementData(veh,"fuel",getfueldb)
		else
			outputChatBox("This is not your car !",player,255,0,0,true);
		end
    end
);
Edited by amirmahdi
Link to comment
1 minute ago, amirmahdi said:

So it does not matter if the car exploded?

Because I thought fixVehicle functions would only work for damaged machines

Why would you think so? The wiki page says the following:

Quote

This function will set a vehicle's health to full and fix its damage model. If you wish to only change the vehicle's health, without affecting its damage model, use setElementHealth.

Do you read anywhere in the above text that the function does not work for you?

  • Thanks 1
Link to comment
10 hours ago, The_GTA said:

I am glad to have helped you! Come back to this forum if you have any further questions.

There is a way that the code remembers the first two letters of the car plate and if Did the code match the given letters to continue ?

for example

function respawnExplodedVehicle()
	for index, free_car1 in ipairs(getElementsByType("vehicle")) do 
		local vehplate = getVehiclePlateText ( free_car1 )
		if vehplate == "FR" then -- "FR" Specified letters
			cancelEvent()
		else
			setTimer(respawnVehicle,2000,1,free_car1) 
			setElementData( free_car1 ,"fuel",105)
		end
	end		
end
addEventHandler("onVehicleExplode", getRootElement(), respawnExplodedVehicle)

 

Link to comment
  • 2 weeks later...
On 29/10/2021 at 02:11, The_GTA said:

Use the string.sub function with parameters 1 and 2 to get the first two letters of a string. Then you can compare the result with your own specified two letters.

Hi again

How do I write a condition to continue the code when the player is out of the water?

Something like that

intt = 10
if isElementInWater(getLocalPlayer()) then
  intt = 20
end
if Getoutofthewater(getLocalPlayer()) then --Getoutofthewater (example)
  intt = 30
end

Client !

Edited by amirmahdi
Link to comment
27 minutes ago, amirmahdi said:

Hi again

How do I write a condition to continue the code when the player is out of the water?

Something like that

intt = 10
if isElementInWater(getLocalPlayer()) then
  intt = 20
end
if Getoutofthewater(getLocalPlayer()) then --Getoutofthewater (example)
  intt = 30
end

Client !

 

 

Of course, I solved the previous one myself

If possible, help me in the text below?

Something can be done
When the car falls into the water, move the car to the nearest land?

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...