How to extend standard functionallity

Discussion in 'Programming' started by snoutie, Mar 6, 2025.

  1. snoutie

    snoutie
    Expand Collapse

    Joined:
    Dec 3, 2021
    Messages:
    43
    What is the recommended way to extend standard functionality provided by the base game?

    There are some missing features in the base lua code which I want to fix / extend upon, however I was not able to figure out a clean way to do so.

    Sometimes you can hook into events which is great, but not all functions seem to have events.
    Sometimes it is possible to straight up overwrite exported functions, and then call the original function after, but this only works if the exported function also gets called via the modules object (M.doThis()) inside the module.

    But not all functions are modifiable by this.

    Is there a clever way to modify a function, e.g. career_modules_inventory.openMenuFromComputer() without breaking compatibility with other mods that also modify this function?
     
  2. r3eckon

    r3eckon
    Expand Collapse

    Joined:
    Jun 15, 2013
    Messages:
    655
    Modifying a function so that it works both for your usage and is still compatible with the standard game is doable and often necessary when making mods. However doing the same thing for potentially all mods that might modify that same function probably isn't possible to achieve automatically. You can manually check other mods and write a function that implements everything needed for all uses to work. But doing so automatically is much harder if not impossible. I mean how would that even work? How would the game decide what version of that function to use, or what lines to merge from each version into a single function that just works even if different versions potentially do things that aren't compatible with other versions?

    This "merging" problem doesn't only apply to script mods. The game doesn't have a way to merge map edits. If you have multiple mods that modify level files, they will interfere with one another, because the items.level.json files that point to level edits inevitably get overwritten by other mods. In such a situation, whatever mod ends up loading last will be the only mod that's working properly. Note that mod loading order is alphabetical, starting with the root mods folder, then mods/repo and finally mods/unpacked.

    Setting aside that problem, to modify functions that aren't attached to the module your only option is to duplicate the script into the userfolder at the same relative location as it resides in the game folder and modify that version however you want. As with everything in the userfolder (including the contents of zipped mods), it will take priority over the original script in the game folder. So you can make any modification you want and technically haven't modified the actual original script. Keep in mind I don't think such a mod is going to be allowed on the repo because even though the original script is intact the game technically sees a modified version of a vanilla script.

    In one instance I needed to keep an entire older version of a script and use it with my mod. In this case it was the drift scoring script, because I made a ton of drift challenges and didn't want to update the target score for the new scoring system. So I copied the old version of that script and renamed it, then whenever my mod is running I overload the original extension with this old version, making sure to reload the new version whenever the mod stops running so freeroam drift and scenarios work properly. I did have to make slight modifications to the old script so that other vanilla drift scripts didn't error out due to missing data or functions from the old script.

    Long story short, your best bet is to manually check other mods and write a function that implements everything needed for all mods and the base game to work as intended.
     
    • Like Like x 1
  3. snoutie

    snoutie
    Expand Collapse

    Joined:
    Dec 3, 2021
    Messages:
    43
    Thanks for your explanation, that confirms my worries.

    Do you happen to know what happens when two separate mods do this with the same file?
    Does the mod whose files get loaded last get the right to overwrite?

    How exactly does the loading work? Let's say I have mod A and mod B, both replace the file that contains the funtction do_sth()
    Now when mod B gets loaded, mod A should have already modified the file and therefore the function.
    Can mod B figure out that this has happened? (Getting filepath of the module for function do_sth() for example?)
    OR
    Does mod B get the exclusive rights to overwrite the file, because B comes after A and the changes A tries to do are never applied at all?
     
  4. r3eckon

    r3eckon
    Expand Collapse

    Joined:
    Jun 15, 2013
    Messages:
    655
    So to answer your questions I should explain the concept of virtual filesystem BeamNG uses. Your game has files that can reside in the install folder or the userfolder. You have vanilla stuff in the install folder (ex: vanilla car configs) and custom user content in the userfolder (ex: custom car configs). But as far as the game is concerned, these aren't different folders. Both folders are "merged" into a single virtual filesystem that the game can access and edit.

    The userfolder is loaded last so if you have two files in the same relative location in both folders, the userfolder version is the one the game will see. The other file may as well not exist to the virtual filesystem. It would only be loaded if you delete the userfolder version or if you launch in safe mode. There's no fancy function detection or any other system that checks the contents of files that exist in both folders. Whatever file is loaded last is the one the game will see. It's that simple. This behavior applies to all files including level files, scripts, car configs, jbeam files, ui scripts, etc.

    The one "special" case is zip files. If you open zip files (such as mods or vanilla vehicle zips) you'll notice a folder structure that matches the relative location of files that are directly in the userfolder or game folder. For instance vehicles zips (both vanilla and mods) contain some configs (.pc files) that in the zip are stored under a path that goes
    Code:
    zip root/vehicles/MODEL/config.pc
    Meanwhile if you saved a custom config for this vehicle it would be stored in
    Code:
    userfolder root/vehicles/MODEL/config.pc
    As far as the virtual filesystem is concerned, both configs are stored in the same folder. So basically zip files are "extracted" into the root of the virtual filesystem when the game loads. For zip files the mod loading order I explained in my previous post applies and that's what controls what version of duplicate files will end up getting loaded. The last mod to get loaded will have priority and whatever files it contain will be the versions the game can see.
     
    #4 r3eckon, Mar 10, 2025
    Last edited: Mar 10, 2025
    • Like Like x 1
  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