While working on my first mod I had to search a lot of places to get information about object life cycle callbacks, until I found this on http://starbounder.org/Modding:Lua/Hooks/Object. That wiki page now links to a series of vanilla code examples. It's the wiki, so, probably not really up to date, but I've checked this against both vanilla code and some large mods and it seems to be ok - as of the last edit date of this post. From there, I started cobbling together both a template for .object's scripts lua files, and the documentation of their behavior and quirks. I made the code in ready to use .lua format for my own use, but I thought I could share it with the community. Then I had the idea of extending the scope of this post to include easy to use .patch templates, or whatever other code templates that I come by or the community wants to share. If anyone knows of callbacks that are not on the lua files, some better info on what we already have, some better way of doing the same things, actually any useful bits and itches of information please feel free to contribute. I reserve the rights to curate and edit the original post, but, really, anyone who wants to contribute can share their material here or via PM to me. All due authoring/contributing attribution will be made. So far we have: objecttemplate.lua - To be used in the "scripts" field of a .object file. Runs client-side. questtemplate.lua - To be used in the "scripts" field of a .questtemplate. Runs server-side. testaddtemplate.patch - To be used with a path which accepts exclusively a value or an array. Checks for path existence, creates it if necessary then adds a value or an array (for arrays, you have to include square brackets around the last "add" value". testaddtemplate2.patch - contributed by @IHart - To be used with a path which accepts alternatively a value or an array. Checks for path existence, creates it if necessary, move the previous value, if already present, into an array at that path or just creates path + array, and then adds a value to that array. Assorted json Bits - assorted useful bits for json configuration, contributed by @lazarus78. I'll move those bits into more specific places, when and if they come around. Link to the MIT License text, applicable to some of the code, as noted in their individual comments. About server/client sidedness, @zetaPRIME has contributed this: Server/client sidedness is important, besides multiplayer issues, because, according to lua/doc/word.md: Code: #### `LuaValue` world.callScriptedEntity(`EntityId` entityId, `String` functionName, [`LuaValue` args ...]) Attempts to call the specified function name in the context of the specified scripted entity with the specified arguments and returns the result. This method is synchronous and thus can only be used on local master entities, i.e. scripts run on the server may only call scripted entities that are also server-side master and scripts run on the client may only call scripted entities that are client-side master on that client. For more featureful entity messaging, use world.sendEntityMessage. Besides that, there are several functions in word that can only be called serverside. They are listed starting at line 788 of word.md Code: --[=====[ Copyright notice: The text on the comments and the lua code is mostly copied or derived from the wiki or vanilla unpacked assets, and are conveyed under the same license as them. --]=====] --[=====[ Called (once) after the object is added to the world, and when the world containing that object is loaded. --]=====] function init() end --[=====[ Update loop handler. Called once every scriptDelta (defined in *.object) ticks dt is the time in seconds (may be a fraction) since the last time update was called. --]=====] function update(dt) end --[=====[ Called when the object is about to be removed from the world. --]=====] function die() end --[=====[ Called when the container contents have been changed or interacted with in a GUI Pane. --]=====] function containerCallback() end --[=====[ function onInteraction(args) Called when the object is interacted with.<br /> 'args' - Map of interaction event arguments: { sourceId = <Entity id of the entity interacting with this object> sourcePosition = <The {x,y} position of the interacting entity> } Returns: nil (no interaction response) or a table -- see sbvnobject and challengedoor examples in -- the link for code examples. { <string "interactAction", --see above <map {<interactData>}> } If interactData is malformed in the returned value, the object will not be interactable in game, even with '''object.setInteractive(true)'''. The same applies if onInteracion() throws a lua exception at runtime. Objects that only need to rely on a GUI Pane doesn't need to specify a "scripts" variable in their '''.object''' file, just provide values for "interactAction" and "interactData"/"uiConfig". Available interaction responses ("interactActions") are: "OpenCraftingInterface" --used 36 times in vanilla "OpenTeleportDialog" --used 29 times in vanilla "ScriptPane" - For widget-based panes --used 26 times in vanilla "OpenMerchantInterface" --used 14 times in vanilla "ShowPopup" --used 6 times in vanilla "OpenCockpitInterface" --not used in vanilla "SitDown" --not used in vanilla "OpenCookingInterface" --not used in vanilla "OpenTechInterface" --not used in vanilla "Teleport" --not used in vanilla "OpenSongbookInterface" --not used in vanilla "OpenNpcCraftingInterface" --not used in vanilla "OpenTech3DPrinterDialog" --not used in vanilla "ScriptConsole" - For ScriptCanvases --not used in vanilla --]=====] function onInteraction(args) -- return {interactActions, interactData} end --[=====[ Called when the level of an inbound connected node changes 'args' - Map of: { node = <(int) index of the node that is changing> level = <new level of the node> } --]=====] function onInputNodeChange(args) end --[=====[ Called when a node is connected or disconnected --]=====] function onNodeConnectionChange(args) end --[=====[ Called when the object is interacted with, by an NPC. --]=====] function onNpcPlay(npcId) end Code: [=====[ Copyright notice: The text on the comments and the lua code is mostly copied or derived from the wiki or vanilla unpacked assets, and are conveyed under the same license as them. --]=====] function init() end function uninit() end function update(dt) end function questOffer() end function questDecline() end function questStart() end function questComplete() end function conditionsMet() end Code: /* This code has been around the community for some time, and it's so simple that I believe it falls under the common programming patterns category, rather than actual software protectable by copyright. */ [ [ { "op": "test", "path": "/scripts", "inverse" : true }, { "op": "add", "path": "/scripts", "value": [ ] } ], [ { "op": "add", "path": "/scripts/-", "value": "/scripts/mything/mything.lua" } ] ] Code: /* Copyright notice: Written by @IHart and released under MIT License. Copyright © 2017 IHart */ [ [ { "op": "test", "path": "/learnBlueprintsOnPickup" }, { "op": "test", "path": "/learnBlueprintsOnPickup/0" , "inverse": true }, { "op": "test", "path": "/learnBlueprintsOnPickup" , "value" : [], "inverse": true }, { "op": "move", "from": "/learnBlueprintsOnPickup" , "path": "/hold" }, { "op": "add" , "path": "/learnBlueprintsOnPickup" , "value": [] }, { "op": "move", "from": "/hold", , "path": "/learnBlueprintsOnPickup/-" } ], [ { "op": "test", "path": "/learnBlueprintsOnPickup" , "inverse": true }, { "op": "add" , "path": "/learnBlueprintsOnPickup" , "value": [] } ], [ { "op": "add", "path": "/learnBlueprintsOnPickup/-" , "value": "your_item" } ] ] Code: ================================================== "renderLayer" ================================================== Used to make an object image render on a specific layer. Values are between -10 and +10, with 0 being the default layer. "renderLayer" : "Object+10", "renderLayer" : "Player+10", Possible application of this function would be for making objects render in front of the player. What this means is, the player will walk BEHIND the object if you use a posative value. So you could make things like bushes and railings that the player actually walks behind, giving the illusion of depth. This functions basically like the "zlevel" bit from block configs, but for objects. I am not 100% sure on the difference between “Object” and “Player”. Example: http://imgur.com/Ke3nWNi ================================================== "actionOnReap" ================================================== Used to perform actions, such as spawning projectiles, calling up configs, or even spawning items. Most commonly used with weapons, especially in projectile configs for spawning multiple projectiles. Options for "action": - spawnitem - projectile - config Examples: "actionOnReap" : [ { "action" : "spawnitem", "item" : "YourItem", "count": 1 } ] Source - rocketTrooper.monstertype ---------------------------------- "actionOnReap" : [ { "action" : "config", "file" : "/projectiles/explosions/regularexplosion2/regularexplosionknockback.config" } ] Source - aegisaltbow.activeitem ------------------------------- "actionOnReap" : [ { "action" : "projectile", "type" : "chargedenergyarrow", "angleAdjust" : -50, "inheritDamageFactor" : 0.2, "inheritSpeedFactor" : 1 } ] ================================================== "requiresBlueprint" ================================================== This setting can be used on crafting table configs to make players not require blueprints for whatever the table can make. AKA: No need to patch the player.config for every new item you want to add. Example: "requiresBlueprint" : false, By default, this setting is not in the configs for crafting tables, and it is assumed "true". ================================================== Adding glow to materials ================================================== How to add a glow to materials, like the Erchias Crystals and whatnot. Example: "renderParameters" : { "texture" : "supermatter.png", "variants" : 5, "lightTransparent" : false, "multiColored" : true, "occludesBelow" : true, "zLevel" : 3930, "radiantLight" : [128, 0, 128] // <-- This line } ================================================== Teleport Object ================================================== This can be added to an object to make a teleportation dialogue open. Beyond just teleporting to your ship or another bookmark, this paticular setup will allow you to define the X and Y coordinates specifically. Meaning you can use this to make hard coded teleportation points on a specific planet. I found this code being used for fake "door" objects to make people teleport below the surface to what was supposed to be the "interior" of the building. Example: "interactAction" : "OpenTeleportDialog" "interactData" : { "canBookmark": false, // Prevents bookmarking of this teleporter object "destinations": [ { "icon": "return", "name": "^white;Enter Building", "planetName": "", "warpAction": "Nowhere=x.y" // The X and Y values can be found with /debug } ], "includePartyMembers": false, // Don't show party members in the dialogue "includePlayerBookmarks": false // Don't show bookmarks in the dialogue } ================================================== Collision Samples ================================================== These are quite common on most objects, but I wanted to document how they are used. This one is quite simple. There are pre-defined sets of collision types. "collision" : "platform", "collision" : "solid", "collision" : [ [-0.25, 0], [0.25, 0], [0.25, 12], [-0.25, 12] ], platform - An objects collision will act like platforms. the collision will only be at the "top" of the object, as calculated by the "spaceScan" setting. solid - As the name implies, the collision of the object will be completely solid, as calculated by the "spaceScan" setting. [ ] - This is an array. You can use coordinates to define a "collision area", which is useful for more complex objects. Example: "collision" : [ [-1, 0], [1, 0], [1, 1], [-1, 1] ], - Values are based on the number of block spaces, so a calue of [-1,0] means one block to the left, and zero blocks up. - This will make a 2x2 (block) collision box, centered on the object. Note, that offsetting an object image will cause the "center" to shift as well. [0,0] is basically wherever the object is on the curser when attempting to place it. - You can use as many coordinates as you wish to make more complex collision shapes. This setting is used to define specific spaces as having collision. Basically "I want collision exactly here". This is used in conjunction with the abolve "collision" setting to define the type of collision; "solid" or "platform". "collisionSpaces" : [ [-5,6], [-4,6], [3,6], [-2,6] ] ================================================== Image Modifiers ================================================== Additional parameters you can add to the "image" setting for various effects. ?fade=<color>=<fraction_amount> ?brightness=<amt_percent> ?saturation=<amt_percent> ?hueshift=<amt_degrees> ?replace;<color1>=<color2>; ?addmask=<file> ?submask=<file> ?multiply=<color> ?border=<size>;<color1>;<color2> ?scalenearest ?scalebilinear ?scale=<value> <-- can't be a variable ?scalebicubic ?crop=<left>;<top>;<right>;<bottom> ?setcolor=<color> ?flip Example: "image" : "<partImage>:default.<frame>?scale=2" http://community.playstarbound.com/threads/s2f-basic-lua-and-advancing-animation.57871/#post-1859602 * Edited on July, 14, 2017: Better info on objecttemplate.lua, including connection nodes callbacks. Included questtemplate.lua. Included testaddtemplate.patch Included testaddtemplate2.patch -- author: @IHart * Edited on July, 15, 2017: Added copyright notice to @IHart contributed code Added information on client/server sidedness * Edited on July, 17, 2017: Added assorted json bits contributed by @lazarus78. document questtemplate.lua add other templates
I think that page lists them all the built in ones, but keep in mind that you can call functions with scripted entity calls - for example in \objects\wired\door\door.lua You have hasCapability() and doorOccupiesSpace() which exist for the sole reason of being called this way. And of course the messaging added callbacks also present in this script as well.
Yes, I'm aware of world.callScriptedEntity and world.sendEntityMessage and how they work. Actually, I could grasp that way sooner, just by reading some mods' code. My problem wast to find when the lifecycle methods were called, since I needed them in order to do some tricks I have in mind, but since they are called from the game engine and not from inside script code, even in the vanila folder tree, I couldn't get that without some documentation.
Challenge mode! "learnBlueprintsOnPickup" accepts strings or arrays. Preserve the string if present. My best solution so far: Code: [[ { "op": "test", "path": "/learnBlueprintsOnPickup" }, { "op": "test", "path": "/learnBlueprintsOnPickup/0", "inverse": true }, { "op": "test", "path": "/learnBlueprintsOnPickup", "value" : [], "inverse": true }, { "op": "move", "from": "/learnBlueprintsOnPickup", "path": "/hold" }, { "op": "add", "path": "/learnBlueprintsOnPickup", "value": [] }, { "op": "move", "from": "/hold", "path": "/learnBlueprintsOnPickup/-" } ],[ { "op": "test", "path": "/learnBlueprintsOnPickup", "inverse": true }, { "op": "add", "path": "/learnBlueprintsOnPickup", "value": [] } ],[ { "op": "add", "path": "/learnBlueprintsOnPickup/-", "value": "your_item" } ]]
Ive accumulated a list of my own for some "useful" bits of information... Not specifically scripting, but JSON. Would this be an appropriate place to post it, or maybe its own thread would be better?
The intention of this thread is exactly that, @lazarus78. Of course I reserve the rights to curate and edit the original post, but anyone who wants to contribute can share their material here.
Okie dokie. Here is a little doc file of some things I have found useful. Note that the explinations are based on my understanding, so they could be wrong, and I am open to corrections as well as expanding. http://www.mediafire.com/file/d4s48yxrjbobyht/Useful_Things.doc