Jump to content

IIYAMA

Moderators
  • Posts

    6,097
  • Joined

  • Last visited

  • Days Won

    218

Everything posted by IIYAMA

  1.  

        /\
       /  \
      /    \
     /      \
    /        \
    ----------

     

    For those who have already downloaded the tool I post. I found and removed a critical bug in it, which had to do with calling back the client. While testing (alone) I didn't notice that it was sending information back to all clients instead of the one that should receive it. My apologies about this.

     

    Change in the source code:

    https://gitlab.com/IIYAMA12/mta-communication-enchantment/commit/c425481b5e49da3ff4aab9b5552795e2f2563e98

     

    It is recommended to re-download the tool in that case.

    NOTE: I will not make feature announcements here, only critical bugs.

     

    Re-download

  2. @Overkillz I made an announcement about your option 2 on my status updates. (Topic comes later, when I have more time)
  3. MTA-Communication-Enchantment

    It is finally far enough in development to share this with you. I made an announcement a few days ago about solving some struggles, that people have with communicating between the server and the client. Today is the day that it isn't just rumour, but for you to use.

     

    Before I am going to write a topic for it, I prefer to solve any unknown issues first. That is where you guys might come in!

     

    Just an example:(1)

    Passing arguments like you used to@

    --CLIENT
    callServer("passingArguments", "arg1", "arg2", "arg3")
    -- SERVER
    function passingArguments (arg1, arg2, arg3)
    	outputChatBox(arg1 .. " " .. arg2 .. " " .. arg3, client)
    end

     

     

    Just an example:(2)

    Calling back!

    -- CLIENT
    callServer(
      	"calculation", 
    	50,
    	100,
    	function (value)
    		outputChatBox("Value: " .. value)			  
    	end
    )

     

    -- SERVER
    function calculation (value1, value2)
    
    	return value1 + value2
    end

     

     

    Just an example:(3)

    Calling before a client has loaded his scripts!

    --SERVER
    addEventHandler("onPlayerJoin", root, 
    function ()
    	
    	callClientAwait(source, "testCallClientAwait")
    	
    end)

     

    -- CLIENT
    function testCallClientAwait ()
    	outputChatBox("Yes this works!")
    end

     


     

    Quote

    List with examples you can explore:

    Examples

     

    List with the syntax of functions you can use:

    Syntax

     

    Set-up for your own resources:

    Set-up

     

     

     

    Thank you @Xwad and @JeViCo for early testing!

     

    Repository: (+ download)

    https://gitlab.com/IIYAMA12/mta-communication-enchantment

    [NOTE] The documentation on the repository is not 100% complete.

     

    Direct download link:
    [NOTE]
    On the repository there is syntax highlight

    https://gitlab.com/IIYAMA12/mta-communication-enchantment/-/archive/master/mta-communication-enchantment-master.zip

    1. Show previous comments  2 more
    2. JeViCo

      JeViCo

      a little example (didn't test it)

      -- CLIENT
      callServer(
        	"checkIfAdmin", localPlayer,
      	function (result)
      		outputChatBox("Does player have admin rights? - " .. tostring(result))			  
      	end
      )
      --SERVER
      function checkIfAdmin(player)
      	return isObjectInACLGroup ( "user." .. getAccountName ( getPlayerAccount ( player ) ), aclGetGroup ( "Admin" ) )
      end

       

    3. IIYAMA

      IIYAMA

      @JeViCo

      Yea it works!

      Nice done

    4. koragg

      koragg

      You intrigued me with the possibility to call certain events after players are actually loaded (thus removing the annoying red errors that come way too often for nothing). I'll definitely use that in a few resources on my server, thanks for creating it! But it'll be a while before I do so, am kinda busy these days. You're awesome ;)

  4. 1. Solving the main issue. In case of sending from server to client. • Do not send triggerClientEvent's over the root variable.(it is also root, when you do not fill in the receiver) Instead use a table which contains all players that have loaded their resources. When the event onClientResourceStart has been triggered, this player is ready to go. When I release a tool that I have been announced two days ago, there will be a 2e. There is also a function in Lua called pcall. This will skip all error messages, but I don't think that will work as it is an async created error. (Not directly shown up when the trigger*Event function is called, but after it has first send to the other side) function test1 (arg) print(arg) end pcall(test1, 13342144) pcall(test2, 354356) -- there is no test2 function, but we can try to call it without any error message.
  5. Dear scripters,

     

    A few days ago I started building  on a new tool/enchantment for a mta functionality. The tool is an enchantment for the trigger[Client/Server]Event function. It will be available for everybody once it is finished.

    I decided to build this tool as challenge for these issues:

    - The current trigger*events can be complex for some people to use.

    - CallBack functionality is not directly available.

    - Sending trigger events before the client has been loaded happens too often. This message will not be received.

    - Can't pass over arguments to the callback function without losing them or making copies. So a functionality that allows you to send tables and functions from(from A to B):

    [A] serverside > (clientside) > B  serverside callback

    (Clientside is left out, while passing  functions/tables)

     

    [A] clientside > (serverside) >  B  clientside callback

    (Serverside is left out, while passing these functions/tables)

     

    A question to you guys:

    Is there any other issue related to the trigger*Event functions that you would like to see automatically/easier?

    1. IIYAMA

      IIYAMA

      Is there anybody who is interested in trying it out, before the beta version is set public?

      If there is, then I will prepare a sample. (documentation included) :fadein:

       

      It is bad practice to release something without letting the user testing it.... You should know better @IIYAMA... ?

  6. @Xwad function getRotationOffset (rot1, rot2) local rotationOffset = (rot1 - rot2 + 360) % 360; if (rotationOffset > 180) then rotationOffset = 360 - rotationOffset else rotationOffset = -rotationOffset end return rotationOffset end function getRotationDifference (rot1, rot2) local rotationDifference = (rot1 - rot2 + 360) % 360; if (rotationDifference > 180) then rotationDifference = 360 - rotationDifference end return rotationDifference end Test them out and see which one you think need. getRotationOffset positive and negative. getRotationDifference only positive.
  7. He said two things: This doesn't sounds like server that can't handle things any more. This sounds like a clientside issue to me. But if the serverside also plays a role in it, that really depends on the resources.
  8. There should be a checkbox with the label: "Include clients" (on the top part you just cut off) Not sure if they disabled or removed it. Another way to view this information can be accessed with the browser: http://127.0.0.1:22005/resourcebrowser/ There you can do the same thing.
  9. Afaik from 0 to 1000. Because according to wiki 1000 enable dual weapons. https://wiki.multitheftauto.com/wiki/Weapon_skill_levels If you really want to know it for sure, then the obvious solution for a programmer is to debug it, isn't it? setPedStat(localPlayer, 21, 1000) iprint("super cow value:", getPedStat(localPlayer, 21))
  10. local selectedResourceName = "" -- < fill in -- This function will be restarting a selected resource. local function restartSelectedResource (selectedResource) local resourceState = getResourceState(selectedResource) if resourceState == "running" then restartResource(selectedResource) elseif resourceState == "loaded" then startResource(selectedResource) end end addEventHandler("onResourceStart", resourceRoot, function () local selectedResource = getResourceFromName(selectedResourceName) if selectedResource then setTimer(restartSelectedResource, 600000, 0, selectedResource) else outputChatBox("Can't find the selected resource.") cancelEvent(true, "Can't find the selected resource.") end end) https://wiki.multitheftauto.com/wiki/SetTimer https://wiki.multitheftauto.com/wiki/OnResourceStart https://wiki.multitheftauto.com/wiki/GetResourceFromName https://wiki.multitheftauto.com/wiki/StartResource https://wiki.multitheftauto.com/wiki/RestartResource https://wiki.multitheftauto.com/wiki/GetResourceState https://wiki.multitheftauto.com/wiki/CancelEvent Make sure the resource has access to these functions <right name="function.startResource" access="true" /> <right name="function.restartResource" access="true" /> startResource restartResource Those functions are blocked by default because they are used for administration purposes. Step 1 The rights can be requested by the resource if you add these lines in to your meta.xml: <aclrequest> <right name="function.startResource" access="true" /> <right name="function.restartResource" access="true" /> </aclrequest> Step 2 Commands left to do: (fill in the <resourceName> of the resource that contains this script) /refreshall /aclrequest allow <resourceName> all
  11. Use the ipb on yourself instead of your server. The server can indeed have influence on the client his FPS, but clientside has far more direct influence on the FPS.
  12. I added some information about the source variable. Feel free to ask questions about this subject.
  13. IIYAMA

    get skin

    local model = getElementModel(element) https://wiki.multitheftauto.com/wiki/GetElementModel setPlayerSkin is deprecated. It might be removed in next MTA versions. Use setElementModel instead. https://wiki.multitheftauto.com/wiki/SetElementModel
  14. yup
  15. I don't think that is enough for just a Youtube video. Open your default browser. Go to the youtube video you want to watch. Open the inspector. Go to the network tab. Reload the page. And see the list of requests + domains showing up one by one.
  16. I am very sure that CORS will block it, if it is from another domain. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS But a way around that would be making a XMLHttpRequest https://developer.mozilla.org/nl/docs/Web/API/XMLHttpRequest And put the website inside of the contentWindow. https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/contentWindow Of course, there are some seriously limitations to this, as images, css, js are received with other requests. So to answer your question: `It depends.` If the CSS, JS, images and other content are embedded then there will be no problem.
  17. Did you optimise it for web? A tool I use a lot: fontsquirrel.com
  18. The easiest way would be invert it's velocity. But in some cases it might not be very accurate. (In case of a player you have to lift him up a little bit) getElementVelocity setElementVelocity ----- Another way would be resetting the player back to it's previous position. (This might require some more performance impact as you will have to record it's previous position at all times.) ----- Another way would be: calculate from the position of the vehicle/player and the position colshape the difference. - Based on each separated axis: x1 - x2, y1 - y2, z1 - z2 (vector) - Based on all axis. (Distance) [might not be required] In case of a sphere colshape the distance from the center is always the same. So you do know how much distance is required to move somebody out of the sphere. If you normalize the vector and multiply it by the required distance, what kind of result do you think that will have? (Just becareful not place the player in the ground....) --- The last way. Just teleport him to a known location out of the area.
  19. Clientside local thisTable = {} addEvent("update-------") addEventHandler("update-------", resourceRoot, function (index, data) thisTable[index] = data end, false) Serverside local thisTable = {} function updateTable (target, index, data) thisTable[index] = data triggerLatentClientEvent(target, "update-------", resourceRoot, index, data) end updateTable(target, "index", {"data"}) -- all players updateTable(getElementsByType("player"), "index", {"data"}) -- all players updateTable(getRandomPlayer(), "index", {"data"}) -- just a single player updateTable({getRandomPlayer()}, "index", {"data"}) -- just a single player Keep in mind that when testing this code, it is important to mind "when/timing?" + "triggerClientEvent/communication". As in this example the client hasn't loaded it's scripts yet. Adjust it to your needs. @majqq
  20. Yes, I can't explain it better than this: Client (see my example) Trigger: When vehicle damage Condition: You must be the syncer of the vehicle. Actions: - Save updates for the table. (Not a new version of the main table) - Start the buffer timer. 200ms?(if not running already) In case of firedamage or a minigun you will be preventing a trigger event that is send every frame. --------------- Trigger: When the buffer timer is finished. Action: Send the table updates to the server. _______________ _______________ _______________ Server Trigger: When there is an update from the client. Condition: If a player is closer to the vehicle than 300+ units, do action 1 for him. Else do action 2 for him. Action 1: Send a (latent) trigger event to the selected person. Action 2: Save this message in a table. Start a personal buffer timer for him. This table could contain similar types of updates from different vehicles. The data should contain is a reference to the player and to the vehicle. Which you can use to pick the right and latest update for the player. (Also here start the buffer timer only when it is not running for the selected person) -------------- Trigger: When the personal buffer timer is finished.(action 2) Action: Send the table new table to the client.
  21. It will hurt the sender a bit. But only if he or she has terrible internet. And you can always increase the buffer/delay time. (Remember to test the latent version for your target group) When you are going to send information back it will also hurt the receiver without doubts. But you can use an even bigger delay for players that are far away. So only the players that are closeby should actually receive data immediately. On the other hand elementdata could save you some data for closeby players. The usage require less data, but the target players are not control able. So if there are 500 players in your server, then I do not recommended it. You should test both ways. It is a paradox I know... Why not set elementdata clientside? Because players will overwrite the data from each other. It is something the server should manage. Who is your target group by the way? @majqq
  22. - With parameters I mean the arguments you want to use there. - There are no shared tables. I recommend to first try to use the clean way. Sync with triggerEvents, so that you do not destroy other players their network usage directly. (of course this can still happen) Buffer up to at least 200ms. Check if latent events are fast enough for your target group. If your players have bad internet, then it might be possible that the information never gets send... Latent events will only send information when the network isn't blocked. This means that position and orientation of players should be more accurate while sending information. Element data usage will increase when the player count increases, so test it before you use that type instead. Untested code local damageToSync = {} local syncVehicleDamageTimer local function syncVehicleDamage () syncVehicleDamageTimer = nil -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- triggerServerEvent("syncVehicleDamage", resourceRoot, damageToSync) -- -- or -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- triggerLatentServerEvent("syncVehicleDamage", resourceRoot, damageToSync) -- It will improve the gameplay. >>> BUT this will work ONLY fine if your target players have fast internet. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- damageToSync = {} -- reset table end addEventHandler("onClientVehicleDamage", root, function (attacker, weapon, loss) if isElementSyncer(source) and attacker and getElementType(attacker) == "player" and loss > 0 then -- register vehicle local vehicleDamageTable = damageToSync[source] if not vehicleDamageTable then vehicleDamageTable = {} damageToSync[source] = vehicleDamageTable end -- register attacker + loss of vehicle vehicleDamageTable[attacker] = (vehicleDamageTable[attacker] or 0) + loss -- start sync delay if not syncVehicleDamageTimer then syncVehicleDamageTimer = setTimer(syncVehicleDamage, 200, 1) end end end) The table structure. --[[ -- table structure -- local damageToSync = { [vehicle] = { [attacker] = loss, [attacker] = loss } [vehicle] = { [attacker] = loss, [attacker] = loss } } ]]
  23. Oke, Is there more to it? Because this is not enough to pick the right method. For example: Response time? Delay in between? Network bandwidth limit? Parameters? Is it used for visuals only or has it also influence on gameplay directly? Which players do need to receive this information immediately? Which ones later? (Which ones not? > Players that join later or that are far away.)
  24. @majqq The answer to that depends for 95% on what your endpoint needs. Enough context is essential for coding with responsibility.
  25. 6000x6000 https://wiki.multitheftauto.com/wiki/GetPlayerMapBoundingBox
×
×
  • Create New...