If you have things to add, please post about them here and I might add them to this list.
A working example of all the stuff mentioned can be found here:
Example: Code Tips And Tricks
require is required
The require function of Lua is an extremely handy tool if taken advantage of. Whenever it loads a file, it stores the result (whatever the file returns) in a table (package.loaded), and any subsequent require calls with the same module name (you can think of module name as filename for now if you're unfamiliar with Lua modules) will give you a reference to the previous result.
This becomes very useful specifically for components, screens, widgets, and basically anything that defines a Class (because they will almost always return the Class at the end of the file). Since require caches its results and gives you a reference to that cached result, if you retrieve the result and modify it, you then also modify the result of any future require calls (and Don't Starve will usually use require to load these files).
With this, you can do things like:
-- if in the mod environment (modmain.lua), you need to get require from the global environment local require = GLOBAL.require -- Deployable becomes a reference to the cached result stored in package.loaded["components/deployable"] local Deployable = require "components/deployable" -- Store the existing function if it exists, otherwise store a dummy function as a fail-safe local Deployable_CanDeploy_base = Deployable.CanDeploy or function() return true end function Deployable:CanDeploy( pt ) -- Get the result of the base CanDeploy function -- Note: Deployable_CanDeploy_base is called with the self parameter because x:fn() is simply a shortcut for x.fn(x) with an implied self parameter local can_deploy = Deployable_CanDeploy_base( self, pt ) -- Add in our own deployment requirement can_deploy = can_deploy and pt == GLOBAL.Point(0,0,0) return can_deploy endNote: This is way faster than using AddComponentPostInit, as instead of overwriting function(s) for each and every component that comes into existence, this just does that modification one time up front and that's it. As far as I'm concerned, this should be the preferred method of extending/overwriting any Don't Starve Class definition.
Adding components to all players
credit to simplex for this workaround
This workaround is no longer necessary. Use AddPlayerPostInit instead.
Utilizing zero-time schedules
Sometimes you may need access to something that doesn't quite exist yet. For example, a prefab's Transform will not yet be initialized in a PrefabPostInit function or a prefab's fn constructor function. So, let's say you wanted to do something based on what tile type something spawned on. The easy way to do this is to create a task that will be executed in 0 time, which essentially waits one frame before executing the callback function you provide it (usually enough for what you want to start existing).
AddPrefabPostInit( "berrybush", function( inst ) -- inst.Transform:GetWorldPosition() will return 0,0,0 here -- this will wait one frame, which is enough time to have inst.Transform initialized inst:DoTaskInTime( 0, function() -- inst.Transform:GetWorldPosition() will give you the correct position now end ) end )
Some handy functions for detecting if other mods are enabled, getting their
environments (and potentially manipulating them), and checking if they have been
loaded yet or not
local _G = _G or GLOBAL -- returns the mod environment of the mod with the given name or ID function GetMod(name_or_id) for _, mod in ipairs( _G.ModManager.mods ) do -- note: mod.modname is the mod directory name if mod.modinfo.id == name_or_id or mod.modinfo.name == name_or_id then return mod end end return nil end -- returns whether or not a mod with the given name or ID is enabled function IsModEnabled(name_or_id) return GetMod(name_or_id) ~= nil end -- returns whether or not a mod with the given name or mod environment has been loaded yet -- 'loaded' means that its modmain.lua has been run function IsModLoaded(name_or_mod) local mod = type(name_or_mod) == "string" and GetMod(name_or_mod) or name_or_mod if mod then return table.contains( _G.ModManager:GetEnabledModNames(), mod.modname ) end return false end
Edited by squeek, 23 September 2014 - 01:04 PM.