API Improvements & Suggestions Thread

Auti0Auti0 REGISTERED Posts: 277
edited April 2015 in Mods
Hey there. After talking around I've realized we don't have a dedicated place for people to request new features or improvements of the Eternus Lua API.

So please, throw your use-cases and requests at us. Let us know what you need from us to be able to create/improve your mod.

Please try to be as specific as possible.

Btw, in case you missed it we recently updated the documentation to be current with the 0.6.4 release. Documentation

Comments

  • SigilSigil REGISTERED, Developers Posts: 678 Developer
    I haven't had that much use or interaction with Modding APIs, but for someone unfamiliar with mods I'd imagine being able to install a mod from in-game menu would be ideal. Especially if it allowed you to find the files anywhere, including desktop and make a copy of them. Finding the specific mod folders seems to be a stopping point for a lot of beginners.

    On a side note I'd think mods and servers would be important. For example I've seen some games list the number of mods they each have, and download them when joining. being able to see a list and file sizes of those mods would also be very useful.
  • ZakeZake REGISTERED Posts: 216 Seed
    I'm intrigued by what Sigil implied, do I see the idea of auto-downloading of mods upon joining a server? That would certainly be convenient for the average user. So I'm guessing right before joining a server you'd see the mod list they're currently using.
    I think more than I say and say more than I do, but I do more than I used to and plan to continue.
    TUG modder (at least in the ounce of free time that occasionally flits by)
  • Youngy798Youngy798 REGISTERED Posts: 905 Seed
    In gmod when you join a server it automatically downloads and adds all the addons you need, its really simple to add addons aswell.
    Hello there! I am Youngy future owner of Plainhold (hopefully), go read the topic about Plainhold, and the Lemurian Empire, maybe also some of my other posts, like my mining suggestions! :)

    Bye!
  • ZakeZake REGISTERED Posts: 216 Seed
    This idea also solves my biggest concern about modding, which is that you wouldn't be able to get the same MMO-style community on modded servers. If this works right, people won't have to fuss with finding and installing mods, they can just join a server that looks fun.

    Recalling that FTB is partnered with NK, I'm curious what they might be cooking up as well.
    I think more than I say and say more than I do, but I do more than I used to and plan to continue.
    TUG modder (at least in the ounce of free time that occasionally flits by)
  • Auti0Auti0 REGISTERED Posts: 277
    Great suggestions. These are definitely features we are thinking about and we should have discussions on them.

    That being said, I'd like to keep the discussion in this thread more directly related to the API itself. I'm looking more for suggestions about exposed functionality, ease-of-use for certain classes, etc. 8-)
  • johnycilohoklajohnycilohokla REGISTERED, Developers Posts: 283 Developer
    My main suggestion would be prioritizing the Persistence API.
    A way to save data on in-world entities, players, mobs/characters and items.
    And a way to serialize items and entities so that they can be saved and loaded from within each other.
    That would be the main thing needed for more advanced mods to be created, I would say 80% of the mods would be possible once there is a way to save and load data.

    The second thing would be GUI.
    While most mods wouldn't necessarily need GUI it is required to simplify advanced actions and to configure machines. Also things like backpacks and other storage containers (on player or in-world) will require GUI, with an exception of storage container that display the items(in-world).
    My Blog
    jc.png
      yt.png  t.png  
  • nocarenocare REGISTERED, Tester Posts: 92
    I haven't really encountered much suggest as of yet.

    In another script I shared a short class to print to the ingame console. I assume the functionality of NKPrint() should cover this in the future?

    Object:OnPlace(), Object:GetReplacingObject() should be added to the example object file, probably along with any other missing/unknown functions.
    Is there an OnPickup()/destroy/remove type of function on objects?

    --
    NKGetNumChildren, NKGetChildAt are useful yes.
    It would be useful to have a function that returns an array of child objects, even more so if it is recursive.
    NKGetChildren()?

    This is useful to me, so I'm building a lua version of it currently, and for some dynamic (not knowing what child will be) uses, this certainly could be a helpful function. I'm also adding a getChildrenByName to have flexibility.

    NKDeleteChild()? By Index probably.
    Currently I have to detach the child and then delete it.

    I wonder now, where do we draw the line? This is easy enough to add to the lua side of things, and I'm sure just the same on the client side.
  • johnycilohoklajohnycilohokla REGISTERED, Developers Posts: 283 Developer
    I have a request for a 2 very specific functions.

    Similar to GameObjectSystem:NKGetGameObjectsInRadius

    First would be GameObjectSystem:NKGetGameObjectsInBB (Bounding Box)
    It would take 3 arguments:
    1 - BoundingBox (extents [minX, maxX, minY, maxY, minZ, maxZ])
    2 - Quaternion (got from the object NKGetWorldOrientation)
    3 - Type (same as in NKGetGameObjectsInRadius)

    And a second one GameObjectSystem:NKGetGameObjectsInCylinder
    1 - Length (moving on quat:Forward())
    1 - Radius (moving on quat:Up()/quat:Right())
    2 - Quaternion (got from the object NKGetWorldOrientation)
    3 - Type (same as in NKGetGameObjectsInRadius)
    My Blog
    jc.png
      yt.png  t.png  
  • ScriptsScripts REGISTERED, Developers Posts: 41 Developer
    Hey johnycilohokla,

    I've been working on getting primitive types into the datafiles and lua. So, that might cover the case of doing a collection query with any type of shape.

    Let's see how this looks written out:
    function MyClass:CollectIntruders()
    
    	-- Table describing the shape to use for the query
    	--	type = Cube
    	--	dimensions = 5 x 5 x 5 <length, width, height>
    	local queryShape = {
    		type = EternusEngine.EPrimitiveTypes.eCube,
    		dimensions = vec3.new(5.0, 5.0, 5.0)
    	}
    
    	-- The world position of the query
    	local location = self:NKGetPosition()
    
    	-- The world orientation of this object
    	local orientation = self:NKGetWorldOrientation()
    
    	local intruders = EternusEngine.GameObjectSystem:NKGetGameObjectsInShape(location, orientation, queryShape)
    
    	NKPrint("Detected: " .. table.getn(intruders) .. " Intruders.")
    	NKPrint("Names: ")
    
    	for i = 1, table.getn(intruders) do
    		NKPrint(i .. ": " .. intruders[i]:NKGetName() .. "<" .. intruders[i]:NKGetDisplayName() .. ">")
    	end
    end
    

    I personally like how this looks. Though, the queryShape struct (table) also has 2 other fields that might be confusing: orientation, position. Those fields essentially provide a local space orientation and translation from its local origin. That way, you can define any offsets or geometric rotation before even using the shape in 'NKGetGameObjectsInShape'

    Having the flexibility is nice. But, terminology could muddy the waters.

    Opinions?
    Let's make something awesome together.

    Follow me! @Scriptslol
  • johnycilohoklajohnycilohokla REGISTERED, Developers Posts: 283 Developer
    Scripts wrote:
    ...

    I personally like how this looks. Though, the queryShape struct (table) also has 2 other fields that might be confusing: orientation, position. Those fields essentially provide a local space orientation and translation from its local origin. That way, you can define any offsets or geometric rotation before even using the shape in 'NKGetGameObjectsInShape'

    Having the flexibility is nice. But, terminology could muddy the waters.

    Opinions?

    It's perfect, good job.
    Can I expect in the upcoming update? (I have a list of uses for it already :D and I would rather not have to use the radius function and add those functions myself)
    The position and orientation is definitely needed, while some modders will not understand it at first, once they start getting into how it works they will see what it does and why it is needed.
    My Blog
    jc.png
      yt.png  t.png  
  • mercormercor REGISTERED Posts: 64 Seed
    Is there a way to subscribe to an event on object of a specific class entering or leaving area (consisting of certain radius from player)?

    API doc mentions EventSystem that has broadcast methods for broadcasting to all objects in certain radius.

    Basically I could just broadcast to certain class every second or so, and look if they reply back. But that might get expensive if there would be lots of objects inside the area. I would probably just rather subscribe to the enter and leave events, as I only need to keep track of objects when they cross the perimeter.
    Modder in making. Point of Interest mod - Now with GUI

    twitter: @mercorinred
  • mercormercor REGISTERED Posts: 64 Seed
    Couple of more additions to the list of suggestions:

    1) More game events

    It might be that these things already exist, and I just haven't found them, in which case this point can be skipped.

    There's a need for events for such things as starting a new GameMode, among other things. More essentially there's a need for a way to load and execute code when game play starts, without having to edit Survival.lua or other GameMode files. It would help with making GameMode independent mods.

    Also: For non coders it's rather hard to install a mod, if it requires editing lua files.

    What I do now (it might be that I'm missing something and doing things the hard way):

    In survival lua, I have to add the following lines in order to get my code included and several slash commands registered.
    ---------------- MyMod mod's code starts here ----------------
    -- Copy this block to Survival.lua around line 22 
    -- Remember to make a copy of your Survival.lua before doing so.
    
    include("Scripts/Mods/MyMod.lua")
    
    Survival:RegisterSlashCommand("MySlashCommandA", "MySlashCommandA")
    Survival:RegisterSlashCommand("MySlashCommandB", "MySlashCommandB")
    
    function Survival:MySlashCommandA(args)
      -- EternusEngine.MyMod holds a reference to the code initialized in include('Scripts/Mods/MyMod.lua')
      EternusEngine.MyMod:MySlashCommandA(args[1])
    end
    
    function Survival:MySlashCommandB(args)
      EternusEngine.MyMod:MySlashCommandA(args[1])
    end
    
    ------------------ MyMod mod's code ends here ------------------
    

    2) [strike]Option to register slash commands and the object on which to call the registered method[/strike]

    Edit: This is actually possibly already, so putting the original to spoilers.
    The option to register slash commands is a great tool for testing mod functionality. It would be super useful addition to it, if there would be a way to also call methods outside the current GameMode. Currently, all functions associated with RegisterSlashCommand need to be methods of the current GameMode.

    For example RegisterSlashCommand could have a third parameter that would consist of the object to call the method on:
    TUGGameMode:RegisterSlashCommand(commandName, functionToCall, objectOnWhichToCall)
    

    Again, this would reduce the need to edit Survival.lua or other existing GameMode files.

    Edit: As TUGGameMode:RegisterSlashCommand and its counterpart TUGGameMode:ExecuteSlashCommand are just lua methods in TUGGameMode, it's fairly simple to create a second version of both methods with the possibility to call methods with different objects. This would take away the need to use pipe methods like those used in the above example. But again, it would require editing the GameMode file.

    And that would again make it harder to distribute a mod with that kind of change to any non-coders.

    Edit 2: Cassy explained in Irc that suggestion 2 can be done already.

    It's pretty easy actually. Just add the wanted function to current GameState with Eternus.GameState and use it also to register the slash command.
    -- you can use the following in any file, after GameState has started:
    function Eternus.GameState:MySlashCommand() 
        NKPrint("This works!")
    end
    
    Eternus.GameState:RegisterSlashCommand("myslashcommand", "MySlashCommand")
    
    Modder in making. Point of Interest mod - Now with GUI

    twitter: @mercorinred
  • MeldrixMeldrix REGISTERED Posts: 24 Seed
    A way to check if an object is currently being rendered would be really helpful.
  • mercormercor REGISTERED Posts: 64 Seed
    Not sure if mod version numbering is used anywhere, but it would be handy if there was a common syntax for setting the third number (e.g. 0.0.1) in manifest file, whether it's called build, change, revision or something else.
    Modder in making. Point of Interest mod - Now with GUI

    twitter: @mercorinred
  • johnycilohoklajohnycilohokla REGISTERED, Developers Posts: 283 Developer
    I have few new requests.

    A way to determinate if the object:
    • is ghost object
    • is placed in the world
    • is in inventory
    • was an dropped item (or was always static)

    A way to find out if an object was removed from the world (pick up or destroyed), some kind of exists() function, I'm running into problem when I have a visible attachment that can be removed, but I'm referencing it from a variable, having a simple function that I could call to find out if an object still exist would be extremely helpful, as when I try to access such object I get a crash.

    The NKScale() function only allows single int variable, I really need to way to scale the object on each axis independently. I have a set of functions that I could easily debug if I could scale an 1x1x1 cube independently. Also I will need it for liquid storage, displaying power or pressure bar on power/steam storage objects, and tons of other cool things will need it as well.

    A way to render text (and item icons, models if possible as well) in 3D, and a rendering hook in lua.
    My Blog
    jc.png
      yt.png  t.png  
  • mercormercor REGISTERED Posts: 64 Seed
    Improvements to NKParseFile:

    NKParseFile was introduced recently. It allows reading a named txt configuration file. It's really handy for reading mod's own configuration files into a lua table.

    In addition to its current functionality, similar function to parse all files with similar name, in every mod's folder would be useful.

    One use case would be to read specifically named files from all mods.

    Example use case: Read CREDITS.txt from all mod directories. The file would contain people and groups behind the mod, with some predefined syntax. This information could then be shown to player in a form or another.

    I know there are other ways to do this, but I take NKParseFile and its like are the intended functions to use, now that it's introduced.


    EDIT: Possibility to only read txt files from own mod folder with NKParseFile would also be handy. This way modders could use more user friendly config file names, such as config.txt, without having to be afraid of name conflicts with other mods. Could be additional parameter for NKParseFile.
    Modder in making. Point of Interest mod - Now with GUI

    twitter: @mercorinred
  • Red AgliatorRed Agliator REGISTERED Posts: 307 Seed
    edited May 2015
    Suggestion: a built-in way to easily control free-flying characters

    Background:
    For ground-bound characters, the current way of controlling movement seems to be to change the game object's orientation, change the character's maximum speed, then move:
    	self.Controller:NKSetMaxSpeed(speed)
    	self.Owner:NKSetOrientation(...)
    	self.Controller:MoveForward()
    	self.Controller:Step(dt)
    
    There are several problems that keep this from working for a free-flying character. I'm fiddling around with other potential ways to control free movement, but it'd be nice to have something this simple for 3D-moving characters.


    Problems for free-flying characters:
    (These behaviors all seem reasonable for ground-bound characters, of course.)

    1) MoveForward always moves horizontally, even if WorldOrientation includes a y component

    2) Combining MoveForward and MoveUp will always make the character move at a 45 degree angle from horizontal. That's because MaxSpeed is applied in each dimension: the character moves up exactly as fast as it moves forward.

    Multi ninja-edits:
    I was apparently wrong about being wrong. If you have no idea what I'm talking about, you can just ignore this statement. Unless you'd find that wrong.
  • ZakeZake REGISTERED Posts: 216 Seed
    That would also be nice for when I start writing my bee AI.
    I think more than I say and say more than I do, but I do more than I used to and plan to continue.
    TUG modder (at least in the ounce of free time that occasionally flits by)
  • nocarenocare REGISTERED, Tester Posts: 92
    RigidBodyComponent.NKSetLinearVelocity crashes if passed anything but a vector. Some handling so there is at least a console message would be nice.
  • ScriptsScripts REGISTERED, Developers Posts: 41 Developer
    nocare said:

    RigidBodyComponent.NKSetLinearVelocity crashes if passed anything but a vector. Some handling so there is at least a console message would be nice.

    When the engine is compiled for release the lua interop layer is optimized and removes type checking. When running in debug there is a helpful assert that fires when there is a type mismatch on a C function call. I can see why it might be helpful to have a debug-release variant that keeps these exceptions compiled in with a small performance cost.

    opinion? :)
    Let's make something awesome together.

    Follow me! @Scriptslol
  • nocarenocare REGISTERED, Tester Posts: 92
    Scripts said:

    opinion? :)

    That would definitely at least let us know what call made things silently crash, so it would be a welcomed change to me.
  • UFIOESUFIOES REGISTERED, Tester Posts: 42 Seed
    Despite what the current documentation says, I don't think that:
    CharacterController(SetGravity(vec3)
    does anything, I have tried y components of -40, -16, -4, 0, and 16, none of which have any effect.

    Additionally I think that:
    CharacterController:SetDefaultGravity()
    is unimplemented (nil)
  • UFIOESUFIOES REGISTERED, Tester Posts: 42 Seed
    edited June 2015
    Eternus.Terrain:NKModifyWorld(modificationInfo) crashes the game when placing/removing voxels if a large value is used for modificationInfo.dimensions = vec3.new(50, 50, 50) and modificationInfo.radius = 50.

    Additionally, when using modificationInfo.dimensions and modificationInfo.radius larger than vec3.new(4, 4, 4) and 4, the center will not be effected, causing the placement/removal of hollow cubes with the square brush, and crashing the game with the sphere brush.

    Is there a reason that Eternus.Terrain:NKModifyWorld(modificationInfo) does not support arbitrarily large brush sizes?
  • ZakeZake REGISTERED Posts: 216 Seed
    edited July 2015
    Scripts said:

    opinion? :)

    Would it be feasible to include that in the config options? Perhaps even a "--debug" launch option?
    I think more than I say and say more than I do, but I do more than I used to and plan to continue.
    TUG modder (at least in the ounce of free time that occasionally flits by)
  • nocarenocare REGISTERED, Tester Posts: 92
    edited July 2015
    I would like the ability to modify a component of a vector without having to create a whole new one.
    Currently I need to do this:
    local speed = physicsComponent:NKGetLinearVelocity()
    speed = vec3.new(speed:x(), speed:y() / 42, speed:z())
    physicsComponent:NKSetLinearVelocity(speed)

    I would like to be able to simply do something like this:
    local speed = physicsComponent:NKGetLinearVelocity()
    speed = speed:y(speed:y() / 42)
    physicsComponent:NKSetLinearVelocity(speed)

    I may have missed some easier way of doing this, but I feel this would simplify code a bit otherwise.
  • nocarenocare REGISTERED, Tester Posts: 92
    edited July 2015
    Quaternion :Direction() functions have an odd relationship with models in tug.

    -y negative being forward on the model is fine with me, but as for quaternions, this drives me a bit crazy.
    I have to modify the base quaternion to get :Direction() vectors that make sense to me.

    In my object if I treat -y as forward and +z up then quat:Forward() will be correct.

    quat:Up() = Left and quat:Right() = up in that case.
    So If I want Up relative to object: quat:NKGetInverse():Right()
    If I want Right: quat:NKGetInverse():Up():mul_scalar(-1)
    This gets confusing real fast..



    I can rotate the model and then rotate the object again in a data file to correct this. But that Is extra work and I also have to keep a badly rotated model. I have to do these rotations on the quaternion before I even start working with them if I want things to make any sort of sense.


  • mercormercor REGISTERED Posts: 64 Seed
    Saving and restoring mod data between sessions is currently being done relative to the mod name, if I've understood correctly.

    It might be useful to identify mod data by other means than name, as a mod's name might change due to a number of reasons.

    A possible solution could be to allow mods to set in the manifest file a save identification URI or such similar id, that would be used to match mod and its saved data. With URI i mean unique string that would be in human readable form, and is being used for resource identification. Basically something looking like URL, except it wouldn't map to any internet location.

    There might also be cases where mods might want to read and/or write to two or more save datas. For example, a mod could want to alter two distinct mods save data, due to two mods being combined. Similar situation could occur when a mod acts as a drop in replacement for another mod but doesn't want to contaminate the other mods save with its own unrelated data.

    Situations to consider:

    * Mod name is changed, just because. [name change]
    * Two mods are combined into one bigger mod that does both parts better than the single one. [name change, multiple save locations needed to be handled for backwards compatibility]
    * A behemoth mod is broken into multiple smaller mods. [name change, possible multiple save locations]
    * A mod is forked.
    * Mod works as a drop in replacement for another mod.
    Modder in making. Point of Interest mod - Now with GUI

    twitter: @mercorinred
Sign In or Register to comment.