Addon Development Prerequisites and Setup - meldavy/ipf-documentation GitHub Wiki

Setting up your development environment

  1. Install an IDE. I recommend VSCode for lightweight IDE, or IntelliJ for full featured IDE.
  2. Check out the tos-ipf repository through git. Both of these IDEs have built in VCS integration. The tos-ipf repository contains a dump of kTest server lua and xml files, as well as tools to dump your own. This is where you will find code usages and examples of first-party code. Addon developers do not have good documentation to work with. Thus the best tool we have in our disposal is to search through IMC codebase, which is why I always recommend you to have a ipf dump checked out in your IDE.
  3. Install Addon Manager and then install the Developer Console addon through the manager.
  4. Install patched IPFSuite from Tos Dev Community discord.
  5. Create addon_d directory under /Nexon/TreeOfSavior/data

Addon Template

Check out the following package and follow the instructions in the README for a quick addon development setup.

https://github.com/meldavy/tos-addons/tree/main/template

For those who want to be bit more hands on with the initial process, follow the following procedure instead of using the the template:

Start developing and testing the addon

  1. Follow the HelloWorld wiki to create a xml and lua file.
  2. As good convention, replace the xml content with my recommended starting xml template.
  3. Make sure that name attribute of the <uiframe/> element is all lowercase, and matches the filename of the xml and lua file. (This is just basic convention)
  4. Open IPFSuite and follow:
    1. Click on New
    2. New Container
    3. addon_d.ipf
    4. OK
    5. Expand (+ button) New IPF in the tree explorer and select addon_d.ipf container
    6. Add Folder
    7. use same name as step 3
    8. select the folder in tree explorer (IMPORTANT!)
    9. Add
    10. Select lua file
    11. Add
    12. Select xml file
    13. Save
  5. Rename saved ipf file to match the following convention: _<addonname>-📖-v2.0.1.ipf and place it in /Nexon/TreeOfSavior/data
    1. obviously replace <addonname> with actual lowercase addonname from step 3
  6. Copy the lua file created in step 2 and put it in /Nexon/TreeOfSavior/data/addon_d/<addonname>/ directory
    1. obviously replace <addonname> with actual lowercase addonname from step 3
  7. Launch game, type in /dev in chat to open developer console, and type in dofile("../data/addon_d/<addonname>/<addonname>.lua");
    1. obviously replace <addonname> with actual lowercase addonname from step 3

image

image

So what have we done here?

Firstly, for our addon to load, the game needs to load the xml file first. The game uses the xml file's name and name attribute of <uiframe/> to initialize addons that match the same name. Note that addons use UPPERCASENAME_ON_INIT() convention when declaring the initializer, which is how the game locates addons.

Thus for an addon to load, the xml needs to load as a prerequisite.

However, the only known way for the game to load an addon xml file is to load a fully packaged ipf. Thus by following the above steps, we packaged a very simple lua file and xml file into an encrypted ipf, and by putting it in the data directory, let the game load it.

And now that the game has loaded the xml file, we can use the DeveloperConsole addon's dofile() to re-load lua files on the fly.

To test:

  1. Open /data/addon_d/<addonname>/<addonname>.lua file in your IDE
  2. Modify ON_INIT to print a random string (such as print("Hi"))
  3. Run the dofile() command above to reload the edited lua script
  4. Move your character to a new map and type /dev to open Developer Console
  5. Check to see new printed line in dev console

Some notes

  • All lua files are "re-initialized" on map transition. Basically every time you see a loading screen in the game, the lua file "ON_INIT" is called.
  • When reinitialized, local variables that are declared outside of a function scope are not wiped. Behavior may vary but usually is persisted until the client is closed.
  • print statements on ON_INIT may not be visible in developer console when going to Barrack (character select) and selecting a character. I think this has to do with loading order or other race condition. But this is not a bug and can be misleading when debugging initialization issues. Thus when you want to reload a new revision of your lua script, run dofile() and then move to an adjacent map to properly reload the code.
  • As a general rule of thumb, always change map (or go to character select and re-enter) after a dofile()
⚠️ **GitHub.com Fallback** ⚠️