libsota - a helper library in lua for Shroud in lua.

Discussion in 'Lua Discussions' started by CatweazleX, Nov 14, 2019.

  1. Archer

    Archer Avatar

    Messages:
    238
    Likes Received:
    165
    Trophy Points:
    18
    Location:
    UK, EU, Terra
    I'm seeing an error on QA:

    chunik_1:(377,4-128): attempt to index a number value.

    I'm trying to do your version of Atos' example using buttons.
     
    Last edited: Dec 5, 2019
  2. Browncoat Jayson

    Browncoat Jayson Legend of the Hearth

    Messages:
    6,259
    Likes Received:
    13,936
    Trophy Points:
    153
    Would it be possible to use a single .lua file in the main folder, that just has include lines to load files from subdirectories? Then turning mods on and off would just mean commenting out the include line.
     
  3. Archer

    Archer Avatar

    Messages:
    238
    Likes Received:
    165
    Trophy Points:
    18
    Location:
    UK, EU, Terra
    Until Chris exposes the functionality to do that, it's not a simple task.
     
  4. Browncoat Jayson

    Browncoat Jayson Legend of the Hearth

    Messages:
    6,259
    Likes Received:
    13,936
    Trophy Points:
    153
    My bad, I was thinking Lua had built in functionality to do file loading. I'll send in a wishlist.
     
  5. Tirrag

    Tirrag Avatar

    Messages:
    164
    Likes Received:
    265
    Trophy Points:
    18
    Location:
    Iowa, US
    @devilcult has a working solution for requiring lua files from subdirectories posted in the discord lua sota channel.
     
  6. Archer

    Archer Avatar

    Messages:
    238
    Likes Received:
    165
    Trophy Points:
    18
    Location:
    UK, EU, Terra
    I've seen that, but as mentioned above, it's not as simple as just includes/requires. May be @CatweazleX could add the functionality to libsota.

    Once the functionality of `require` is exposed, using a single Lua file to add modules would be simple and very useful for addon management.
     
  7. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    I do not have discord, if someone can post @devilcult solution here i can have a look at it.
     
  8. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    this happend when the image you want to use is not there. Eg. you do not have "test.png" in your Lua folder. In this case ui.texture.add returns -1 not a valid texture object.
     
  9. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    Download:
    libsota.0.4.7 and libsota.util.0.4

    If guiButton is used with a invalid texture object it will now give you a error message on the console. ui.guiButton.add will return nil in this case. ShroudButton does not draw a button without a texture.
    ui.texture.add will now return nil instead of the return code from ShroudLoadTexture in the case a texture can not be loaded

    ui.timer - improved the handling of userdata. ui.SetInterval and ui.SetTimout can now also be used with userdata
    ui.onConsoleLog, ui.onConsoleCommand and command invokation - now uses a faster queue

    fixed: client.isHitching may not return to false

    libsota.0.4.6 and the patch file are found in the folder archive

    ---- libsota.util

    cleaned up the code and added functions for textures

    \info stat - will now search in stat.name and stat.description when no stat with the given name is found
    \info inventory - added. Shows the players inventory on the console

    \info player - does not show player.inventory. that may are a lot of entries, so i decided to hide this. Replacement is \info inventory. The players inventory is still accessed through player.inventory

    --- libsota.ui

    add a dev folder with libsota.0.5.d, libsota.util and libsota.ui
    i do not progress as fast as i want with it. The folder is only there to show something is done.

    The current concept is, that a application object needs to be created. All ui objects then are created trough the application object. (in the one or other way).
    The composing of the add-on is done in app.onActivate(). Freeing objects in app.onDeactivate().
    This allows to activate and deactivate a application/add-on. Ui objects are freed through the api.
    Players should have the ability to de- and activate a add-on as they like. Hence the onActivate and onDeactivate events.

    a command will be added \shell <appname> activate and \shell <appname> deactivate (or load / unload). May also a menu in the upper right area to allow this by clicking a menu entry.

    uitest.lua shows what is currently working.
    Linux users have to add a symlink in <datafolder> named "Lua\share" that points to Lua/share/
    (The bug with the backslash is still present in QA 896)

    --- licence
    added LGPL licence to all libsota files
     
    Last edited: Dec 6, 2019
    Browncoat Jayson likes this.
  10. devilcult

    devilcult Avatar

    Messages:
    1,096
    Likes Received:
    2,289
    Trophy Points:
    113
    Code:
    local modulesPath = "\\yourmodulename\\modules\\"
    function doRequire(filename)
        local _modulesPath = ShroudLuaPath .. modulesPath
        local file = io.open(_modulesPath .. filename .. ".lua")
        local data = file:read("*all")
        file:close()
        _G[filename] = assert(loadsafe(data))
    end
     
    Drake Aedus, Anpu and CatweazleX like this.
  11. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    Download:
    libsota.0.4.8 and libsota.util.0.4

    added ui.module

    ui.module.add(modulename, prefix) - loads a module from file and returns the compiled version of it. if prefix is given the module will be added to the global namespace
    ui.module.get(modulename) - returns the compiled version from the module, nil if it does not exists
    ui.module.remove(modulename) - removes a modules
    ui.module.invoke(modulename, function, ...) - calls a function within the module code with parameters given (...). If function is omitted the module is called as a function.

    --- libsota.util
    load - points to loadsafe
    loadstring - points to loadsafe
    loadfile - points to ui.module.add. (loadfile mimics loadfile from LUA)
    dofile(filename) - loads a file and runs it. Returns the result (mimics dofile from LUA)
    require(modulename, ignoreErrors) - loads a file and runs it. (mimics require from LUA)
    include(modulename) - loads a file and runs it, but ignore errors. Like require but script(s) are not stopped in case of an error
    module - loads a file and adds it to the global namespace (this does not! work like module from LUA)

    ----

    Modules are searched in lib/, share/, bin/ and include/ within the <ShroudLuaPath>. When not found an error message is shown on the console. Modulenames can be given as "mod\\filename", "mod/filename.lua", "mod.filename", etc. The final modulename is always divided with dots without the lua extension. So, ui.module.add("mod\\filename.lua") will result in this modulename: mod.filename. All ui.module functions accept any of \, / or . as divider. ui.module.add("mod.filename.lua") will also load the file when it exists.
    ui.module caches loaded files, so they are only loaded once (and compiled once).

    ui.module.get or ui.module.add can be used to assign the module to a variable:
    local mod = ui.module.add(mod.locals) - loads the module mod/locals.lua and assign it to the local variable mod. If the module is a function, the function can be called with mod().
    mod = ui.module.add(mod.globlas) - loads the module and assign it to the global variable mod. All scripts can access the module with mod() or mod.index (depending of if it is a table or a function)

    ui.module.add also supports a prefix. If a prefix is given the module code is added to the global namespace with the name prefix. If the prefix contain dots (or / or \\) a table is created with the deepest element as the module code.
    ui.module.add("mod/subdir/filename.ext", "mod") - loads the module and adds its code as mod in the global namespace. The code is access able from all scripts via mod()
    ui.module.add("mod/subdir/filename.ext", "mod.globals") - loads the module and adds its code to the table mod as the index globals. The code is access able for all scripts via mod.globals()
    ui.module.add("mod/subdir/filename.ext", "mod.special") - loads the module and adds its code to the table mod as index special. If the line before was also used both modules are in the table mod and access able via mod.globals() and mod.special()

    mytable = {
    x = somevalue,
    y = somefunction(),
    }
    ui.module.add("filename.ext", "mytable.z") - loads the module code into the table mytable as z. So, one can do mytable.y() or mytable.z()
    Another way is:
    mytable = {
    x = somevalue,
    y = somefunction(),
    z = ui.module.add("filename.ext")
    }

    The prefix can also be true or "". In this case the modulename is used as prefix.

    ui.module.remove(modulname) - removes the module from memory. and from all prefixes that where used with this module. It cannot remove modules that are assigned to a variable. Like local myvar = ui.module.add or myvar = ui.module.add.

    ui.module.invoke(modulename, function, ...) - calls the module code, even it is neither assigned to a variable or to a prefix.
    ui.module.get(modulename) - may be used to assign the module code to a variable at a later time. might it be a local or global variable.

    loadsafe works similar to load from LUA 5.3 but is compatible to loadstring from LUA 5.2. loadsafe does not use the global env as its default, like the LUA functions
    loadfile loads a file and returns its code. ui.module.add is similar to this (when prefix is not used)
    dofile - loads a file and runs it. Returns the result. The same is in LUA
    require - loads a file and runs it. (no return). The same as in LUA. If the file can not be loaded all scripts are halted and a errormessage is shown on the console. It also do not run code more then once.
    include - calls require with ignoreError = true. No errors are shown (except the ones coming from ui.module.add). Scripts are not halted in the case of an error.
    module - calls ui.module.add with prefix = true. The module is added to the global namespace with its name.


    All of this needs some testing. Feedback is welcome.
     
    Last edited: Dec 6, 2019
    Browncoat Jayson, Anpu and Tirrag like this.
  12. Tirrag

    Tirrag Avatar

    Messages:
    164
    Likes Received:
    265
    Trophy Points:
    18
    Location:
    Iowa, US
    @CatweazleX thank you for the update! i was hoping to get your opinion on the window system. i am done with my planning for my next mod and was about to begin but it is dependent upon windows. should i hold off a while longer or do you feel it is safe to move forward.
     
  13. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    Hm. The libsota.ui will come. There is a dev version in the dev folder. There is also a uitest.lua. you can look into.
    With this early version you can create a window and add images (ShroudTexture) and text (ShroudLabel) to the window. A window title can be set and a background. The windows are move able with the mouse. Also mouse events are send to the window in client coordinates.
    Today i was doing the ui.module stuff. I'll try to work on libsota.ui this weekend.

    You can test the dev version and play a little with it. And/or wait until the first production ready version is available.
     
  14. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    Thanks for the code. And the info that the io functions are now active, including loadsafe. I expanded your code a little and added it to the library.
     
  15. devilcult

    devilcult Avatar

    Messages:
    1,096
    Likes Received:
    2,289
    Trophy Points:
    113
    one major thing though, _G will set the mod to global, all other will be able to use it, having multiple library with same name and modified function might cause an error.
     
  16. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    That is why you have to give a prefix. Without the mod is not added to the global namespace _G. dofile, require will not add the mod to the global namespace but execute/run it, like LUA does it. You can look at the code, you will see.
     
  17. Archer

    Archer Avatar

    Messages:
    238
    Likes Received:
    165
    Trophy Points:
    18
    Location:
    UK, EU, Terra
    That could only be the 'error.png' file, which does exist in the LuaPath directory. File permissions look good, so I have no idea why it "does not exist".
     
  18. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    libsota.0.4.7 and above does not throw "trying to index a number value" anymore, so you should see on the console "ui.texture: Unable to load texture with filename '<filename>'".
    Absolute path does not work you need to use relative path. (eg. ShroudLuaPath../<filename> does not work, but <filename>). (see also post #53 - #55)
    I should handle this, if the filename starts with ShroudLuaPath.
     
  19. Archer

    Archer Avatar

    Messages:
    238
    Likes Received:
    165
    Trophy Points:
    18
    Location:
    UK, EU, Terra
    Can you explain what you mean by this? https://www.lua.org/manual/5.2/manual.html#2.2 gives me the impression that _G is initiated with the global environment, but after that it is unconnected (never updated by Lua). I ask because I would like to put libsota into the global environment so I don't have to repeat it in multiple scripts ;-)
     
    Last edited: Dec 6, 2019
  20. CatweazleX

    CatweazleX Avatar

    Messages:
    643
    Likes Received:
    760
    Trophy Points:
    93
    Location:
    Veritas Sanctuary
    Just drop libsota and libsota.util in the ShroudLuaPath (no subfolder), it should be loaded and executed by Shroud and the objects are globally access able. But you have to wait on ShroudOnStart, that indicates that all scripts are loaded.