WIP superUsefulUtilities mod

Discussion in 'Utilities and programming' started by _N_S_, Aug 25, 2023.

  1. _N_S_

    _N_S_
    Expand Collapse

    Joined:
    Oct 28, 2017
    Messages:
    73
    While working on an update for my "Cheat Panel" mod, I needed to create easy to use and universal functions/modules that could work in VLUA and GE.
    For example, a "setTimeout" module that could call a function "added" to it after a certain time has passed, as implemented in JavaScript.

    However, the number of modules quickly increased, and I decided to separate them into a separate mod, which could then be used in future projects not only by me, but also by everyone.

    The idea is very simple - to add superUsefulUtilities (hereinafter - sUU) to your mod, it will be enough to write one line at the beginning of the script file:
    Code:
    if not readFile"sUU"then obj:queueGameEngineLua[[local i,m,s,k,v,t,f="SUU mod id from the repository (not yet known)",core_modmanager,settings,"onlineFeatures","enable",0,""if(m.getModNameFromID(i))then m.activateModId(i)else f = function()if(s.getValue(k)~=v)then s.setValue(k,v)end;if Engine.Online.isAuthenticated()then core_repository.modSubscribe(i)elseif t<25 then t=t+1 getmetatable(newproxy(true)).__gc=f;end;end;f()end]]return{}end
    
    Code:
    if not readFile"sUU"then local i,m,s,k,v,t,f="SUU mod id from the repository (not yet known)",core_modmanager,settings,"onlineFeatures","enable",0,""if(m.getModNameFromID(i))then m.activateModId(i)else f = function()if(s.getValue(k)~=v)then s.setValue(k,v)end;if Engine.Online.isAuthenticated()then core_repository.modSubscribe(i)elseif t<25 then t=t+1 getmetatable(newproxy(true)).__gc=f;end;end;f()end;return{}end
    

    Code:
    if not readFile("sUU") then
        obj:queueGameEngineLua([[
            local id = "SUU mod id from the repository (not yet known)"
    
            if core_modmanager.getModNameFromID(id) then
                core_modmanager.activateModId(id)
            else
                local tryCount = 1
                local MAX_TRY_COUNT = 25
     
                local function installationTry()
                    if settings.getValue("onlineFeatures") ~= "enable" then
                        settings.setValue("onlineFeatures", "enable")
                    end
     
                    if Engine.Online.isAuthenticated() and core_modmanager.isReady() then
                        core_repository.modSubscribe(id)
                    elseif tryCount < MAX_TRY_COUNT then
                        tryCount = tryCount + 1
     
                        getmetatable(newproxy(true)).__gc = installationTry
                    end
                end
     
                installationTry()
            end
        ]])
    
        return {}
    end
    
    Code:
    if not readFile("sUU") then
        local id = "SUU mod id from the repository (not yet known)"
    
        if core_modmanager.getModNameFromID(id) then
            core_modmanager.activateModId(id)
        else
            local tryCount = 1
            local MAX_TRY_COUNT = 25
    
            local function installationTry()
                if settings.getValue("onlineFeatures") ~= "enable" then
                    settings.setValue("onlineFeatures", "enable")
                end
    
                if Engine.Online.isAuthenticated() and core_modmanager.isReady() then
                    core_repository.modSubscribe(id)
                elseif tryCount < MAX_TRY_COUNT then
                    tryCount = tryCount + 1
    
                    getmetatable(newproxy(true)).__gc = installationTry
                end
            end
    
            installationTry()
        end
    
        return {}
    end
    

    Example of including:
    example.png

    If the mod is found - ok, if not - it will be installed. After installation, it will automatically reload GE and VLUA, so your newly loaded mod will be able to use modules from sUU.


    On July 19, 2022, the first module, setTimeout, was written. For more than a year I worked on the update for the "Сheat Panel" and in parallel created modules for sUU. Mostly, of course, the work was done on sUU. And now, on August 25, 2023 I can say that sUU is finished.

    Currently, 34.5 modules are completed:
    1. trunc

    2. numberToBool
    3. boolToNumber

    4. tableContainsKey
    5. tableContainsKeySafe
    6. tableContainsKeyCaseInsensitive

    7. tableFindKey
    8. tableFindKeyCaseInsensitive

    9. tableGetElementSafe
    10. tableContainsElement
    11. tableContainsElementCaseInsensitive

    12. tableCopy
    13. mergeTables

    14. getModByTagId
    15. getModTagIdByTagLine

    16. disableDefaultAutoUpdate
    17. checkUpdate
    18. updateMod
    19. autoUpdate
    20. requireMod

    21. installModule
    22. onUpdate
    23. onUiReady
    24. setTimeout
    25. skipIterations
    26. setInterval

    27. createBackgroundTask

    28. wrap

    29. registerKeyDownCallback
    30. registerKeyHoldCallback
    31. registerKeyUpCallback

    32. getVehRotation
    33. getTimeMS

    34. simpleToastr
    functionsStore.

    Module Description:
    1. trunc - trunc function truncates the fractional part.
      1.png
    2. numberToBool - numberToBool function converts numbers to boolean values.
      2.png
    3. boolToNumber - boolToNumber function converts boolean values to numbers.
      3.png
    4. tableContainsKey - tableContainsKey function returns true if the table contains a key, and false if no key is found.
      4.png
    5. tableContainsKeySafe - tableContainsKeySafe function returns true if the table contains a key, and false if no key is found.
      tableContainsKeySafe function allows you to check the contains key without calling meta-methods.
      It does not differ from rawget, but you can pass it (nil,nil) and it will not cause an error, unlike rawget.
      5.png
    6. tableContainsKeyCaseInsensitive - tableContainsKeyCaseInsensitive function returns true if the table contains a key, and false if no key is found.
      Case insensitive.
      6.png
    7. tableFindKey - tableFindKey function searches key by value.
      7.png
    8. tableFindKeyCaseInsensitive - tableFindKeyCaseInsensitive function searches key by value.
      Case insensitive.
      8.png
    9. tableGetElementSafe - tableGetElementSafe function allows you to get a value without calling meta-methods.
      It does not differ from rawget, but you can pass it (nil,nil) and it will not cause an error, unlike rawget.
      9.png
    10. tableContainsElement - tableContainsElement function returns true if the table contains an element, and false if the element is not found.
      10.png
    11. tableContainsElementCaseInsensitive - tableContainsElementCaseInsensitive function returns true if the table contains an element, and false if the element is not found.
      Case insensitive.
      11.png
    12. tableCopy - tableCopy function performs a deep copy of the table. Supports filters.
      12.png
    13. mergeTables - mergeTables function merges tables.
      Supports filters.
      13.png
    14. getModByTagId - getModByTagId function will return information about the mod by tagid.
      The mod must be installed in the mods folder.
      14.png
    15. getModTagIdByTagLine - getModTagIdByTagLine function will return the tagId of the mod by tagLine.
      The mod must be installed in the mods folder.
      15.png
    16. disableDefaultAutoUpdate - disableDefaultAutoUpdate function disables vanilla auto-updates for mods with a tagId.
      This means that the only way to update the mod would be to use the functions: autoUpdate or updateMod.
      16.png
    17. checkUpdate - checkUpdate function checks for updates on a mod by tagId.
      You can use tagLine when you don't know the tagId, for example, when you upload a mod to the repository.
      But after loading it is necessary to specify the tagId.
      17.png
    18. updateMod - updateMod function will update the mod with the tagId.
      If the mod was not found, it will be installed.
      18.png
    19. autoUpdate - autoUpdate function will automatically update the mod by tagId when updates are released on it.
      You can use tagLine when you don't know the tagId, for example, when you upload a mod to the repository.
      But after loading it is necessary to specify the tagId.
      19.png
    20. requireMod - requireMod function will install the mod with tagId if it was not found, or add it to autoUpdate if it was.
      20.png
    21. installModule - installModule function installs modules.
      21.png
    22. onUpdate - onUpdate function adds functions to the list of functions that will be called on each iteration of onUpdate(GE) or updateGFX(VLUA).
      To remove a function from onUpdate you need to write in that function - onUpdate:clear().
      22.png
    23. onUiReady - The onUiReady function adds functions to the list that will be called each time the interface is updated.
      For example - when the user presses F5.
      To remove a function from onUiReady you need to write in that function - onUiReady:clear().
      23.png
    24. setTimeout - setTimeout function adds the function to waiting and it will be called after the specified time has passed.
      24.png
    25. skipIterations - skipIterations function adds a function to the waiting and it will be called after the specified number of iterations onUpdate(GE) or updateGFX(VLUA).
      25.png
    26. setInterval - function added to setInterval will be called with the specified periodicity.
      To remove a function from setInterval you need to write in that function - setInterval:clear().
      26.png
    27. createBackgroundTask - createBackgroundTask function is needed to create asynchronous, background functions, for example, with the loop of a large array without lags.
      Yes, the idea is taken from extensions.core_jobsystem, but I think it's a little simpler.
      You can use the "wrap" module to create a wrap.
      27.png
    28. wrap - wrap function will create a wrapper over the function, and when it is called, the original function with the arguments passed to it will be called as well.
      28.png
    29. registerKeyDownCallback - registerKeyDownCallback function adds your function to a list that will "listen" for key presses.
      29.png
    30. registerKeyHoldCallback - registerKeyHoldCallback function adds your function to a list that will "listen" for key holds.
      30.png
    31. registerKeyUpCallback - registerKeyUpCallback function adds your function to the list that will "listen" for key releases.
      31.png
    32. getVehRotation - getVehRotation function returns the rotation vector(X, Y, Z) in degrees.
      getVehRotation function can also calculate the rotation for the vehicle passed in the argument, e.g. obj for VLUA and be:getPlayerVehicle(0)(or or any other) for GE.
      32.png
    33. getTimeMS - getTimeMS function returns the current time in ms.
      33.png
    34. simpleToastr - The difference with guihooks.trigger("toastrMsg", ...) is that my module allows the use of lua functions.
      simpleToastr can be used for example to display a recommendation to install an optional mod (e.g. an add-on).
      341.png 342.png 343.png 344.png


    All modules can be used in both VLUA and GE.
    All modules(except 34.5) are "safe" to use. Memory leaks are excluded. If a function has been stored somewhere, it will be removed when it is no more needed.
    For example, if a module was called from VLUA that needs to register a callback function in GE, then after reloading or removing the vehicle, the "bound" function in GE will be removed.
    The same is true in the opposite direction, if the GE is restarted, the function required for it in VLUA will be removed.

    If you find any error, write about it, I'll try to fix it as soon as possible.


    Also, all modules (except obviously getVehRotation) can work even if they are loaded before the main GE or VLUA systems. For example, even before "luaCore".
    ge.png vlua.png
    I will not tell you how to do it, who really need it will understand himself, but just say that in order to make the mod sUU work at this stage, you need to write the following:
    Code:
    FS:mountList((function()
        local modName = "superusefulutilities"
        local path = "/mods/unpacked/" .. modName .. "/"
    
        if not FS:directoryExists(path) then
            local mods = FS:findFiles( "/mods/", "*.zip", -1, false, false )
    
            for _, modPath in pairs(mods) do
                if modPath:match(modName) then
                    path = modPath
                    break
                end
            end
        end
    
        return {{srcPath = path}}
    end)())
    Nothing needs to be done, everything will work as it is.



    Answers to some questions:
    Will the mod be paid - NO.
    Will the mod be in the repository - YES.
    Can it be used in your own mods - YES.
    Can you COPY files/code from the mod - NO.
    Copying files/code is not allowed and is not recommended as the integration is very simple.(see above).
    In addition, the mod will be updated and fixes/optimizations are possible.

    P.S. In general, the mod is intended for "programmers" only, and for solving specific problems/issues I've encountered myself.
    P.S.2 a little later I will add an option to support me.
     
    #1 _N_S_, Aug 25, 2023
    Last edited: Aug 28, 2023
    • Like Like x 9
  2. Derpitron

    Derpitron
    Expand Collapse

    Joined:
    Jun 25, 2017
    Messages:
    252
    NPM but for beamng lua libraries? Sign me up!

    Could you make a Git repository?
     
  3. _N_S_

    _N_S_
    Expand Collapse

    Joined:
    Oct 28, 2017
    Messages:
    73
    Not really, all modules come in 1 mod (weight - 95 kb).
    According to the idea, by writing only 1 line, all of them become available for use.
    User installs your mod->First run installs sUU->Automatic reload lua->Everything works.
    I would not want to separate them, as they use each other.
    And, as I wrote in the post, mod integrity and not allowing copying ensures operability, avoids conflicts, outdates and, as a result, increases stability.
    Also, there is no need to manually update modules (as opposed to copying individual modules into the mod).

    About git, yes, I will do it. (but a little later, I'll release the mod first)
     
    • Agree Agree x 1
  4. Derpitron

    Derpitron
    Expand Collapse

    Joined:
    Jun 25, 2017
    Messages:
    252
    I meant "npm" more in the sense that this mod could potentially lead to a new type of mod: lua code libraries, becoming popular. But I do see the logic in your decisions
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice