From the user sublogic, written in the Runeforge Forum, 01 February 2015
ZitatAlles anzeigen
Just figured this out myself, which prompted to overhaul my experimental mods greatly, to potentially make things a lot easier in the future (both to develop and to allow others to modify simple settings). Thought I would share this to those who may have the need but have not discovered the means.
The need and the road so far:
* In many mods, we usually have a tabular kind of data that we need to refer to often.
* Naively, this can be done by using a massive if-else statement.
* Then I started to put that in a function so that it can be reused elsewhere. Often, having a function just to return size of some virtual list so that I don't have hard-code that value in more than one location.
* Then, I try to explore using globals (setting it once, on first use, then used by others), but requires tricks to "serialize" an array into simple values.
* Then, I realised how troublesome it was to add another item, which will require script changes, and every time a risk to breaking something...
* Then, I decided to invest time into discovering how dbt works and to design scripts such that adding new "items" of similar type will no longer require script changes, and that various "magic constants" are instead correctly derived from dbt (reflecting changes if necessary)
The Goal:
* Future changes should also be easily concentrated in one place, instead of being spread over many areas in many script files.
* Once the script is "done", adding new items should not need script changes anymore (which should make the task easier). It should be just adding new dbt items and other resource files like textures/models/sound etc.
Step 1. Design and Create a new dbt
Create a new empty text file, e.g. MyNewTable.dbt in the DB subdirectory from the game's main directory.
Copy the following "sample" content. (the comments are probably off, but I'm just lazy)
The first 2 columns most commonly used are provided. The "id" column is mandatory. The "name" column is useful for human reading during debugging and such.
The row under "Table Description:" is the schema, where each column, delimited by the pipe character "|", consists of a string Name, a type (INT/FLOAT/STRING/LIST) and something which I am not sure of but usually -1 for first id column, and 0 for the rest.
The data is specified after the line "Data:" where each value corresponds to a column in the specified order, delimited by WHITESPACE(any number of space/tab) and must end with a pipe character "|" (Note: this is very important. In my modding, one of the most common mistakes in dbt changing is forgetting or accidentally deleting the last pipe character. The second most common mistake is forgetting to enclose a string properly in double quotes)
Comments are lines starting with "//" which will be ignored when the dbt is being parsed.
CodeAlles anzeigen//Table File, Version 1.02 (c) 2004 4head studios //Exported Table Description: "id" INT -1 |"name" STRING 0 | Data: 0 "unknown" |
You can add new columns by adding to the schema and adding a new corresponding value in each row.
Example, if I want to add a new column called "mydata" which is a FLOAT type, I will change the above dbt contents to the following:
CodeAlles anzeigen//Table File, Version 1.02 (c) 2004 4head studios //Exported Table Description: "id" INT -1 |"name" STRING 0 |"mydata" FLOAT 0 | Data: 0 "unknown" 3.14 |
Step 2. Add it to tables.dbt
This is what got me when I first failed to use my own dbt.
The dbt created will not be available in-game unless they are first declared in this dbt itself (making tables.dbt possibly the only table which is always read by the game engine).
To add your table, add in a new line at the end, using an "id" which is not used, and use the filename(excluding the ".dbt" extension) as the "exportname" value. Below shows an example assuming my new dbt file was named "MyNewTable.dbt".
CodeAlles anzeigen//Table File, Version 1.02 (c) 2004 4head studios //Exported Table Description: "id" INT -1 |"exportname" STRING 0 | Data: 1 "textcategories" | 19 "tables" | 26 "Properties" | 27 "PropertiesTypes" | ... 102 "Lordship" | // including in my custom table 103 "MyNewTable" |
Step 3. Use it in your script
By using the "GetDatabaseValue" function.
The following is copied from the script function documentation.
CodeAlles anzeigenNumber or String GetDatabaseValue(String TableName, Number RowID, String ColumnName) Parameters: String TableName : The name of the database table. Number RowID : The ID of the row. String ColumnName : The name of the column for the desired value. Return Value: Number or String : The desired entry. Description: Returns an entry from a database table.
To use it on our table, example to extract the column "mydata" which I added, use the following:
Codelocal rowid = 0 -- the value in the "id" column to look for local mydata = GetDatabaseValue("MyNewTable", rowid, "mydata") -- probably a good idea to check if the value exists if( mydata ~= nil ) then -- use the data end
Step 4? Database-Script Synergy?
This tutorial just teaches how to create and use dbts accessible to in-game scripts. However, it still take a good modder to design how dbts should be use with respect to his/her scripts. The possible ways of using dbts would stretch into rdbms design stuff which would be too much to cover, but with the right use, it can greatly streamline your scripts (e.g. avoid tall "if-else towers") towards trying to achieve to "Goal" listed near the start of this tutorial.
Good Modding to all