• 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!

[LIB] Storing Information (Items and Players) TFS 1.2

Mkalo

ボーカロイド
Senator
Joined
Jun 1, 2011
Messages
1,118
Solutions
55
Reaction score
946
Location
Japan
The purpose of this lib is to add flexibility to what you're going to save in your server about players and items.
For example, using this lib you can save any string, table, boolean or number in a player and/or in an item and it will be saved in the database.

For the item part I had to edit the source to add a new attribute to store the data. I'll explain the source edits in the end of this post. (You can choose to not use it and only use the functions for player, then you wont need to edit anything in the source.)

Lib: http://pastebin.com/rcWX8hDf

SQL schema:
Code:
CREATE TABLE `player_misc` (
  `player_id` int(11) NOT NULL,
  `info` blob NOT NULL,
  UNIQUE KEY (`player_id`),
  FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Add this to login.lua:
Code:
    player:loadSpecialStorage()
Add this to logout.lua:
Code:
    player:saveSpecialStorage()

Note: As you can see the storages set are only going to be saved when the function to save is called, preventing information from being saved while the player was not saved. (You can set it to save in your script depending on what information you're saving, for default lets just save when the player logout like everything else.)

Functions:
Item:setSpecialAttribute(attr, value, ...)
Item:getSpecialAttribute(attr, ...)
Player:setSpecialStorage(storage, value)
Player:getSpecialStorage(storage)

The parameters storage and attr (keys) can be strings or numbers. The parameter value can be string,table,number or boolean.

-- EDIT:
To avoid serializing/unserializing the attribute too many times while seting/geting ITEM special attributes, now you should use the functions to set/get with all the values you want at the same time example:
Code:
        item:setSpecialAttribute("critical", 30, "dodge", 10)
        print(item:getSpecialAttribute("critical", "dodge")) -- prints 30 10

To help you with that I've added 2 functions:
unpack2(table)
pack(table, ...)


Example how to use:
Code:
local attributes = {
    ["critical"] = 30,
    ["dodge"] = 10,
}

function onSay(player)
    local item = player:addItem(2400)
    if item then
        item:setSpecialAttribute(unpack2(attributes))
        local out = {}
        pack(out, item:getSpecialAttribute("critical", "dodge"))
        print(out[1], out[2]) -- prints30  10
    end
    return false
end

Remember you don't have to use those functions, but they are going to help you if you have to get or set a lot of attributes at once.

Example (talkactions):
Code:
function onSay(player)
    player:setSpecialStorage("nickname", "Mkalo")
    player:setSpecialStorage("info", {1, 2})
    print(player:getSpecialStorage("nickname")) -- prints Mkalo
    print(unpack(player:getSpecialStorage("info"))) -- prints 1 2
    return false
end

This will set the key "nickname" as string "Mkalo" and the key "info" as that table.

Code:
function onSay(player)
    local item = player:addItem(2400)
    if item then
        item:setSpecialAttribute("critical", 30)
        print(item:getSpecialAttribute("critical")) -- prints 30
    end
    return false
end

This will add an item (id:2400) and set the key "critical" to 30.

Alright now its up to you to use it in some script that you may need to save strings/tables/booleans in an item or in a player.

Source changes to add the attribute needed for the item functions (You may need to change things if you already have new attributes added to your source, in that case you will have to know what you are doing or ask for help.)

enums.h:
Under:
Code:
    ITEM_ATTRIBUTE_DOORID = 1 << 22,

Add:
Code:
    ITEM_ATTRIBUTE_SPECIAL = 1 << 23,

item.h:
Under:
Code:
    ATTR_SHOOTRANGE = 33,

Add:
Code:
    ATTR_SPECIAL = 34,


Change:
Code:
return (type & 0x1EC) != 0;

To:
Code:
return (type & 0x8001EC) != 0;

item.cpp:
Under:
Code:
    if (hasAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)) {
        propWriteStream.write<uint8_t>(ATTR_SHOOTRANGE);
        propWriteStream.write<uint8_t>(getIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE));
    }

Add:
Code:
    if (hasAttribute(ITEM_ATTRIBUTE_SPECIAL)) {
        propWriteStream.write<uint8_t>(ATTR_SPECIAL);
        propWriteStream.writeString(getStrAttr(ITEM_ATTRIBUTE_SPECIAL));
    }

Above:
Code:
//these should be handled through derived classes

Add:
Code:
        case ATTR_SPECIAL: {
            std::string special;
            if (!propStream.readString(special)) {
                return ATTR_READ_ERROR;
            }

            setStrAttr(ITEM_ATTRIBUTE_SPECIAL, special);
            break;
        }

luascript.cpp:
Under:
Code:
    registerEnum(ITEM_ATTRIBUTE_DOORID)

Add:
Code:
    registerEnum(ITEM_ATTRIBUTE_SPECIAL)
 
Last edited:
Lib updated. Now you can set/get more than 1 attribute at once, this way the code wont serialize/unserialize in every execution. No changes to player storage as its only unserialized at load and serialized at save.
 
Great base for items upgrade system and race system :D

Example:
Sword only for dwarfs, +5 against orcs
 
Code:
        item:setSpecialAttribute("critical", 30, "dodge", 10)
        print(item:getSpecialAttribute("critical", "dodge")) -- prints 30 10

for me it returns nil, what can be a reason of that ?

item:setSpecialAttribute executes, i've checked it
 
Code:
        item:setSpecialAttribute("critical", 30, "dodge", 10)
        print(item:getSpecialAttribute("critical", "dodge")) -- prints 30 10

for me it returns nil, what can be a reason of that ?

item:setSpecialAttribute executes, i've checked it
Maybe it ssomething wrong with the attribute in the source, you did something wrong.

You can test it using some code to set/get the attribute like:
Code:
item:setAttribute(ITEM_ATTRIBUTE_SPECIAL, "test")
print(item:getAttribute(ITEM_ATTRIBUTE_SPECIAL))

If it prints test then I have no idea what may be wrong.
 
and the special attr can its in the item description when is put?
 
any example please?
Code:
function Player:onLook(thing, position, distance)
    local description = "You see " .. thing:getDescription(distance)
    if thing:isItem() then
        local attr = thing:getSpecialAttribute("critical")
        if attr then
            description = string.format("%s\nCritical: %d", description, attr)
        end
    end
    if self:getGroup():getAccess() then
        if thing:isItem() then
...
...
...
Similar for lookInTrade
 
Could you explain the benefits of storing this data in database rather than storing tables in storage values? I've been contemplating which method to use. Great script.
 
Could you explain the benefits of storing this data in database rather than storing tables in storage values? I've been contemplating which method to use. Great script.
You can't store strings in storages in TFS 1.2.

If you're using 0.x go for it, there is no difference, storage are also stored in the database.
 
Can you help?

4 errors were found during the analysis.

1 - Unrecognized data type. (Near "player_id" at position 35)
2 - A comma or a closing brace was expected. (Near "INT" at position 47)
3 - Unexpected start of the statement. (Near "11" at position 51)
4 - Type of instruction not recognized. (Near "NOT NULL" at position 55)

SQL Command:
CREATE TABLE `player_misc` (` player_id` INT (11) NOT NULL, `info` BLOB NOT NULL,` single player_id`, FOREIGN KEY (`player_id`) REFERENCES` players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = latin1

MySQL Messages:
# 1064 - You have a syntax error in your SQL next to `` player_id` INT (11) NOT NULL,
`Info` BLOB NOT NULL,
SINGLE KEY ('' on line 2
 
hi, this is really helpfull.

any idea why when i try to use a class in core folder it throws error in save and load special storage ?
sometimes i set the value with player:setSpecialStorage("key",value) but when i check the value it is still the same?

hope some one can help me!

thanks in advice!!
 
Can I ask why this?


Change:
return (type & 0x1EC) != 0;

To:
return (type & 0x8001EC) != 0;
 
Back
Top