This article contains information about features and important notes regarding Eluna.
Eluna has some settings in the server configuration file. It is important that you use the new configuration file that you get from compiling after adding Eluna. If the new configuration file is not used you will not receive any error log or output to console.
The configuration file includes at least the following settings:
- enable and disable Eluna
- enable and disable traceback function - this adds extra debug information if you have the default Eluna extensions.
- configure script folder location
- configure Eluna logging settings
To make testing easier it is good to know that Eluna scripts can be reloaded by using the command
However this command should be used for development purposes ONLY. If you are having issues getting something working restart the server.
It is important to know that reloading does not trigger for example the login hook for players that are already logged in when reloading.
Eluna loads scripts from the
lua_scripts folder by default. You can configure the folder name and location in the server configuration file.
Any hidden folders are not loaded. All script files must have an unique name, otherwise an error is printed and only the first file found is loaded.
The loading order is not guaranteed to be alphabetic.
Any file having
.ext extension, for example
test.ext, is loaded before normal lua files.
Instead of the ext special feature however it is recommended to use the basic lua
The whole script folder structure is added automatically to the lua require path so using require is as simple as providing the file name without any extension for example
require("runfirst") to require the file
In C++ level code you have types like
When in code you have an object of type
Unit you need to convert it to a
Creature or a
Player object to be able to access the methods of the subclass.
In Eluna this is automatic. All objects are automatically converted to the correct type and you will always have full access to all member functions of an object.
Storing userdata objects over time that are memory managed by C++ is a bad idea. For example you should never save a player to a global variable and then try access it in a timed event. The reason is that the player object in C++ is a pointer to an object that C++ can delete at any time. When time passes the player may have logged out and using the pointer after player object no longer exists can be catastrophic.
To prevent users from doing this objects that are memory managed by C++ are automatically turned into nil when they are no longer safe to be accessed - this means usually after the hooked function ends.
Instead of storing the object itself you can use store guids
player:GetGUID() and fetch the object by the guid with
Any userdata object that is memory managed by lua is safe to store over time. These objects include but are not limited to: query results, worldpackets, uint64 and int64 numbers.
All userdata objects in Eluna have tostring metamethod implemented.
This allows you to print the player object for example and to use
The userdata uses metatables that contain the methods and functions it uses.
These tables are globally accessible by using the type name. For example
Player is a global table containing all Player methods.
You can define new methods in lua for a class using these global tables.
function Player:CustomFunc(param1) -- self is the player the method is used on self:SendBroadcastMessage(param1) end function GameObject:CustomFunc(param1) -- self is the gameobject the method is used on print(self:GetName()) end -- Example use: player:CustomFunc("test") gob:CustomFunc("test2")
It is recommended that in normal code these global tables and their names (variables starting with capital letters like Player, Creature, GameObject, Spell..) are avoided so they are not unintentionally edited or deleted causing other scripts possibly not to function.
Database is a great thing, but it has it's own issues.
Database queries are slow. The whole server has to wait for the script to fetch the data from disk before continuing. Compared to reading cache or RAM reading from disk is the same as going to the moon to fetch the data (no pun intended).
Depending on what you need, prefer database Execute over Query when not selecting anything from the database. Database Executes are made asynchronously and they will not keep the server waiting.
Move all database queries possible to the script loading, server startup or similar one time event and use cache tables to manage the data in scripts.
Database types should be followed strictly.
Mysql does math in bigint and decimal formats which is why a simple select like
SELECT 1; actually returns a bigint.
If you fetch a bigint or decimal using a function for a smaller type it is possible the value is read incorrectly.
For example the same code for fetching the result of
SELECT 1; returned 1 on one machine and 0 on another. Using the correct function, in this case GetInt64, the right result was returned on both. https://github.com/ElunaLuaEngine/Eluna/issues/89#issuecomment-64121361
|base type||defined type||database type|
|(long int / int)||int32||mediumint(8)|
|(long int / int)||int32||int(10)|
|long long int||int64||bigint(20)|
|unsigned char||uint8||tinyint(3) unsigned|
|unsigned short int||uint16||smallint(5) unsigned|
|unsigned (long int / int)||uint32||mediumint(8) unsigned|
|unsigned (long int / int)||uint32||int(10) unsigned|
|unsigned long long int||uint64||bigint(20) unsigned|
|double||double||double and decimal|
|std::string||std::string||any text type|