• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Tibia [LUA] Global environment storage using JSON

Roddet

Staff member
Global Moderator
Joined
May 1, 2013
Messages
943
Solutions
102
Reaction score
760
Location
Mex
I decided to create my own global environment by using JSON since im one of those that still uses an ancient distro (0.3.7) where environments are not shared through scripts. It will make your life alot easier!

It can be used on TFS 1.0 series to export data to the database nor import to the server in a cleaner way.
Also its useful to store global data between restarts!

Installation:
  • Go to data/lib/ and paste globalstorage.lua inside (if you are on TFS 1.x dont forget to register the file on lib.lua)
  • Inside data/lib create a new folder called json and paste the json.lua there
  • Go to phpmyadmin and execute the following query:
SQL:
CREATE TABLE IF NOT EXISTS `json_data` (
    `id` int NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL DEFAULT '',
    `data` text NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Module information

By default a global.json file is created to store all the data, however you can specify on the contrusctor if you want to store the data in a separate file
.json files are automatically created if necessary, so you dont need to worry about that

Main Functions
Lua:
json.encode(table)
json.decode(json)
json.stringify(json)

Constructor
Lua:
-- # server_data = main table index
local data = json("server_data") -- # it will create/load an object (table index) on global.json file (default)
local data = json("server_data", "otclient") -- # it will create/load an object (table index) on the specified file which is "otclient.json"

Constructor Methods
Lua:
data:json_delete() -- # deletes all the contents related to the constructor key, which in this case is "server_data"
data:json_update() -- # updates the contents of the current object to the file
data:json_load() -- # loads json code stringified and replaces the current object data
data:json_mysql_set() -- # stringifies json code and stores it on database (which is readable on any other language such as PHP - JavsScript)

Creating / modifying an object (table index)

Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)

    local castleInfo = json("castle_data")

    castleInfo.lastIndex = os.time()
    castleInfo.winners = {"Vulcan" , "Artemis", "Scylla"}

    print(castleInfo.lastIndex) -- # returns the timestamp
    print(castleInfo.winners) -- # returns the array

   -- # you must update the file contents each time you made modifications
   -- # its totally fine to do multiple updates at once (for example, inside a loop) or for each modification you make to keep the contents up to date always
    castleInfo:json_update()
    return true
end

As you can see, its literally a table where you can store anything and be accessible through all script environments
I highly recommend to avoid arrays and use associative values instead or be aware of the following:

You cannot mix value types - example:
Lua:
local t = {1, 2, v = 3} -- # this will lead to an error

Real example:
Lua:
-- # leads to the error
local castleInfo = json("castle_data")

castleInfo.players = {}
castleInfo.players[1] = 5
castleInfo.players["value"] = "string"

castleInfo:json_update()

# However, to workaround this you have several options such as:

Converting numeric keys into strings

Lua:
local castleInfo = json("castle_data")

castleInfo.players = {}
castleInfo.players["1"] = 5
castleInfo.players["value"] = "string"

castleInfo:json_update()

Storing numeric arrays in a sub-table
Lua:
local castleInfo = json("castle_data")

castleInfo.players = {}
castleInfo.players["arr"] = {1, 2, 3}
castleInfo.players["value"] = "string"

castleInfo:json_update()

Removing an object
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    local castleInfo = json("castle_data")

    -- # removes all the contents of the constructor key, in other words -> ["castle_data"] = nil
    -- # file contents are updated automatically at calling "delete()"
    castleInfo:json_delete()
    return true
end

Storing contents in database and displaying on PHP

Now ... using the first script shown above, if you call the method json_mysql_set() right after the method json_update(), it will store the contents on the database.

The following will be stored on database:
Code:
"{\"winners\":[\"Vulcan\",\"Artemis\",\"Scylla\"],\"lastIndex\":1670117246}"

Which later you can display in PHP very easily - example:
PHP:
# assuming this is a query
$string = "{\"winners\":[\"Vulcan\",\"Artemis\",\"Scylla\"],\"lastIndex\":1670117246}";

$json = json_decode($string);

echo $json->winners[0]; # prints "Vulcan"
echo $json->winners[1]; # prints "Artemis"
echo $json->winners[2]; # prints "Scylla"

echo $json->lastIndex; # prints 1670117246

Loading a json code stringified

Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    local copyInfo = json("copy_castle_data")
    copyInfo:std_json_load("{\"winners\":[\"Vulcan\",\"Artemis\",\"Scylla\"],\"lastIndex\":1670117246}") -- # assuming this is a query or smth

    print(copyInfo.lastIndex) -- # returns the timestamp
    print(copyInfo.winners) -- # returns the array

    copyInfo:json_update() -- # dont forget to update the file contents ALWAYS!
    return true
end

Loading an existing table

Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)

    local data = {
        winners = {"Vulcan", "Artemis", "Scylla"},
        lastIndex = 1670117246
    }

    local copyInfo = json("copy_castle_data")
    copyInfo:json_load(data)

    print(copyInfo.lastIndex) -- # returns the timestamp
    print(copyInfo.winners) -- # returns the array

    copyInfo:json_update() -- # data pushed into desidered file
    return true
end
Once you load an existing table or json code, you can overwrite values or create new indexes, as normally you would do in a normal table.

Changelog

[Update 1.1][globalstorage.lua]:
previous data keys are no longer accessible once std_json_delete() is called
[Update 1.2][globalstorage.lua]: added possibility to load an existing table
[Update 1.3][globalstorage.lua]: it will keep spaces inside string keys or values
[Update 1.4][globalstorage.lua]: click here

Enjoy!
 

Attachments

Last edited:
Crazy thing is, most users have no clue how awesome this system is, and the fact that you are sharing it with everyone. Thanks bro! Very Much appreciated, I'll check it out when I have some time and give more detailed feedback when I can :D
 
Update
  • Constructor has been renamed to json
  • Constructor methods has been renamed for friendly use
  • Now the module provides global access to the main functions
Lua:
-- # constructor
obj = json("example")

-- # methods
obj:json_update()
obj:json_delete()
obj:json_load()
obj:json_mysql_set()

-- # main functions
json.encode()
json.decode()
json.stringify()
 
Last edited:
Update
  • Constructor has been renamed to json
  • Constructor methods has been renamed for friendly use
  • Now the module provides global access to the main functions
Lua:
-- # constructor
obj = json("example")

-- # methods
obj:json_update()
obj:json_delete()
obj:json_load()
obj:json_mysql_set()

-- # main functions
json.encode()
json.decode()
json.stringify()
Thanks for your contribution, already implemented, works like a charm.. i only had to change SQL QUERY to:
SQL:
CREATE TABLE IF NOT EXISTS `json_data` (
    `id` int NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL DEFAULT '',
    `data` text NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

Now i can easily export item list to load on OTC (8.0.. no in-game market attributes in dat/spr)
Thanks!
 
Thank you, query updated. Nice to see you found a good use for it.
 
local loot = {
[2160] = 555,
[2471] = 444,
[2522] = 333
}

local lootJson = json.encode(loot)
not working for me. i added json.lua to data/lib/json and try with code upper and:

attempt to index global 'json' (a nil value)
stack traceback:
 
not working for me. i added json.lua to data/lib/json and try with code upper and:

attempt to index global 'json' (a nil value)
stack traceback:
did you register the lib...
 
Back
Top